想要試試Electron ,不如看看這篇爬坑總結

前言

web端能作的事情不少,可是當涉及到操做系統的時候,可能就有點力不從心了。前段時間在開發一個web系統的時候,就遇到了相似的狀況。咱們須要獲取電腦操做系統的一些信息,好比mac地址等。咱們的web系統是徹底放在服務器上,經過瀏覽器來運行的,可是經過web端並不能直接實現咱們想要的效果。javascript

問題就是留給人們來解決的。通過同事之間的討論,由於系統自己並不複雜,並且要進行快速的開發。決定用Electron + 原web系統的頁面,來解決涉及操做系統信息的問題。html

這篇文章總結了我在使用Electron 時所遇到的一些問題和解決方法。前端

什麼是Electron?

使用 JavaScript, HTML 和 CSS 構建跨平臺的桌面應用——這是 Electron官網的簡介

Electron是GitHub開發的一個開源框架。它容許使用Node.js(做爲後端)和Chromium(做爲前端)完成桌面GUI應用程序的開發。Electron現已被多個開源Web應用程序用於前端與後端的開發,著名項目包括GitHub的Atom和微軟的Visual Studio Code。——知乎vue

能夠簡單的理解爲Electron爲web項目套上了Node.js環境的殼,使得咱們能夠調用Node.js的豐富的API。這樣咱們能夠用JavaScript來寫桌面應用,拓展不少咱們在web端不能作的事情。java

怎麼構建Electron應用?

構建Electron應用很簡單,能夠直接查看官方文檔,也能夠利用現有的輪子。基原本說能夠分爲兩大類:模板和命令行工具。這兩種方式都有各自的優勢,具體選用哪一種方式要根據本身實際的狀況來。就拿我來講,由於我要作的項目本來就有web端的頁面了,這些模板基本都不適用,爲了趕進度,就直接參考官網入門——打造你的第一個-electron-應用,再加上原有的代碼進行構建項目。node

下面爲一些經常使用的構建模板與命令行工具react

模板

命令行工具

一個例子

下面是一個最基礎的Electron項目,後續的代碼都是在此基礎上進行拓展。linux

npm install --save-dev electron

通常結構git

demo/
├── package.json
├── main.js
└── index.html

package.jsongithub

{
  "name": "demo",
  "version": "1.0.0",
  "description": "electornDemo",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "author": "xmanlin",
  "license": "MIT",
  "devDependencies": {
    "electron": "^9.0.0"
  }
}

main.js

const {app, BrowserWindow} = require('electron')

app.on('ready', function createWindow () {
    // 能夠建立多個渲染進程
    let win = new BrowserWindow({
        width: 800,
        height: 600,
    })
    
    win.show()

    // 渲染進程中的web頁面能夠加載本地文件
    win.loadFile('index.html')


    // 記得在頁面被關閉後清除該變量,防止內存泄漏
    win.on('closed', function () {
        win = null
    })


})

// 頁面所有關閉後關閉主進程,不一樣平臺可能有不一樣的處理方式
app.on('window-all-closed', () => {
    app.quit()
})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>demo</title>
</head>
<body>
    <div>一個electron項目</div>
    <script>
    
    </script>
</body>
</html>

什麼是主進程和渲染進程?

在Electron中,主進程和渲染進程的概念是十分重要的,具體能夠查看官網介紹:主進程和渲染進程

主進程

  • 運行package.json中的main腳本的進程是主進程。
  • 一個electron應用有且只有一個主進程。
  • 主進程能夠進行GUI相關的原生API操做。

渲染進程

  • Electron 使用了 Chromium 來展現 web 頁面,因此 Chromium 的多進程架構也被使用到。
  • 每一個web頁面運行在它本身的渲染進程中。
  • 使用BrowserWindow類開啓一個渲染進程並將這個實例運行在該進程中,當一個BrowserWindow實例被銷燬後,相應的渲染進程也會被終止。
  • 渲染進程中不能調用原生資源,可是渲染進程中一樣包含Node.js環境,因此能夠引入Node.js

模塊,在Node.js支持下,能夠在頁面中和操做系統進行一些底層交互。

渲染進程之中如何調用Node.js的API?

在Electron5.0版本後,渲染進程默認是不能調用Node.js的API的,通過設置後才能夠:

主進程(main.js)

let win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
        nodeIntegration: true,  //設置爲true就能夠在這個渲染進程中調用Node.js
    }
})

怎樣打開開發者工具?

Electron雖然是用了Chromium,可是想要打開開發者工具並非像瀏覽器同樣,如在windows下默認狀況直接按F12。

在Electron中有兩種方式打開開發者工具:

第一種是在主進程中進行設置,設置後,啓動項目,該渲染進程就默認打開了開發者工具

