日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > vue >内容正文

vue

electron打包vue-cli4项目的解决方案1(项目实测)

發(fā)布時間:2025/3/12 vue 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 electron打包vue-cli4项目的解决方案1(项目实测) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

背景:

項目已通過vue-cli4框架開發(fā)并運(yùn)行在nginx服務(wù)器上(使用了nginx的反向代理),現(xiàn)需要將該項目轉(zhuǎn)成桌面端應(yīng)用程序,選擇electron來實(shí)現(xiàn)。

設(shè)想2種解決方案:

1、使用electron-quick-start的loadURL方法讀取服務(wù)的線上url,需要做一個用戶URL輸入界面便于部署。vue服務(wù)的版本迭代部署都和該electron無關(guān);

2、vue-cli項目引入electron并取代nginx服務(wù)器的功用

?

electron簡介:

Electron 使用 web 頁面作為它的 GUI,所以你能把它看作成一個被 JavaScript 控制的,精簡版的 Chromium 瀏覽器。

Electron大家應(yīng)該不陌生了,它提供了一種解決方案,讓我們能夠利用Node.js 和 前端三寶 HTML + JS + CSS 來實(shí)現(xiàn)客戶端軟件。咋一聽感覺像NW.js。其實(shí)NW.js(node+websocket)可以算是Electron的前身了,都是出自同個作者之手。關(guān)于Electron和NW.js的區(qū)別官網(wǎng)上是這么說的。簡單講就是Electron優(yōu)化了NW.js中的一些不足。 秉著與時俱進(jìn)的態(tài)度,我們當(dāng)然要使用Electron。有了Electron作為容器,我們小前端就可以用HTML+JS+CSS來開發(fā)客戶端了。就像開發(fā)前端頁面一樣柔順。Electron的使用比較簡單,提供的API也比較清晰。核心概念就是Main Process 和 Render Process顧名思義Main Process是主進(jìn)程,用于運(yùn)行Electron的基本操作,如創(chuàng)建窗口,創(chuàng)建菜單等。Render Process是渲染進(jìn)程,我們需要在渲染進(jìn)程中創(chuàng)建軟件界面,每個渲染進(jìn)程對應(yīng)的是一個窗口,主進(jìn)程開啟了多個窗口就會有多個渲染進(jìn)程。

通俗解釋:electron使用nodejs將web應(yīng)用套了一層殼使之變成了桌面應(yīng)用electron官網(wǎng)

?

electron-quick-start快速啟動項目

下載?electron-quick-start?demo 或使用git clone后啟動

git clone https://github.com/electron/electron-quick-start cd electron-quick-start cnpm install //這里我用的是cnpm,npm太慢了 npm start

啟動成功效果

??

?

啟動流程:關(guān)注main.jspackage.jsonindex.html這幾個文件。從?package.json?文件看起,我們運(yùn)行?npm start 命令?其實(shí)是 運(yùn)行了?electron . 命令,該命令會從當(dāng)前目錄文件中尋找?package.json 文件,找到?package.json 文件?然后讀取?package.json 文件?中的?main 值main值?指向?main.js文件,然后運(yùn)行 man.js 文件找到index.html文件在主進(jìn)程創(chuàng)建應(yīng)用窗口,創(chuàng)建桌面應(yīng)用實(shí)例。

注意:

1、npm start命令中的 “chcp 65001”表示使用utf-8的編碼格式,解決console打印亂碼的問題

2、main進(jìn)程中“nodeIntegration”配置表示是否集成nodejs模塊

?

?

如何打包成exe桌面應(yīng)用程序

需求分析:loadURL方法讀取服務(wù)的線上url,但需要做一個URL輸入界面便于用戶輸入vue服務(wù)的地址,因?yàn)閘oadURL方法不管vue服務(wù)是否成功都會跳轉(zhuǎn),url無法訪問會導(dǎo)致electron打包后的桌面一片空白,所以盡量在loadURL跳轉(zhuǎn)頁面前加以判定

?

解決方案一

流程:

1、打包前需要確認(rèn)已安裝electron和electron-packager、jquery依賴

cnpm install electron --save-dev cnpm install electron-packager --save-dev //這個是打成exe文件的插件,之后要用,提前下載好 cnpm install jquery --save-dev

2、在package.json配置文件中修改啟動和打包命令

