用electron 打包發(fā)布集成vue2.0項(xiàng)目的操作過程
手里有個(gè)老項(xiàng)目是基于element admin框架下的,之前寫的時(shí)候沒考慮到要打包成桌面端,后期需要打包成客戶端,然后就開始了一些列版本操作,看著百度了都很簡單,把electron 加入到自己項(xiàng)目中各種不兼容,升級(jí)版本,改代碼各種百度,一個(gè)國慶假期就搞了這個(gè)事情,為了后面大家少踩點(diǎn)坑,打算詳細(xì)的寫寫我的踩坑之路還有版本配置(版本配置真的很有必要,不要嫌麻煩,一步一步走哈)
1.大家比較關(guān)注的版本配置表
node.js | v15.0.0 |
electron | V14.2.9 |
vue | 2.7.8 |
sass-loader | 8.0.2 |
1.如果環(huán)境中沒有安裝cnpm 建議安裝下,畢竟electron 用npm 安裝基本99% 是安裝失敗的,別太僥幸了,已經(jīng)走了很多遍了我(版本太高也會(huì)報(bào)錯(cuò))
npm install cnpm@7.1.0 -g
2.安裝 electron 環(huán)境
(如果 輸入 vue add electron-buider 沒反應(yīng)需要 vue/cli升級(jí)下這個(gè)東西)
(1).在終端輸入命令
Electron安裝 npm install electron -g Vue項(xiàng)目添加Electron-builder打包工具 vue add electron-builder
(2)設(shè)置鏡像方法(不配置也會(huì)報(bào)錯(cuò),什么githhub)
npm config edit
使用該命令會(huì)彈出npm的配置文檔,將以下類容復(fù)制到文件末尾。
electron_mirror=https://npm.taobao.org/mirrors/electron/ electron-builder-binaries_mirror=https://npm.taobao.org/mirrors/electron-builder-binaries/
3.測(cè)試下的代碼
npm run serve--網(wǎng)頁 npm run electron:serve--客戶端
4.打包命令:npm run electron:build
打包完成了之后,會(huì)出.exe
這個(gè)就很順利的操作了
我遇到的bug總結(jié)
打包好了之后啟動(dòng),發(fā)現(xiàn)后臺(tái)連不上,這個(gè)地方好像
不需要代理了。問就不知道啥原因
好不容易登錄上去了,發(fā)現(xiàn)路由不跳轉(zhuǎn)(真的暈死在廁所算了我)
好了好 了改個(gè)mode:hash 就ok了
還是點(diǎn)不動(dòng)還需要改改cookie:
const TokenKey = 'Admin-Token' // if (process.env.NODE_ENV === 'production') { // store = new Store() // } export function getToken() { return localStorage.getItem(TokenKey) } export function setToken(token) { return localStorage.setItem(TokenKey, token) } export function removeToken() { // if (process.env.NODE_ENV === 'production') { // return store.delete(TokenKey) // } return localStorage.removeItem(TokenKey) }
最后忘記了該有的background.js和preload 兩個(gè)文件代碼(放在src 文件夾底下)(這個(gè)有啥用呢,在package.json 文件中加入一句 "main": "background.js",)
import { app, protocol, BrowserWindow, ipcMain, Menu, dialog, globalShortcut } from 'electron' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'; import installExtension, { VUEJS3_DEVTOOLS } from "electron-devtools-installer"; const fs = require('fs') // 引入node原生fs模塊 const os = require('os') const isDevelopment = process.env.NODE_ENV !== 'production'; let mainWindow // Scheme must be registered before the app is ready protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }]); const path = require('path') const menus = [{ label: '視圖', submenu: [{ label: '刷新', role: 'reload' }, { label: '退出', role: 'quit' } ] }] const menu = Menu.buildFromTemplate(menus) function createWindow() { mainWindow = new BrowserWindow({ width: 800, height: 600, show: false, webPreferences: { enableRemoteModule: true, // 允許彈框 webSecurity: false, nodeIntegration: true, nodeIntegrationInWorker: true, // 在Web工作器中啟用了Node集成 preload: path.join(__dirname, 'preload.js'), defaultEncoding: 'utf-8' } }) mainWindow.once('ready-to-show', () => { mainWindow.show() }) if (process.env.WEBPACK_DEV_SERVER_URL) { // 開發(fā)環(huán)境 // Load the url of the dev server if in development mode mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL) if (!process.env.IS_TEST) mainWindow.webContents.openDevTools(); globalShortcut.register('CommandOrControl+Shift+i', function () { // 使用快捷鍵shift+ctrl+i 調(diào)起開發(fā)工具 mainWindow.webContents.openDevTools() }) } else { // 生產(chǎn)環(huán)境 // mainWindow.webContents.openDevTools() // 生產(chǎn)環(huán)境關(guān)閉調(diào)試工具 // Load the index.html when not in development createProtocol('app') // Load the index.html when not in development mainWindow.loadURL('app://./index.html') } Menu.setApplicationMenu(menu) } /** * 初始化 */ app.whenReady().then(() => { createWindow() app.setAppUserModelId('管理平臺(tái)') // 點(diǎn)擊MacOS底部菜單時(shí)重新啟動(dòng)窗口 app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) }) // 兼容MacOS系統(tǒng)的窗口關(guān)閉功能 app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } mainWindow = null }) // 最小化窗口(自定義導(dǎo)航條時(shí)) ipcMain.on('window-min', () => { mainWindow.minimize() }) // 最大化窗口(自定義導(dǎo)航條時(shí)) ipcMain.on('window-max', () => { // 如果已經(jīng)是最大化窗口就還原 if (mainWindow.isMaximized()) { mainWindow.restore(); } else { mainWindow.maximize() } }) // 關(guān)閉窗口 ipcMain.on('window-close', () => { mainWindow.close() mainWindow = null; app.exit(); }) // 主進(jìn)程給進(jìn)程通信 ipcMain.on('toMain', function (event, arg) { event.sender.send('fromMain', arg); // 返回給渲染進(jìn)程 }); // 下載進(jìn)程 ipcMain.on('downLoad', function (event, arg) { mainWindow.webContents.downloadURL(arg.url); }); // 調(diào)用文件讀入方法 ipcMain.on('judgeUse', function (event, arg) { // 讀入文件 // 異步返回 fs.readFile('./authorize.bin', { encoding: 'utf-8' }, (err, data) => { // if (err) { // // dialog.showMessageBox({ // // type: 'error', // // title: '找不到authorize.bin文件', // // message: err.path, // // buttons: ['ok'] // // }).then((index) => { // // if (index.response === 0) { // // mainWindow.close() // // mainWindow = null; // // app.exit(); // // } // // }) // event.sender.send('fromMain', null); // 返回給渲染進(jìn)程 // } else { // event.sender.send('fromMain', data); // 返回給渲染進(jìn)程 // } event.reply('authorizeBack', data); // 返回給渲染進(jìn)程 }) }); // 讀取本地服務(wù)的IP 地址 同步 ipcMain.on('syncGetLocalServer', function (event, arg) { // 讀入文件,同步返回?cái)?shù)據(jù) fs.readFile('./localServer.xml', { encoding: 'utf-8' }, (err, data) => { event.returnValue = data; // 返回給渲染進(jìn)程 }) }); // 讀取本地服務(wù)的IP 地址 異步 ipcMain.on('asyncGetLocalServer', function (event, arg) { // 讀入文件 // 異步返回 fs.readFile('./localServer.xml', { encoding: 'utf-8' }, (err, data) => { event.reply('asyncBackLocalServer', data); // 返回給渲染進(jìn)程 }) }); // 隱藏按鈕 ipcMain.on('hideMenu', function (event, arg) { mainWindow.setMenu(null); }); // 顯示按鈕 ipcMain.on('showMenu', function (event, arg) { mainWindow.setMenu(menu); }); app.on("ready", async () => { if (isDevelopment && !process.env.IS_TEST) { try { await installExtension(VUEJS3_DEVTOOLS); } catch (e) { console.error("Vue Devtools failed to install:", e.toString()); } } await createWindow(); }); // Exit cleanly on request from parent process in development mode. if (isDevelopment) { if (process.platform === 'win32') { process.on('message', data => { if (data === 'graceful-exit') { app.quit(); } }); } else { process.on('SIGTERM', () => { app.quit(); }); } }
import { contextBridge, ipcRenderer } from 'electron' import { autoUpdater } from 'electron-updater' window.ipcRenderer = ipcRenderer contextBridge.exposeInMainWorld('ipcRenderer', { // 異步向主進(jìn)程 發(fā)送消息 send: (channel, data) => { const validChannels = ['toMain', 'downLoad', 'judgeUse', 'hideMenu', 'showMenu', 'window-close', 'asyncGetLocalServer'] if (validChannels.includes(channel)) { ipcRenderer.send(channel, data) } }, // 同步向主進(jìn)程 發(fā)送消息, sendSync: (channel, data) => { const validChannels = ['syncGetLocalServer'] if (validChannels.includes(channel)) { return ipcRenderer.sendSync(channel, data) } }, // 異步接收主進(jìn)程返回的數(shù)據(jù) receive: async (channel) => { const validChannels = ['authorizeBack', 'asyncBackLocalServer'] if (validChannels.includes(channel)) { return new Promise((resolve) => { ipcRenderer.on(channel, (event, ...args) => { resolve(...args) }) }); } } }) // 檢測(cè)更新,在你想要檢查更新的時(shí)候執(zhí)行,renderer事件觸發(fā)后的操作自行編寫 ! function updateHandle() { let message = { error: '檢查更新出錯(cuò)', checking: '正在檢查更新……', updateAva: '檢測(cè)到新版本,正在下載……', updateNotAva: '現(xiàn)在使用的就是最新版本,不用更新', }; const uploadUrl = "http://61.4.184.177:7799/download/"; // 下載地址,不加后面的**.exe autoUpdater.setFeedURL(uploadUrl); autoUpdater.on('error', function (error) { sendUpdateMessage(message.error) }); autoUpdater.on('checking-for-update', function () { sendUpdateMessage(message.checking) }); autoUpdater.on('update-available', function (info) { sendUpdateMessage(message.updateAva) }); autoUpdater.on('update-not-available', function (info) { sendUpdateMessage(message.updateNotAva) }); // 更新下載進(jìn)度事件 autoUpdater.on('download-progress', function (progressObj) { mainWindow.webContents.send('downloadProgress', progressObj) }) autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) { ipcMain.on('isUpdateNow', (e, arg) => { console.log(arguments); console.log("開始更新"); //some code here to handle event autoUpdater.quitAndInstall(); }); mainWindow.webContents.send('isUpdateNow') }); ipcMain.on("checkForUpdate", () => { //執(zhí)行自動(dòng)更新檢查 autoUpdater.checkForUpdates(); }) }() // 通過main進(jìn)程發(fā)送事件給renderer進(jìn)程,提示更新信息 function sendUpdateMessage(text) { mainWindow.webContents.send('message', text) }
到此這篇關(guān)于用electron 打包發(fā)布集成vue2.0項(xiàng)目的文章就介紹到這了,更多相關(guān)electron 打包vue內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue表單提交點(diǎn)擊事件只允許點(diǎn)擊一次的實(shí)例
這篇文章主要介紹了Vue表單提交點(diǎn)擊事件只允許點(diǎn)擊一次的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10前端Vue3實(shí)現(xiàn)圖片標(biāo)點(diǎn)兩種方式總結(jié)
這篇文章主要介紹了如何使用Vue3和Ant?Design?Vue4.x實(shí)現(xiàn)圖像標(biāo)點(diǎn)和質(zhì)量檢測(cè)功能,文章詳細(xì)描述了兩種方式,每種方式都包括前端顯示代碼、配置基本數(shù)據(jù)、繪制圓點(diǎn)和序號(hào)以及處理圖片點(diǎn)擊的步驟,需要的朋友可以參考下2024-11-11在?Vue?項(xiàng)目中如何引用?assets?文件夾中的圖片(方式匯總)
Vue中引用assets文件夾中的圖片有多種方式,在.vue文件的模板部分,使用相對(duì)路徑或通過@別名引用圖片,在CSS中,通過相對(duì)路徑或@別名引用圖片作為背景,在JavaScript中,通過import語句導(dǎo)入圖片資源,并使用v-bind在模板中綁定顯示,這些方法均可有效管理和引用項(xiàng)目中的圖片資源2024-09-09vue打包部署到springboot的實(shí)現(xiàn)示例
項(xiàng)目開發(fā)中,一般我們都會(huì)使用SpringBoot+Vue進(jìn)行前后端開發(fā),本文主要介紹了vue打包部署到springboot的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07vue.js 使用axios實(shí)現(xiàn)下載功能的示例
下面小編就為大家分享一篇vue.js 使用axios實(shí)現(xiàn)下載功能的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看2018-03-03vue結(jié)合Axios+v-for列表循環(huán)實(shí)現(xiàn)網(wǎng)易健康頁面(實(shí)例代碼)
這篇文章主要介紹了vue結(jié)合Axios+v-for列表循環(huán)實(shí)現(xiàn)網(wǎng)易健康頁面,在項(xiàng)目下安裝axios,通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03