win.webContents.openDevTools();

第二種能夠在渲染進程窗口的菜單欄進行選擇View -> Toggle Developer Tools。(或者直接按照上面的快捷鍵進行操做)

electron 控制檯打印亂碼問題?

咱們可能在Windows的控制檯會出現中文亂碼的問題,當咱們在Windows的控制檯下輸入chcp,能夠查看到當前字符編碼,常見的gb2312的值是936,utf8的值是65001。這種狀況下只要對package.json進行設置就能解決。

"start": "chcp 65001 && electron ."

主進程和渲染進程之間如何通訊?

主進程和渲染進程之間能夠經過ipcRendereripcMain模塊通訊。

主進程主動向渲染進程發送消息

主進程(main.js)

//主進程向渲染進程發送消息,'did-finish-load':當導航完成時發出事件,onload 事件也完成
win.webContents.on('did-finish-load', () => {
    win.webContents.send('msg', '消息來自主進程')
})

渲染進程(index.html)

<script>
    const {ipcRenderer} = require('electron')
    ipcRenderer.on('msg', (event, message) => {
        console.log(message) // 消息來自主進程
    })
</script>

渲染進程主動向主進程發送消息

渲染進程(index.html)

const {ipcRenderer} = require('electron')
ipcRenderer.send('indexMsg','消息來自渲染進程')

主進程(main.js)

const {ipcMain} = require('electron')
ipcMain.on('indexMsg',(event,msg) => {
    console.log(msg) //消息來自渲染進程
})

渲染進程之間如何通訊?

渲染進程之間的通訊方式有不少種,下面列出幾種:

使用全局共享屬性

//主進程
global.sharedObject = {
  user: ''
}

//渲染進程一
const {remote} = require('electron')
remote.getGlobal('sharedObject').user = 'xmanlin'

//渲染進程二
const {remote} = require('electron')
console.log(remote.getGlobal('sharedObject').user) //xmanlin

ipcRenderer.sendTo()

下面是ipcRenderer.sendTo()的參數

ipcRenderer.sendTo(webContentsId, channel, [, arg1][, arg2][, ...])
ipcRenderer.sendTo(windowId, 'ping', 'someThing')
//webContentsId : Number
//channel : String
//...args : any[]

具體用法

主進程(main.js)

//建立一個新的渲染進程
let win2 =  new BrowserWindow({
    width: 800,
    height: 600,
})

//爲渲染進程設置惟一id
win2.id = 2

渲染進程1

<script>
    const {ipcRenderer} = require('electron')
    //向id爲2的渲染進程發送消息
    ipcRenderer.sendTo(2,'msg1','來自渲染進程1的消息')
</script>

渲染進程2

<script>
    const {ipcRenderer} = require('electron')
    ipcRenderer.on('msg1', (event, message) => {
        console.log(message) // 來自渲染進程1的消息
    })
</script>

利用主進程作消息中轉站