{"name": "electron-quick-start","version": "1.0.0","description": "A minimal Electron application","main": "main.js","scripts": {"start": "chcp 65001 && electron .", //utf8編碼格式,啟動"electron_exe":"electron-packager . --platform=win32 --arch=x64 --overwrite" , //覆蓋打包"electron_all":"electron-packager ./ notes --all --overwrite" //全平臺打包},"repository": {"type": "git","url": "git+https://github.com/electron/electron-quick-start.git"},"keywords": ["Electron","quick","start","tutorial","demo"],"author": "GitHub","license": "CC0-1.0","devDependencies": {"electron": "^11.2.0","electron-packager": "^15.2.0","jquery": "^3.5.1"},"bugs": {"url": "https://github.com/electron/electron-quick-start/issues"},"homepage": "https://github.com/electron/electron-quick-start#readme","dependencies": {"jquery": "^3.5.1" } }

?

3、在mian.js主進(jìn)程中創(chuàng)建窗口配置nodeIntegration允許使用nodejs功能。這里使用了ipcMain和ipcRender(主進(jìn)程和渲染進(jìn)程)通信,見后文或官網(wǎng)

// Modules to control application life and create native browser window var electron = require('electron'); var { app, BrowserWindow, Menu, ipcMain, globalShortcut } = require('electron') var path = require('path') var { dialog } = require('electron')var electronScreen = electron.screen; //window.screen 是一個預(yù)設(shè)值的 DOM 屬性, 所以這樣寫 var screen = require('electron').screen 將不會工作function createWindow() {var mainWindow = new BrowserWindow({ //創(chuàng)建窗口// frame:false, //無邊框width: 1400,height: 800,// fullscreen: true, //默認(rèn)全屏展示webPreferences: {nodeIntegration: true, //false則禁用Node.js的require模塊化引入preload: path.join(__dirname, 'preload.js'),enableRemoteModule: true, //遠(yuǎn)程模塊}})mainWindow.loadFile('index.html') //窗口讀取本地文件// 在開發(fā)環(huán)境和生產(chǎn)環(huán)境均可通過快捷鍵打開devToolsglobalShortcut.register('ctrl+F12', function () {if(mainWindow.webContents.isDevToolsOpened()){mainWindow.webContents.closeDevTools()}else {mainWindow.webContents.openDevTools() // 打開F12調(diào)試頁面}})//主進(jìn)程監(jiān)聽渲染進(jìn)程發(fā)過來的數(shù)據(jù)ipcMain.on('asynchronous-message', (event, arg) => {try {// console.log("主進(jìn)程收到有效數(shù)據(jù)-----", arg) // prints "ping"mainWindow.loadURL(arg)} catch (err) {console.error(err)mainWindow.loadFile('index.html')}})Menu.setApplicationMenu(null) // 關(guān)閉菜單欄.//快捷鍵全屏globalShortcut.register('ctrl+f11', () => {if(mainWindow.isFullScreen()){mainWindow.setFullScreen(false);}else {mainWindow.setFullScreen(true);}})}// This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.whenReady().then(() => {createWindow()app.on('activate', function () {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) {mouseTimer = null;createWindow()}})})// Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on('window-all-closed', function () {if (process.platform !== 'darwin') app.quit()mouseTimer = null; })

?

4、index.html中可能出現(xiàn)CSP的安全策略,Content-Security-Policy這里可以注釋掉了。

<!DOCTYPE html> <html><head><meta charset="UTF-8"><!-- 關(guān)閉內(nèi)容安全策略 --><!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --><!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"><meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'"> --><title>Hello Boy!</title><style>body {text-align: center;}.url-setting {height: 20%;min-height: 150px;font-size: 30px;}</style></head><body><h1>Hello World!</h1><hr><div class="url-setting"><input type="url" id="vueUrl" placeholder="格式如http://127.0.0.1:8080"><button id="linkBtn">進(jìn)入系統(tǒng)</button></div><script>//解決在electron-packager打包為exe時nodejs無法require加載jquery的問題window.$ = window.jQuery = require("./node_modules/jquery/dist/jquery.min.js");</script><script src="./renderer.js"></script> </body></html>

?

5、在renderer.js渲染進(jìn)程中使用nodejs的require引入jquery會在exe包運(yùn)行時報錯“$ not defined ”,所以在index.html中重新定義$,要注意jquery依賴的文件路徑是否能在打包好的electron項目下找到

// This file is required by the index.html file and will be executed in the renderer process for that window. // No Node.js APIs are available in this process because `nodeIntegration` is turned off. // Use `preload.js` to selectively enable features needed in the rendering process.// ipcRenderer 用于和主進(jìn)程通信 const ipcRenderer = require('electron').ipcRenderer; //const $ = require('jquery'); //盡管nodeIntegration設(shè)置允許繼承nodejs后可以正常啟動electron,但打包成exe時會報錯//使用 remote 模塊,可以調(diào)用主進(jìn)程對象的方法 const remote = require('electron').remote; const dialog = remote.dialog; const app = remote.app;//使用nodejs讀取本地文件數(shù)據(jù),安裝electron-store也可以存儲數(shù)據(jù),但響應(yīng)性能受較大影響//electron-store存儲數(shù)據(jù) // const Store = require('electron-store'); // const store = new Store(); // const currentUrl = store.get('serveUrl');const fs = require('fs')//jquery檢查連接的url服務(wù)是否有效,適用所有瀏覽器 $(document).ready(function () {// 執(zhí)行代碼var filePath = "./serveUrl.txt"if(app.isPackaged){ //app.isPackaged在生產(chǎn)模式則為truefilePath = "./resources/app/serveUrl.txt"}fs.readFile(filePath, function (error, data) { //if (error) {console.log('讀取文件失敗了',error)} else {$("#vueUrl").val(data.toString());}})function NetPing(pingUrl) {$.ajax({type: "GET",cache: false,url: pingUrl,data: "",success: function () {fs.writeFile(filePath, pingUrl,function (error) { //存儲用戶輸入的路徑if (error) {console.log('存儲URL失敗',error)}}) ipcRenderer.send('asynchronous-message', pingUrl); //異步將渲染進(jìn)程的數(shù)據(jù)傳給主進(jìn)程},error: function () {dialog.showErrorBox("錯誤提示", "無效網(wǎng)址,請重新輸入!")$("#vueUrl").val("");}});}//點(diǎn)擊連接vue前端服務(wù)$("#linkBtn").click(function () {let urlVal = $("#vueUrl").val();if(urlVal){NetPing(urlVal);}else {dialog.showErrorBox("錯誤提示", "網(wǎng)址不能為空,請重新輸入!")}}) });//接收主進(jìn)程的信息 ipcRenderer.on('asynchronous-reply', function (event, arg) {// console.log(arg); // prints "pong" });

注意:沒有使用electron-store存儲持久化數(shù)據(jù),而是使用nodejs讀存到本地文件serveUrl.txt上。引用本地文件時可以用app.isPackaged判斷是否是生產(chǎn)環(huán)境

?

6、啟動.\electron-quick-start\electron-quick-start-win32-x64成功

? ?

?

?

electron方案優(yōu)缺點(diǎn):

對比于Cocoa,Qt等傳統(tǒng)桌面客戶端技術(shù),基于前端技術(shù)的實(shí)現(xiàn)成本較低(C++牛請忽略)跨平臺支持更好(框架都幫你做好了),且天然支持熱更新。

由于Electron本身包含了chromium和Node.js的代碼, 所以不考慮項目本身體積,打包后的軟件最小仍然有100M+, 這也是Electron最為顯著的缺點(diǎn)之一。所以基本體積是無法避免的,我們只能盡量減小其他開發(fā)文件的大小,避免將一些無關(guān)包文件也打包進(jìn)去。為什么要強(qiáng)調(diào)這點(diǎn)呢?因?yàn)?strong>基于Node.js開發(fā)的項目往往會有一個龐大的node_modules文件夾,里面包含了一些開發(fā)和生產(chǎn)所用的包,也即對應(yīng)package.json中的dependencies和devDependencies。而devDependencies中的包是不需要打包到軟件的。這里推薦使用?electron-packager, 能自動排除dev依賴包,并支持自定義排除包文件夾。也可以打包出支持不同系統(tǒng)格式的軟件。

對于NW.js 有的大多數(shù)缺點(diǎn)Electron也有,其中一個通病就是性能問題,主要是渲染性能方面。基于webkit引擎來渲染UI界面,跟原生的系統(tǒng)UI還是有一定的差距。畢竟是基于DOM節(jié)點(diǎn)的渲染,每次節(jié)點(diǎn)的重排都是一次大的開銷。這點(diǎn)只能通過在前端框架中來優(yōu)化,比如利用Virtual DOM等相關(guān)技術(shù)。而視覺上的缺點(diǎn)則可以通過CSS做到竟可能接近原生控件。

?

electron主進(jìn)程和渲染進(jìn)程間通信:

Electron提供了IPC用于進(jìn)程間通信。分別是ipcMain和ipcRender。該通信機(jī)制允許ipcRender向ipcMain發(fā)送信號請求,并通過ipcMain返回數(shù)據(jù)。反回來ipcMain無法向特定的ipcRender發(fā)起請求。而且通信間傳遞的消息會被格式化為JSON字符串,所以并不支持在兩個進(jìn)程間傳遞句柄方法等,也就是不支持上下文傳遞。假如要實(shí)現(xiàn)在渲染進(jìn)程中點(diǎn)擊一個按鈕,則關(guān)閉客戶端窗口,可以通過ipcRender發(fā)送一個信號給ipcMain, ipcMain接收到該信號后調(diào)用Electron的API關(guān)閉窗口。對于類似這種比較簡單的指令操作,運(yùn)用IPC實(shí)現(xiàn)就可以了,但是如果操作比較復(fù)雜,并且需要傳遞復(fù)雜數(shù)據(jù)類型,則用IPC就行不通了。Electron提供了另一個API?remote,用于在Render Process中直接操作主進(jìn)程的方法。這樣就不需要移交Main Process處理,直接在前端頁面中調(diào)用Electron的API。

// In main process. const ipcMain = require('electron').ipcMain; ipcMain.on('asynchronous-message', function(event, arg) {console.log(arg); // prints "ping"event.sender.send('asynchronous-reply', 'pong'); });ipcMain.on('synchronous-message', function(event, arg) {console.log(arg); // prints "ping"event.returnValue = 'pong'; }); // In renderer process (web page). const ipcRenderer = require('electron').ipcRenderer; console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong"ipcRenderer.on('asynchronous-reply', function(event, arg) {console.log(arg); // prints "pong" }); ipcRenderer.send('asynchronous-message', 'ping');

?

?

解決方案二見下文

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的electron打包vue-cli4项目的解决方案1(项目实测)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。