把 Windows 版 Electron 应用搬到 deepin,不用 Wine 也能跑

2026-05-27 28 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:9 分钟

很多企业用 Electron 开发桌面软件,宣传语写的是"一次开发,三平台运行"。现实却很骨感——大量 Electron 应用只发布了 Windows 和 macOS 版本,Linux 用户要么等官方适配,要么自己折腾 Wine。Wine 兼容性参差不齐,字体渲染、输入法、文件关联经常出问题。

但 Electron 有一个结构性优势:应用逻辑打包在 ASAR 归档里,与底层 Electron 运行时(Chromium + Node.js)是分离的。这意味着只要拿到 ASAR 包,配上 Linux 版 Electron 运行时,就能让原本只有 Windows 版的应用在 deepin 上原生运行。下面一步步拆解怎么做。

Electron 应用的内部结构

先看一个典型 Windows 版 Electron 应用的目录布局:

MyApp/
├── MyApp.exe          # 主入口,本质是 Electron shell
├── resources/
│   ├── app.asar       # 应用逻辑(JS、HTML、CSS、图片等)
│   └── app.asar.unpacked/  # 无法打包进 asar 的外部文件
├── locales/           # Chromium 语言包
├── chrome_100_percent.pak  # Chromium 资源
├── icudtl.dat         # ICU 国际化数据
├── v8_context_snapshot.bin  # V8 快照
├── libGLESv2.so       # GPU 渲染库(Windows 版是 dll)
├── ...

关键发现:MyApp.exe 不过是个壳,真正的业务代码全在 resources/app.asar 里。asar 是一种类似 tar 的只读归档格式,Electron 启动时通过内置的 original-fs 模块读取它。

这就给了我们一条路:剥离 Windows 壳,换上 Linux 壳,内核不变

提取 ASAR 包

第一步,从 Windows 版安装目录拿到 app.asar。如果你手上有安装包(.exe 或 .msi),可以用以下方式提取:

# 方式一:如果已有 7z,直接解压安装包
7z x MyApp-Setup-1.2.3.exe -o./myapp_extracted

# 方式二:msi 包用 msiextract(deepin/Debian 可装 msitools)
sudo apt install msitools
msiextract MyApp-Setup-1.2.3.msi -C ./myapp_extracted

提取后,resources/app.asar 就是核心资产。接下来确认它的内容:

# 安装 asar 工具(Node.js 自带 npm)
npm install -g @electron/asar

# 列出 asar 内的文件树
asar list resources/app.asar | head -30

# 如果想查看入口文件确认 package.json 里的 main 字段
asar extract-file resources/app.asar package.json ./extracted_package.json
cat extracted_package.json

package.json 中的 main 字段指向应用启动入口,通常是 main.jsindex.js。确认这个值,后面启动命令要用。

换壳:配 Linux 版 Electron 运行时

现在需要一个与原应用 Electron 版本匹配的 Linux 运行时。版本号可以从 Windows 版的文件名或 package.json 中推断,也可以直接运行原 exe 用 process.versions.electron 查看(不过在 Linux 上跑 exe 就又回到 Wine 了,更实用的办法是看安装目录里的 LICENSE.electron.txt 或版本文件)。

假设原应用用的是 Electron 22.x,下载对应的 Linux release:

# 从 GitHub Electron Releases 下载(替换版本号)
ELECTRON_VER="22.3.27"
wget "https://github.com/electron/electron/releases/download/v${ELECTRON_VER}/electron-v${ELECTRON_VER}-linux-amd64.zip"

# 解压到运行时目录
mkdir -p ./electron-runtime
unzip electron-v${ELECTRON_VER}-linux-amd64.zip -d ./electron-runtime

deepin 基于 Debian,amd64 架构,所以选 linux-amd64。如果是 ARM 设备则换 linux-arm64

组装与启动

把 ASAR 包放进 Linux 运行时的 resources/ 目录:

# 复制 asar 包到运行时目录
mkdir -p ./electron-runtime/resources
cp resources/app.asar ./electron-runtime/resources/

# 如果原包有 app.asar.unpacked 目录,也要一并复制
cp -r resources/app.asar.unpacked ./electron-runtime/resources/ 2>/dev/null || true

启动应用:

# 直接用 electron 可执行文件启动,指定 app 目录
./electron-runtime/electron ./electron-runtime/resources/app.asar