//主進程
ipcMain.on('msg1', (event, message) => {
  yourWindow.webContents.send('msg2', message);
}

//渲染進程1
ipcRenderer.send('msg1', '來自渲染進程1的消息')

//渲染進程2
ipcRenderer.on('msg2', (event, message) => {
    console.log(message)  //來自渲染進程1的消息
  }
)

如何對項目進行打包?

打包也是必不可少的一步,這裏介紹兩種比較成熟的打包工具:electron-packagerelectron-builder。這兩個工具主要是對其進行配置。

electron-packager

咱們能夠利用 electron-packager把咱們現有的electron應用打包爲exe可執行文件。

先進行安裝

npm install electron-packager --save-dev

安裝好以後要配置electron-packager的基本命令,下面爲官方文檔中的基本格式:

electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> [optional flags...]

簡要的介紹一下各個參數所表明的意思:

  • sourcedir:項目所在路徑
  • appname:應用名稱(打包後文件的名稱)
  • platform:肯定了你要構建哪一個平臺的應用(Windows、Mac 仍是 Linux)

    • platform=win32 表明Windows
    • platform=darwin 表明Mac
    • platform=linux 表明Linux
  • arch:決定了使用 x86 仍是 x64 仍是兩個架構都用
  • optional options:可選選項

下面爲一個例子,供參考

package.json

"scripts": {
    "build32": "electron-packager ./ appDemo --platform=win32 --arch=ia32  --out=./app --app-version=1.0.0 --overwrite --icon=./favicon.ico",
    "build64": "electron-packager ./ appDemo --platform=win32 --arch=x64  --out=./app --app-version=1.0.0 --overwrite --icon=./favicon.ico"
  }

上面都是打包Windows下的軟件,build32打包的爲32位,build64打包的爲64位。除基本參數外,上面其餘參數所表明的意義以下:

  • --out表示打包後生成的文件的目錄
  • --app-version表示打包生成文件的版本號
  • --overwrite表示刪除原有的打包文件,生成新的打包文件
  • --icon表示打包文件的圖標

electron-builder

electron-builder不只能夠打包爲exe可執行文件,還能夠打包爲可安裝程序,功能與electron-packager相比也要豐富一些。

官網更爲推崇yarn 來進行安裝

yarn add electron-builder --dev

固然npm也是能夠的

npm install electron-builder --save-dev

而後咱們能夠進行配置了

"scripts": {
  "pack": "electron-builder --dir",
  "dist": "electron-builder"
},
 "build": {
   "productName": "appDemo", // app中文名稱
   "appId": "appDemoId",// app標識
   "directories": { // 打包後輸出的文件夾
     "buildResources": "resources",
     "output": "dist/"
   }
   "files": [ // 打包後依然保留的源文件
     "dist/electron",
     "node_modules/",
     "package.json"
   ],
   "mac": { // mac打包配置
     "target": "dmg",
     "icon": "icon.ico"
   },
   "win": { // windows打包配置
     "target": "nsis",
     "icon": "icon.ico"
   },
   "dmg": { // dmg文件打包配置
     "artifactName": "appDemo.dmg",
     "contents": [
       {
         "type": "link",
         "path": "/Applications",
         "x": 410,
         "y": 150
       },
       {
         "type": "file",
         "x": 130,
         "y": 150
       }
     ]
   },
   "nsis": { // nsis文件打包配置
     "oneClick": false,
     "allowToChangeInstallationDirectory": true, // 容許修改安裝目錄
     "allowElevation": true, // 容許請求提高。 若是爲false,則用戶必須使用提高的權限從新啓動安裝程序。
     "installerIcon": "./build/icons/aaa.ico",// 安裝圖標
     "uninstallerIcon": "./build/icons/bbb.ico",//卸載圖標
     "installerHeaderIcon": "./build/icons/aaa.ico", // 安裝時頭部圖標
     "createDesktopShortcut": true, // 建立桌面圖標
     "createStartMenuShortcut": true,// 建立開始菜單圖標
     "shortcutName": "xxxx", // 圖標名稱
     "include": "build/script/installer.nsh", //包含的自定義nsis腳本這個對於構建需求嚴格得安裝過程至關有用。
   },
 }

在使用electron-builder打包時,也能夠指定參數

--mac, -m, -o, --macos   macOS打包
 --linux, -l              Linux打包
 --win, -w, --windows     Windows打包
 --mwl                    同時爲macOS,Windows和Linux打包
 --x64                    x64 (64位安裝包)
 --ia32                   ia32(32位安裝包)

所有參數可參考Command Line Interface (CLI)

關於NSIS,也能夠了解一下這種打包方式:electron 打包流程 electron-packager + NSIS

如何設置窗口默認最大化和全屏?

默認最大化

//主進程(main.js)
let win = new BrowserWindow({show: false})
win.maximize()
win.show()

默認全屏

//主進程(main.js)
let win = new BrowserWindow({fullscreen: true})

如何自定義菜單欄?

能夠直接參考這篇文章-使用 Electron 自定義菜單,寫的比較詳細,也能夠直接參考官方文檔來。固然咱們也能夠把自帶的菜單欄隱藏掉,而後本身調用寫Electron的API寫一個菜單欄。例如VSCode就是這麼作的,打開VSCode,而後在幫助裏面找到切換開發者工具,你可能會發現新世界~。

如何獲取操做系統mac地址?

這個主要是調用Node.js的API,就能夠獲取系統的mac地址。

var os=require("os");
//獲取mac地址
var mac = ''
var networkInterfaces=os.networkInterfaces();
for(var i in networkInterfaces){
    for(var j in networkInterfaces[i]){
        if(networkInterfaces[i][j]["family"]==="IPv4" && networkInterfaces[i][j]["mac"]!=="00:00:00:00:00:00" && networkInterfaces[i][j]["address"]!=="127.0.0.1"){
            mac = networkInterfaces[i][j]["mac"]
        }
    }
}

參考

https://www.electronjs.org/docs

https://blog.csdn.net/weixin_...

https://www.jianshu.com/p/62c...

https://blog.csdn.net/qq_3480...

https://segmentfault.com/a/11...

https://juejin.im/post/5cfd2e...

最後

這篇文章是我到目前爲止在學習並應用Electron時所遇到的問題以及所找到的解決辦法,但願對你們有所幫助。如有不足或錯誤的地方,歡迎指出~

相關文章
相關標籤/搜索