electron-vue不要再用了画髓,版本太老作者也不更新宦赠,而且electron11.0才開始支持Apple Silicon(m1)機型。
近期我自己也在開發(fā)一些electron + vue的跨平臺項目,本文主要記錄一下新起一個項目的時候需要安裝哪些工具與步驟
安裝系統(tǒng)全局組件Vue CLI用于創(chuàng)建vue項目
npm install -g @vue/cli
創(chuàng)建標準化Vue項目
vue create vueapp
然后根據Vue CLI提示選擇自己的常用工具并建立一個vue網站項目
具體步驟
添加electron插件
首先進入剛才建好的vueapp文件夾樟遣,安裝以下插件
vue add electron-builder
然后選擇最新的版本雕憔,等待安裝完成即可姿骏。
這里可能會非常慢,最終導致超時失敗斤彼。這是因為需要根據系統(tǒng)來下載electron的基礎庫分瘦,由于網絡原因,建議此處使用設置npm proxy來進行下載琉苇。不建議使用其他鏡像源下載嘲玫,可能會導致最終打包失敗,遇到過好幾次問題了并扇。
npm config set proxy http://127.0.0.1:58592
npm config set https-proxy http://127.0.0.1:58592
還有一種方式是把electron的源換成淘寶的:
npm config set registry https://registry.npmmirror.com
npm config set ELECTRON_MIRROR https://npmmirror.com/mirrors/electron/
啟動項目查看是否正常
此時項目src文件夾下就多了一個background.js去团,這里就是electron主進程相關代碼,負責和我們的vue頁面(渲染進程)進行交互穷蛹。
執(zhí)行以下代碼啟動項目
npm run electron:serve
此時應當能彈出一個應用程序界面土陪,并且還有我們熟悉的Vue:
可喜可賀!你可以正常開發(fā)了俩莽,添加npm插件就正常使用npm install xxx即可旺坠。
如果此時出現electron安裝錯誤請重新安裝的提示,那么就按以下步驟操作issue:
- 在node_modules\electron文件夾下新建一個path.txt
- txt中寫入:electron.exe
- 前往https://npmmirror.com/mirrors/electron/根據自己的版本下載對應平臺的zip包
- 將zip包解壓到node_modules\electron\dist 這樣即可修復安裝錯誤問題扮超。
進行一些必要配置
- electron升級
由于剛才安裝的electron版本已經過低取刃,我們需要先進行升級蹋肮。
在命令行中卸載當前electron:
npm uninstall electron
然后安裝最新的electron和remote模塊:
npm install -S electron
npm install -S @electron/remote
【可選步驟】由于vue-cli-plugin-electron-builder已經長年不更新了,在electron20+璧疗、mac系統(tǒng)上具有大量兼容性bug坯辩,因此需要升級到3.0.1(這個庫可能對element兼容不太好,會丟字體):
@matthijsburgh/vue-cli-plugin-electron-buildernpm install -D @matthijsburgh/vue-cli-plugin-electron-builder
另外需要注意崩侠,background.js中引用createProtocol也要更改為這個包:
import { createProtocol } from '@matthijsburgh/vue-cli-plugin-electron-builder/lib'
然后進行electron配置漆魔,background.js:
//background.js
//文件頭部,引用增加ipcMain用于通信
import { app, protocol, BrowserWindow, ipcMain } from 'electron'
import { createProtocol } from '@matthijsburgh/vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
//窗口啟動增加選項
const win = new BrowserWindow({
width: 800, //窗口默認寬度
height: 600, //窗口默認高度
useContentSize: false,
frame: true, //取消window自帶的關閉最小化等
resizable: false, //禁止改變主窗口尺寸
transparent: false, //透明
hasShadow: true, //窗口陰影
maximizable: true, //是否允許最大化
webPreferences: {
enableRemoteModule:true, //在渲染進程啟用remote模塊
nodeIntegration: true, //在渲染進程啟用Node.js
contextIsolation:false,
webSecurity: false,
backgroundThrottling: false, //程序在最小化時渲染進程不凍結
}
})
//由于渲染進程中electron.remote已廢棄却音,需要手動引入改抡,并在每一個browserwindow中啟用remote
require('@electron/remote/main').initialize()
require("@electron/remote/main").enable(win.webContents);
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
- Vue相關配置,這樣就可以在使用electron的API系瓢,main.js:
//main.js
const electron = window.require('electron') //引用electron
const fs = window.require('fs') //引用Node模塊fs
const remote = window.require('@electron/remote') //引用remote模塊用于通信阿纤、打開文件彈框等
Vue.prototype.$electron = electron
Vue.prototype.$fs = fs
Vue.prototype.$remote = remote
具體頁面中,xxx.vue:
//在頁面中使用相關API
this.$electron.ipcRenderer.sendSync('testMsg',data); //與主進程通信
this.$remote.getCurrentWindow().minimize(); //最小化窗口
this.$fs.existsSync("C:/test.js"); //調用nodejs方法查找文件是否存在
3.添加必要文件
- gitignore忽略輸出文件夾build夷陋、dist_electron
// .gitignore
/build
/dist_electron
- 新建vue.config.js欠拾,添加打包相關配置項,具體配置的作用在electron-builder官網有詳細說明骗绕,下文請自行替換appid藐窄、name之類的字段
module.exports = {
pluginOptions: {
electronBuilder: {
"customFileProtocol": "./", //增加此項讓css中相對引用的文件能正常訪問,否則一些css庫中的字體會無法顯示
"builderOptions": {
"extraResources": [
"./extraResources/**", //這里指定外部資源文件夾酬土,你可以把一些外部程序放在./extraResources中荆忍,比如ffmpeg等,打包時electron將直接原樣拷貝
"./node_modules/@electron/remote/**"诺凡,//必須添加這一行否則remote會引用不到
],
"productName": "your app name",
"appId": "your.app.appId",
"copyright":"Copyright ? your name 2021",// 版權信息
"directories": {
"output": "./build" //輸出文件夾
},
"afterSign": "./notarize.js", //簽名文件
"dmg": { //輸出mac的dmg時圖標位置
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
]
},
"mac": {
"icon": "./icons/icon512.icns",//mac圖標东揣,必須至少包含512*512尺寸的圖標
"target":[{
"target": "dmg", //設置輸出dmg安裝包
"arch": ["arm64", "x64"], //arm64是apple silicon機器專用的包;x64是intel版的包腹泌,兩種電腦都能用嘶卧,不過x64運行啟動會慢一點;這里你可以填universal凉袱,這樣會生成一個arm64+x64打出來然后裝一起的一個包(體積也是兩種應用之和)芥吟,運行時會自動選擇版本
}],
"identity": "your name",
"entitlements": "./entitlements.mac.plist", //簽名必須
"entitlementsInherit": "./entitlements.mac.inherit.plist",//簽名必須
"entitlementsLoginHelper": "./entitlements.mas.loginhelper.plist"专甩,//如果需要mac的mas版打包钟鸵,則需要此項
},
"win": {
"icon": "./icons/icon256.ico",//win打包圖標
"target": [{
"target": "nsis",// 利用 nsis 制作安裝程序
"arch": [
"x64",//64 位
]
}]
},
"nsis": {
"oneClick": false, // 是否一鍵安裝
"allowElevation": true, // 允許請求提升. 如果為 false, 則用戶必須使用提升的權限重新啟動安裝程序.
"allowToChangeInstallationDirectory": true, // 允許修改安裝目錄
"installerIcon": "./icons/icon256.ico",// 安裝圖標
"uninstallerIcon": "./icons/icon256.ico",// 卸載圖標
"installerHeaderIcon": "./icons/icon256.ico", // 安裝時頭部圖標
"createDesktopShortcut": true, // 創(chuàng)建桌面圖標
"createStartMenuShortcut": true,// 創(chuàng)建開始菜單圖標
"shortcutName": "DNG自動轉換工具", // 圖標名稱
"perMachine": true
},
}
}
},
configureWebpack: config => {
return {}//webpack相關配置
}
}
- 項目下新建icons文件夾用于存放圖標,內部放置至少2個圖標,分別為mac的icon512.icns和用于win的icon256.ico,打包時要用到漫玄。從普通圖片創(chuàng)建圖標可以使用IconWorkshop荆萤。
- 項目下新建extraResources文件夾,里面存放需要使用的外部程序澡罚,比如ffmpeg等顶瞒。electron在打包時將不會編碼該文件夾下的文件血筑,直接原樣拷貝害幅,安裝時也會直接放置于安裝目錄中消恍。
- 接下來,如果你是mac以现,需要打包成dmg安裝包狠怨,則需要安裝這個@electron/notarize (electron-notarize已廢棄)
//安裝公證組件
npm install @electron/notarize --save-dev
項目下新建.env文件,這里存放在mac開發(fā)者中心成為開發(fā)者時你的appleID及蘋果提供相關密碼邑遏,注意這個密碼不要寫你的appleID密碼佣赖,可以在蘋果賬號中心中手動添加一個app專用密碼,填寫在這里记盒。teamId是你apple開發(fā)者賬號下找到茵汰。也可以使用鑰匙串,具體參見此文mac下electron簽名及公證教程
//.env
appleId=youraccount@test.com
appleIdPassword=xxxx-xxxx-xxxx-xxxx
teamId=xxxxx
項目下新建entitlements.mac.plist文件孽鸡,固定寫死,直接拷(編譯arm64的應用時栏豺,務必添加com.apple.security.cs.allow-jit權限彬碱,否則程序很可能崩潰)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
</dict>
</plist>
項目下新建notarize.js文件,固定寫死奥洼,直接拷
require('dotenv').config()
const {notarize} = require('@electron/notarize')
exports.default = async function packageTask (context) {
const appName = context.packager.appInfo.productFilename
const {electronPlatformName, appOutDir} = context
if (electronPlatformName !== 'darwin') {
return
}
let appPath = `${appOutDir}/${appName}.app`
let {appleId, appleIdPassword, teamId} = process.env
console.log("notarize")
console.dir({appleId, appleIdPassword, teamId})
return await notarize({
appPath,
appleId,
appleIdPassword,
teamId,
})
}
@electron/notarize使用的是notarytool巷疼,舊版altool的公證將會在2023年11月停止訪問。新版工具將會訪問aws的地址灵奖,很可能連不上嚼沿,需要自行準備魔法
打包你的App
按上面的操作一步步來的話應該已經可以打包成exe或者dmg了
npm run electron:build
打包這一步也會非常慢,同樣是墻的問題瓷患,請不要使用cnpm骡尽,而是用本文一開始的set proxy方式
npm config set proxy http://127.0.0.1:58592
npm config set https-proxy http://127.0.0.1:58592
如果還是出現這種網絡原因導致的報錯: Get "https://github.com/electron-userland/electron-builder-binaries/releases/download/winCodeSign.7z" A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
可以手動進入提示上的網址將文件下載下來并解壓
- nsis和nsis-rescources放置到 C:\Users\username\AppData\Local\electron-builder\Cache\nsis中;
- winSodeSign放置到 C:\Users\username\AppData\Local\electron-builder\Cache\winSodeSign中
- electron-vx.x.x-win32-x64.zip放置到 C:\Users\username\AppData\Local\electron\Cache中
開發(fā)相關坑點解讀 Electron 常見問題
1. 無法使用require引用
當你在項目中使用require引用一些模塊(比如jQuery)擅编,會導致Uncaught TypeError: $ is not a function
這個問題是的直接原因是require無法引用攀细,根本原因node中的require覆蓋了webpack的require,這就導致了打包失敗
- 解決方案一:
在渲染進程中禁用Node.js爱态。在主進程background.js中谭贪,將nodeIntegration選項設置為false
//background.js
const win = new BrowserWindow(
webPreferences: {
nodeIntegration: false //該選項在渲染進程中禁用Node.js
}
})
這樣就可以正常使用require了。副作用是無法訪問一些底層的參數比如__dirname锦担,當引用的組件使用這些參數時會報錯俭识。
- 解決方案二:
當不可避免的想要使用Node.js時,比如想引用fs來讀取某個文件洞渔,那么在主進程background.js中套媚,將nodeIntegration選項設置為true
//background.js
const win = new BrowserWindow(
webPreferences: {
nodeIntegration: true //該選項在渲染進程中啟用Node.js
}
})
在require組件時缚态,必須在main.js中引用,并且必須使用window.require
//main.js
const electron = window.require('electron')
Vue.prototype.$electron = electron
這樣就可以在頁面中通過this.$electron訪問到electron的API了
- 解決方案三
將require重命名凑阶。在index.html中添加以下代碼猿规,放置在所有script標簽之前
<!-- index.html -->
<script>
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
</script>
然后就可以在main.js中使用nodeRequire 引用模塊了(不能在頁面中使用)
//main.js
const fs = nodeRequire('fs')
Vue.prototype.$fs = fs
//App.vue
this.$fs.existsSync("C:/test.js")
2. 在mac下,啟動項目時會報一個fsevents的錯誤:
ERROR Failed to compile with 1 errors
error in ./node_modules/fsevents/fsevents.node
Module parse failed: Unexpected character '?' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process his file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
@ ./node_modules/fsevents/fsevents.js 13:15-41
@ ./node_modules/chokidar/lib/fsevents-handler.js
@ ./node_modules/chokidar/index.js
@ ./src/background.js
@ multi ./src/background.j
fsevents是mac系統(tǒng)的一個必須要有的二進制模塊宙橱,如果你想開發(fā)跨平臺程序姨俩,一定繞不開他。
這個報錯的原因是fsevents.js中使用了require师郑,導致項目無法啟動环葵。
需要點擊./node_modules/fsevents/fsevents.js 13:15,找到該文件13行代碼宝冕,按照下文修改即可
// ./node_modules/fsevents/fsevents.js
const Native = require("./fsevents.node")
//更改為
const Native = window.require("./fsevents.node")
3. 在mac下张遭,electron-builder打包項目時會報一個ENOENT的錯誤:
spawn /usr/bin/python ENOENT
產生原因是macos ventura中移除了python2,因此electron-builder在打包dmg時將無法讀取這個地址地梨。
解決方案:卸載默認的vue-cli-plugin-electron-builder2.0.0菊卷,安裝 @matthijsburgh/vue-cli-plugin-electron-builder 即可。
我們也采用手動安裝的方式解決宝剖。
打開終端洁闰,使用conda創(chuàng)建一個python2.7的環(huán)境
conda create -c 'https://repo.continuum.io/pkgs/free/osx-64' -n py2 python=2.7
這里沒有直接conda create -ns是因為新版anaconda已無法搜索到py2.7,因此需要手動指定channel万细,否則會提示“ackagesNotFoundError: The following packages are not available from current channels python=2.7”
創(chuàng)建完成后進入anaconda圖形界面扑眉,找到py27的環(huán)境,打開terminal赖钞,運行以下代碼找到你的python2.7執(zhí)行文件的地址
which python
# /Users/mordom/anaconda3/envs/py2/bin/python
記下這個地址腰素,稍后將會用到
回到我們的electron項目的地址,定位到以下兩個文件
/node_modules/vue-cli-plugin-electron-builder/node_modules/dmg-builder/out/dmg.js
/node_modules/dmg-builder/out/dmg.js
前者找到261行:
await builder_util_1.exec(process.env.PYTHON_PATH || "/usr/bin/python", [path.join(dmgUtil_1.getDmgVendorPath(), "dmgbuild/core.py")], {
cwd: dmgUtil_1.getDmgVendorPath(),
env,
});
將這里的"/usr/bin/python"替換為我們剛才記錄下的地址"/Users/mordom/anaconda3/envs/py2/bin/python"雪营,這樣在打包時electron-builder將調用我們手動下載的python2.7了弓千。
后者同樣搜索“/usr/bin/python”,并替換為我們的地址即可卓缰。
至此問題解決计呈。
4.打包后在部分windows系統(tǒng)上出現白屏閃退問題
該問題由chromium的沙盒機制造成,詳細見進程沙盒化
解決方案
//background.js
import { app } from 'electron'
app.commandLine.appendSwitch('--no-sandbox'); //該行應在app.on('ready')前面執(zhí)行