如果原应用 package.jsonmain 字段指向的是相对路径(比如 ./dist/main.js),asar 内部会自动解析,不需要额外处理。

做成 deepin 桌面应用

命令行启动不够优雅,接下来创建一个 .desktop 文件,让应用出现在 deepin 的启动器里:

# 创建启动脚本
cat > ./myapp-launch.sh << 'LAUNCH_EOF'
#!/bin/bash
# 根据实际路径修改
ELECTRON_PATH="/opt/myapp/electron"
ASAR_PATH="/opt/myapp/resources/app.asar"

# 禁用 GPU 加速(某些 deepin 环境下可避免渲染问题,按需开启)
# exec "$ELECTRON_PATH" "$ASAR_PATH" --disable-gpu

exec "$ELECTRON_PATH" "$ASAR_PATH"
LAUNCH_EOF

chmod +x ./myapp-launch.sh

# 创建 .desktop 文件
cat > ./MyApp.desktop << 'DESKTOP_EOF'
[Desktop Entry]
Name=MyApp
Comment=从 Windows 移植的 Electron 应用
Exec=/opt/myapp/myapp-launch.sh
Icon=/opt/myapp/resources/app-icon.png
Type=Application
Categories=Utility;
StartupNotify=true
DESKTOP_EOF

# 安装到系统应用目录
sudo cp MyApp.desktop /usr/share/applications/
sudo mkdir -p /opt/myapp
sudo cp -r ./electron-runtime/* /opt/myapp/
sudo cp ./myapp-launch.sh /opt/myapp/

图标可以从 asar 里提取,也可以用原 Windows 版的 .ico 转换:

# 从 asar 中找图标(常见路径)
asar extract-file resources/app.asar assets/icon.png /opt/myapp/resources/app-icon.png

# 如果只有 .ico,用 ImageMagick 转换
convert original.ico -resize 256x256 app-icon.png

需要注意的坑

版本匹配是关键。原应用用 Electron 20 开发,你配 Electron 28 的运行时,大概率能跑,但遇到 API 变更或 Node.js 内置模块差异就可能崩溃。尽量用同版本运行时,至少同大版本号。

原生模块会出问题。如果原应用用了 node-gyp 编译的原生 .node 模块(比如 better-sqlite3keytar),Windows 版的 .dll 在 Linux 上无法加载。解决办法是重新编译这些模块的 Linux 版,然后替换进 asar:

# 解压整个 asar 以便修改
asar extract resources/app.asar ./app-extracted

# 在 app-extracted 目录下重新安装原生模块
cd app-extracted
npm rebuild better-sqlite3  # 需要对应版本的 Node.js headers
# 或
npm install better-sqlite3  # 全量重装

# 重新打包为 asar
cd ..
asar pack ./app-extracted ./electron-runtime/resources/app.asar

自动更新会冲突。很多 Electron 应用内置了 electron-updater,它会检查官方服务器并下载 Windows 版更新。移植后需要要么禁用自动更新,要么在 main.js 里拦截更新逻辑指向你自己的更新源。

文件路径差异。Windows 用反斜杠和盘符,Linux 用正斜杠。如果应用代码里硬编码了 C:\Users\... 这样的路径,在 Linux 上会找不到文件。asar 里的 JS 代码需要审查这类硬编码,用 path.join()app.getPath() 替代。

移植检查清单

动手之前,跑一遍这个清单能省不少排查时间:

检查项 方法 风险等级
Electron 版本号 package.jsonLICENSE.electron.txt 高——版本不匹配直接崩溃
是否有原生 .node 模块 asar list app.asar | grep '.node' 高——不重编译无法加载
是否硬编码 Windows 路径 asar extract 后搜索 C:\\\\Users 中——运行时文件读写失败
自动更新机制 搜索 electron-updaterautoUpdater 中——会覆盖你的移植版本
系统托盘 / 全局快捷键 BrowserWindowglobalShortcut 调用 低——deepin 桌面兼容性偶有问题
字体 / 渲染 首次启动观察界面 低——缺字体可装 fonts-noto-cjk

这套方法的本质是利用 Electron "壳 + 内容"的分离架构,把平台相关的壳换掉,保留平台无关的内容。它不是万能的——重度依赖原生模块或 Windows 专有 API 的应用还是得改代码。但对于大量只做 Windows/macOS 发布、内部逻辑纯 JS 的 Electron 应用来说,这条路的投入产出比远优于 Wine 方案。


相关推荐