🧑💻 寫在開頭
點贊 + 收藏 === 學會🤣🤣🤣
我本身是做 Web 開發的,最近需要寫個小工具,調用一些系統 API,就選擇了比較成熟的 Electron。結果業務代碼寫了三小時,環境配置、鏡像、文件引用、打包路徑、體積過大、文件被鎖定……各種問題卻折騰了將近三天。寫下這篇筆記,記錄這一路的坎坷。
第一難:官方文檔搭不起項目
按照官方説明初始化項目:
npm init npm install electron --save-dev
結果第一步就卡住了——裝不上。
初步猜測是網絡問題。雖然開梯子能解決,但不想一直掛着。查閲文檔後發現,Electron 在國內需要配置鏡像。
於是動手配置:
- 找到
.npmrc文件,路徑可通過npm config list查看user字段; - 加入鏡像地址:
electron_mirror=https://npmmirror.com/mirrors/electron/
小結
國內開發環境配置鏡像算是常規操作,只是初次接觸時容易讓人心煩。
第二難:引入 Vue 與 Vite
官方示例雖然能運行,但沒有熱更新,開發效率低。既然選擇了 Electron,自然要利用前端生態,於是決定引入 Vue 和 Vite,配合 vite-plugin-electron 替換原有結構。
思維方式需要轉變:原本是加載本地 HTML 文件,現在則要加載 Vite 啓動的本地服務:win.loadURL('http://localhost:3000')。
另一個問題是開發環境與生產環境的差異,需要引入環境變量。最終使用 cross-env 實現:
"dev": "cross-env NODE_ENV=development vite dev",
小結
邏輯上並不複雜,關鍵在於理解 Electron 分為主進程與渲染進程,最終前端跑的還是編譯後的 HTML 與 JS。理清整個流程後,內部實現就可以靈活替換。
第三難:如何調試?
頁面跑起來了,但怎麼打開開發者工具?後端代碼如何打斷點?
首先在創建 BrowserWindow 時加上:
win.webContents.openDevTools({ mode: 'detach' })
這樣啓動時就會自動打開調試工具。如果不小心關掉了,還可以用 Ctrl + Shift + I 重新打開。
主進程調試需要在 VSCode 中配置 launch.json,雖然不復雜,但配置起來略繁瑣:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Electron with Vite",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"windows": {
"runtimeExecutable": "npm.cmd"
},
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"skipFiles": ["<node_internals>/**"],
"env": {
"NODE_ENV": "development",
"ELECTRON_IS_DEV": "true"
}
},
{
"name": "Attach to Renderer",
"type": "chrome",
"request": "attach",
"port": 9223,
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/src/renderer",
"sourceMaps": true,
"sourceMapPathOverrides": {
"/@fs/*": "${webRoot}/*",
"/@id/*": "${webRoot}/*",
"/src/*": "${webRoot}/*",
"/node_modules/.vite/*": "${webRoot}/node_modules/*"
}
}
],
"compounds": [
{
"name": "Debug Main + Renderer",
"configurations": ["Debug Electron with Vite", "Attach to Renderer"]
}
]
}
同時 Vite 配置也要配合調整端口與調試參數。
小結
前端調試工具的打開方式藏在文檔深處,最後還是靠博客文章才找到;主進程調試則要配置 VSCode 和 Vite 插件,整套流程配下來,比寫業務邏輯還耗時。
第四難:electron-forge 打包初體驗
一開始使用的是官方推薦的 electron-forge,但體驗並不理想:
- 直接生成 exe,沒有安裝引導,也沒有卸載入口;
- 雙擊直接運行,還會附帶一個無説明的更新進程;
- 配置引導進程不生效;
- 內存佔用高達 600MB,明顯是把 node_modules 全打包了;
- 中文文件名在安裝後變成亂碼;
- 打包時 asar 文件被佔用,必須殺掉所有 Electron 進程才能繼續。
小結
或許是我沒配置對,但整體使用體驗確實不佳。
第五難:electron-builder 打包卡在下載
於是換用 electron-builder,結果打包時卡在三個依賴包的下載:
- winCodeSign-2.6.0
- nsis-3.0.4.1
- nsis-resources-3.4.1
又是網絡問題。有兩種解決辦法:
手動下載並放置緩存
將下載的包解壓到以下路徑:
C:\Users\15034\AppData\Local\electron-builder\Cache\winCodeSign\winCodeSign-2.6.0 C:\Users\15034\AppData\Local\electron-builder\Cache\nsis\nsis-3.0.4.1 C:\Users\15034\AppData\Local\electron-builder\Cache\nsis\nsis-resources-3.4.1\plugins
配置鏡像
在 .npmrc 中加入:
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
第六難:打包流程未完成
打包過程沒有報錯,但 release 文件夾沒有生成,流程未完整執行。
排查後發現,主進程入口不是 ./dist/main/main.js,而是由 Vite 插件控制的 ./dist-electron/main.js。
小結
入口路徑的理解偏差,讓成功只差一步,卻耗費不少時間。
第七難:打包時文件被佔用
又遇到文件佔用錯誤:
EBUSY: resource busy or locked, unlink '.../dist/win-unpacked/resources/app.asar'
原因是 vite build 和 electron-builder 同時操作 dist/ 目錄,導致文件被鎖定。
解決方案是讓它們使用不同的輸出目錄。修改 Vite 配置:
outDir: fileURLToPath(new URL('./renderer-dist', import.meta.url))
同時調整 electron-builder.config.js 中的 files 配置:
files: ['renderer-dist/**/*', ...]
但打包後仍然沒有生成 release 文件夾,日誌顯示輸出在 dist\electron-deploykit Setup 0.0.1.exe,似乎配置文件未生效。
檢查 dist\builder-effective-config.yaml,確認配置未加載。嘗試修改配置文件名、加入日誌打印、甚至回退版本,均無效。
最後將配置文件改為 electron-builder.config.yml,居然成功了。
第八難:包體積過大
一個簡單頁面打包後居然佔用了 700MB。
將 asar 設為 false 後,發現果然是 node_modules 被全部打包。於是在配置中將其排除:
files: - ./renderer-dist/**/* - ./dist-electron/**/* - ./package.json - '!./**/*.map' - '!node_modules/**/*'
第九難:ESM 與 CommonJS 模塊衝突
打包安裝後程序無法啓動,日誌顯示模塊引用錯誤。由於代碼被壓縮,難以定位問題。
取消壓縮後,發現是 const windowManager = require('/windowManager') 這種 CommonJS 寫法在 Vite 中不被支持。
Electron 官方示例使用 CommonJS,但 Vite 默認使用 ESM。最終將所有模塊改為 ESM 寫法。
也可嘗試使用 vite-plugin-commonjs 插件轉換,但我沒有實際驗證。
第十難:preload.js 未被打包
開發環境運行時出現錯誤:
Unable to load preload script: D:\code\DeployKit\electron-DeployKit\preload.js Error: ENOENT: no such file or directory, open 'D:\code\DeployKit\electron-DeployKit\preload.js'
檢查發現 dist-electron 下沒有 preload.js。
於是在 Vite 配置中加入自定義插件,手動複製 preload 文件:
function copyPreloadPlugin() {
return {
name: 'copy-preload',
closeBundle() {
const src = fileURLToPath(new URL('./src/main/preload.js', import.meta.url))
const destDir = fileURLToPath(new URL('./dist-electron', import.meta.url))
const dest = join(destDir, 'preload.js')
if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true })
copyFileSync(src, dest)
console.log('✅ Copied preload.js to dist-electron')
}
}
}
在 plugins 中啓用:
plugins: [
// ...
copyPreloadPlugin()
]
備註
Electron 主進程可以使用 ESM,但 preload.js 必須使用 CommonJS(require),並且必須確保它被正確複製到輸出目錄。
其他
powershell 不能執行npm 命令
由於powershell 執行策略限制不能執行npm命令
解決方案:修改策略
- 在打開的窗口中,你可以先輸入
Get-ExecutionPolicy查看當前策略,通常會是Restricted(禁止所有腳本)。 - 然後輸入核心命令:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser。 - 完成後,可以再次輸入
Get-ExecutionPolicy檢查是否已變為RemoteSigned,此時就可以執行命令了。
總結
Electron 在開發環境下邏輯清晰,編寫方便;但打包、工具鏈配置等方面卻相當繁瑣,相當於手動組裝一套完整的構建流程。