導航:
(一)Electron跑起來
(二)從零搭建Vue全家桶+webpack項目框架
(三)Electron+Vue+Webpack,聯合調試整個項目
(四)Electron配置潤色
(五)預加載及自動更新
(六)構建、發布整個項目(包括client和web)
摘要:整個項目就剩最后一哆嗦了,但僅僅是當作demo模版來說,實際項目的話,還有很多需要細化的地方。項目完整代碼:https://github.com/luohao8023/electron-vue-template,隨博客更新。
一、打包客戶端
首先是要改一下build.js,把上篇文章沒做的事兒給做了。
上篇文章已經構建出了可執行文件目錄app,這次我們要做的就是使用electron-builder把app目錄打包為安裝包。
在之前的基礎上引入electron-builder,然后對app目錄進行打包:
const builder = require('electron-builder'); // 在所有的打包邏輯執行完成之后,確認已經正確生成了app目錄 builder.build().then(() => { del(['./pack/*.yaml', './pack/*.blockmap']); // 為了方便,打包完成之后我們打開文件管理器 openFileManager(); }); function openFileManager() { // 打開文件管理器 let dirPath = path.join(__dirname, '..', 'pack'); if (process.platform === 'darwin') { spawn('open', [dirPath]); } else if (process.platform === 'win32') { spawn('explorer', [dirPath]); } else if (process.platform === 'linux') { spawn('nautilus', [dirPath]); } }
然后自信滿滿的開始打包。。。。
報錯了,說是什么描述缺失,icon沒有設置啥的,就是打包的時候沒有配置唄,去看下package.json文件,果然是少了build字段,package.json文件中的build字段就是有關打包的配置,一些必要的配置項還是要填的。
在package.json中增加build字段:
"build": { "asar": true, "productName": "Electron+vue+webpack模板", "appId": "com.electron.template", "copyright": "Copyright © template", "directories": { "output": "pack" }, "files": [ "app/**" ], "mac": { "identity": "com.electron.templat", "target": [ "dmg" ], "artifactName": "${productName}.${ext}", "icon": "main/favicon/favicon.icns" }, "dmg": { "title": "${productName}", "artifactName": "${productName}.${ext}", "icon": "main/favicon/favicon.icns" }, "win": { "legalTrademarks": "Copyright © template", "publisherName": "electron", "requestedExecutionLevel": "highestAvailable", "target": [ { "target": "nsis", "arch": [ "ia32" ] } ], "artifactName": "${productName}.${ext}", "icon": "main/favicon/favicon.ico" }, "nsis": { "oneClick": false, "allowToChangeInstallationDirectory": true, "perMachine": true, "allowElevation": true, "artifactName": "${productName}-安裝包-V${version}.${ext}", "runAfterFinish": true, "shortcutName": "Electron+vue+webpack-template" } },
現在我們來挨個解讀一下各個配置項都是什么意思,當然還有很多其他配置,這里不再額外介紹了。
asar:是否打包為asar文件,設置為true的話,相當於給你的代碼加密了一下,直接就是個.asar的文件,具體內容需要解密了之后才能看到;設置為false的話,不對你的代碼進行加密處理,也就是用戶安裝你的程序之后,找到安裝目錄,就能直接看到源碼,目錄結構跟你開發的時候是一樣的,不太安全,建議設置為true;
(node:96470) UnhandledPromiseRejectionWarning: Error: Application entry file "index.js" in the "/Volumes/SHARE/projects/github/electron-vue-template/pack/mac/Electron+vue+webpack模板.app/Contents/Resources/app.asar" does not exist. Seems like a wrong configuration.
還是有錯啊,說的很詳細,說是程序入口文件index.js不存在,我們看一下:
"name": "electron-vue-template", "version": "1.0.0", "description": "electron-vue-template", "main": "index.js", "scripts": { "dev": "node ./builder/dev.js", "build": "node ./builder/build.js" },
main字段就是程序入口,我們寫的是index.js,看下代碼目錄,我們的主進程入口是main.js,那就改一下吧,把index.js改為main.js,接着運行打包命令:
還是出錯呦,入口文件找不到,這個問題還真想來好大一會兒,感覺沒有錯啊,名稱也修改來,就是main.js啊,又瞅了眼代碼目錄才恍然大悟,這不陰溝里翻船嘛,通常情況下main.js是在工程根目錄的,但是我們規划完工程目錄之后,把main.js給打包到app目錄下了,所以入口字段應該填"app/main.js",接着運行打包命令,這次終於成功了,看下pack文件夾中生成的文件:
第一個dmg文件就是mac的安裝包,第二個yml文件記錄了程序的一些基本信息,mac文件夾下是一個免安裝的可執行程序,最后一個就是我們壓縮出來的小版本,windows下跟這個目錄不一樣。
先不着急安裝,打開mac文件夾下的可執行程序,可以直接打開我們的程序,打開之后懵了,一片空白啊,啥東西也沒有,趕緊找找原因。
打開app目錄發現,沒有生成update.html,經排查發現,上次提交的代碼有個地方寫錯了,拼錯了個單詞:
Promise.all([buildPreload(), buildRender()]).then(resolve => { resolve.forEach(log => { console.log('打包輸出===>', log); }); const outpath = path.join(__dirname, '../pack/'); try { fs.mkdirSync(outpath); } catch(e) { console.log('已創建pack文件夾', e); } console.log('打包渲染進程完畢!壓縮小版本!'); const zipPath = renderConfig.output.path; const fileName = setup.versionType + '-' + setup.version.join('.'); const filePath = path.join(zipPath, `../pack/${fileName}.zip`); compress(zipPath, filePath, 7 , (type,msg) => { if (type === 'error'){ Promise.reject('壓縮文件時出錯:' + msg); } else { console.log(`壓縮包大小為:${(msg / 1024 / 1024).toFixed(2)}MB`); } }); Promise.all([buildMain(), buildUpdate()]).then(resplve => { resolve.forEach(log => { console.log('打包輸出===>', log) }); builder.build().then(() => { del(['./pack/*.yaml', './pack/*.blockmap']); openFileManager(); }); }).catch(err => { console.error('打包【main】-【update】錯誤輸出===>', err); process.exit(2); }); }).catch(err => { console.error('打包【preload】-【render】出錯,輸出===>', err); process.exit(1); });
看一下,第二個Promise.all.then中,參數寫成了resplve,而在打印log的時候用的是resolve,偏偏上面有resovle,所以也沒報錯,但是第二次promise的log就全被吃了,趕緊改回來,再跑一下,果然有個錯誤:
打包輸出===> ModuleNotFoundError: Module not found: Error: Can't resolve 'css-loader' in '/Volumes/SHARE/projects/github/electron-vue-template':undefined
沒有css-loader,那就裝一個:
打包輸出===> ModuleNotFoundError: Module not found: Error: Can't resolve 'less-loader' in '/Volumes/SHARE/projects/github/electron-vue-template':undefined
又說沒有less-loader,再裝一個,運行命令,看到app目錄下生成了update.html,這下應該沒問題了吧。
打開mac文件夾下的免安裝文件,程序啟動后跟我們本地調試的效果是一樣的,再使用安裝包安裝一下,安裝完成打開后也是正常的。
好啦,打包客戶端就說到這兒了,下面說一下怎么使用同一套代碼打包web端。
二、打包web端
這里建議把打包web端的邏輯單獨拆出來,網站代碼是同一套,但是打包邏輯是兩套
dev的邏輯就是起個devServer返回html文件就行了,不再多說。
而打包的話是針對單頁面的,只會生成一個html文件,如果相針對每個路由都生成一個html文件,這里提供下思路:
引入路由文件,遍歷路由,拿到路徑,針對每個路徑,實例化一個HtmlWebpackPlugin,即可生成一個html文件:
webpackDevConfig.plugins.push(new HtmlWebpackPlugin({ template: './src/index.ejs', filename: `.${routerPah}`, title: "加載中...", inject: false, hash: true, minify: false, cache: false }))
在package.js中增加啟動命令:
"scripts": { "dev": "node ./buildClient/dev.js", "devweb": "node ./buildWeb/dev.js", "build": "node ./buildClient/build.js", "buildweb": "node ./buildWeb/build.js" }
分別調試和打包客戶端、web端。
這篇文章端內容就到這里了,具體的邏輯還是要去看代碼的。針對這套邏輯我們其實有已經上線了的產品的,很多細化的東西也有,但是不便拿出來說,也不好做成demo。模板中可能會有些冗余代碼,就是之前的邏輯沒有刪除干凈,自行優化就好了。
有什么問題歡迎留言討論。項目完整代碼:https://github.com/luohao8023/electron-vue-template。