前言 在 Node.js 盛行的年代,使用 JavaScript 開發各種應用程式不在話下,隨著 Electron 套件的推出,讓前端工程師不須學習額外語言,即可撰寫跨平台桌面應用程式。除此之外,由於 Electron 桌面應用程式是使用 html/css/js 來建立,所以我們可以整合其他前端框架 (React /Vue /Angular 等) 作為應用程式 UI 開發工具。這裡要分享的是如何建立基於 React 的 Electron 開發環境,並詳細記載最重要的打包步驟。
React + Electron 實際專案
環境
建立開發環境 CRA 首先建立 React 專案 (CRA, Create React App)
1 npx create-react-app react-based-electron
npx
:使用 create-react-app
套件,但不將該套件下載到本地端。
react-based-electron
:此為 CRA 的專案名稱,可任意更改。
Electron 相關套件 安裝開發 Electron 桌面應用程式時所需套件
1 2 3 4 5 cd react-based-electronnpm install --save-dev electron npm install --save electron-is-dev npm install --save wait-on
main.js/preload.js 於專案根目錄建立兩個檔案,分別為 Electron 的進入點 main.js
(內容如下) 與 preload.js
(空白檔案)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 const { app, BrowserWindow } = require ('electron' )const path = require ('path' )const isDev = require ('electron-is-dev' );function createWindow () { const mainWindow = new BrowserWindow ({ width : 800 , height : 600 , webPreferences : { preload : path.join (__dirname, 'preload.js' ) } }) if (isDev) { mainWindow.loadURL ('http://localhost:3000/' ); mainWindow.webContents .openDevTools () } else { mainWindow.loadFile ('./build/index.html' ); } } app.whenReady ().then (() => { createWindow () app.on ('activate' , function ( ) { if (BrowserWindow .getAllWindows ().length === 0 ) createWindow () }) }) app.on ('window-all-closed' , function ( ) { if (process.platform !== 'darwin' ) app.quit () })
入口點與啟動腳本 於 package.json
中加入 main
資訊與 homepage
資訊,將 Electron 入口點設為 main.js
。最後加上 Electron 的啟動腳本 electron-start
與修改 CRA 的啟動腳本 start
內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { "name" : "react-based-electron" , "version" : "0.1.0" , "private" : true , "homepage" : "." , "main" : "main.js" , "dependencies" : { ... } , "scripts" : { "start" : "set BROWSER=none && react-scripts start" , ... "electron-start" : "wait-on tcp:3000 && electron ." } , ... }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { "name" : "react-based-electron" , "version" : "0.1.0" , "private" : true , "homepage" : "." , "main" : "main.js" , "dependencies" : { ... } , "scripts" : { "start" : "export BROWSER=none && react-scripts start" , ... "electron-start" : "wait-on tcp:3000 && electron ." } , ... }
"start"
:BROWSER=none
讓 CRA 啟動的時候不要跳出瀏覽器。
"electron-start"
:wait-on tcp:3000
先等待 CRA 服務啟動,再執行 electron .
啟動桌面應用程式。
運行測試 開啟兩個 cmd
,一個用來啟動 CRA (npm run start
),另一個則是用來啟動 Electron (npm run electron-start
)。啟動沒有順序之分,因為我們專案使用 wait-on
套件協助等待 CRA 服務 (預設為 Port 3000) 運行起來,再執行 Electron 桌面應用程式
npm run start & electron-start
等待指令運行一小段時間,就會看到 Electron 桌面應用程式中顯示 CRA 預設畫面與瀏覽器的開發工具。到目前為止,已經正確建立基於 React 的 Electron 開發專案環境囉!接著便可以放心的開始使用 React 框架開發桌面應用了
基於 React 的 Electron 桌面應用程式運行
開啟兩個 terminal
,一個用來啟動 CRA (npm run start
),另一個則是用來啟動 Electron (npm run electron-start
)。啟動沒有順序之分,因為我們專案使用 wait-on
套件協助等待 CRA 服務 (預設為 Port 3000) 運行起來,再執行 Electron 桌面應用程式
npm run start & electron-start
等待指令運行一小段時間,就會看到 Electron 桌面應用程式中顯示 CRA 預設畫面與瀏覽器的開發工具。到目前為止,已經正確建立基於 React 的 Electron 開發專案環境囉!接著便可以放心的開始使用 React 框架開發桌面應用了
基於 React 的 Electron 桌面應用程式運行
打包應用程式 當我們桌面應用程式開發完成後,下一步就是將專案打包並發佈給其他人使用,讓沒有 Node.js 開發環境的使用者也能來使用服務。
安裝套件 安裝 Electron 打包套件 electron-builder
1 npm install --save-dev electron-builder
icon.png 在根目錄放置一個格式為 png
的 Icon 並命名為 icon.png
,會將其用作顯示應用程式的代表圖案,圖案大小建議至少 256x256。若讀者手邊沒有圖檔可以使用,這裡提供個人設計的 Logo,僅供練習使用
Logo (WRX, Wei-Ren Xue)
build.js 於專案根目錄建立一個檔案,為 Electron 的打包配置檔 build.js
,其內容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 const path = require ('path' );const builder = require ('electron-builder' );builder.build ({ projectDir : path.resolve (__dirname), win : ['portable' , 'nsis' ], config : { 'appId' : 'io.github.weirenxue.react-electron-demo' , 'productName' : 'React Based Electron' , 'copyright' : 'Copyright © 2021 Wei-Ren Xue' , 'directories' : { 'output' : 'electron-build/win' }, 'win' : { 'icon' : path.resolve (__dirname, 'icon.png' ), }, 'files' : [ 'build/**/*' , 'node_modules/**/*' , 'package.json' , 'main.js' , 'preload.js' , ], 'extends' : null , } }).then ( (data ) => console .log (data), (err ) => console .error (err) )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 const path = require ('path' );const builder = require ('electron-builder' );builder.build ({ projectDir : path.resolve (__dirname), win : ['portable' , 'nsis' ], mac : ['dmg' ], config : { 'appId' : 'io.github.weirenxue.react-electron-demo' , 'productName' : 'React Based Electron' , 'copyright' : 'Copyright © 2021 Wei-Ren Xue' , 'directories' : { 'output' : 'electron-build/win' }, 'win' : { 'icon' : path.resolve (__dirname, 'icon.png' ), }, 'mac' : { 'icon' : path.resolve (__dirname, 'icon.png' ), }, 'files' : [ 'build/**/*' , 'node_modules/**/*' , 'package.json' , 'main.js' , 'preload.js' , ], 'extends' : null , } }).then ( (data ) => console .log (data), (err ) => console .error (err) )
打包腳本 於 package.json
加入 electron-build
打包腳本
1 2 3 4 5 6 7 8 9 { ... "scripts" : { ... "electron-start" : "wait-on tcp:3000 && electron ." , "electron-build" : "npm run build && node build.js" } , ... }
"electron-build"
:npm run build
先建置 CRA 專案,node build.js
再建置 Electron 專案。
執行打包腳本 第一次執行打包會需要較久時間,因為需要下載相關套件,請耐心等待
這裡提供成功打包的 Log 做為參考
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 PS C :\Users \wrxue\source\nodejs\react-based-electron> npm run electron-build> react-based-electron@0.1 .0 electron-build C :\Users \wrxue\source\nodejs\react-based-electron > npm run build && node build.js > react-based-electron@0.1 .0 build C :\Users \wrxue\source\nodejs\react-based-electron > react-scripts build Creating an optimized production build...Compiled successfully.File sizes after gzip : 41.34 KB build\static \js\2. e86009e0.chunk .js 1.63 KB build\static \js\3. a8f12dc9.chunk .js 1.18 KB build\static \js\runtime-main.6c97c200.js 600 B build\static \js\main.6d3c4ff6.chunk .js 556 B build\static \css\main.a617e044 .chunk .css The project was built assuming it is hosted at ./.You can control this with the homepage field in your package.json .The build folder is ready to be deployed.Find out more about deployment here : https : • electron-builder version=22.11 .7 os=10.0 .19042 • description is missed in the package.json appPackageFile=C :\Users \wrxue\source\nodejs\react-based-electron\package.json • author is missed in the package.json appPackageFile=C :\Users \wrxue\source\nodejs\react-based-electron\package.json • writing effective config file=electron-build\win\builder-effective-config.yaml • packaging platform=win32 arch=x64 electron=13.1 .7 appOutDir=electron-build\win\win-unpacked • building target=portable file=electron-build\win\React Based Electron 0.1 .0 .exe archs=x64 • building target=nsis file=electron-build\win\React Based Electron Setup 0.1 .0 .exe archs=x64 oneClick=true perMachine=false • building block map blockMapFile=electron-build\win\React Based Electron Setup 0.1 .0 .exe .blockmap [ 'C:\\Users\\wrxue\\source\\nodejs\\react-based-electron\\electron-build\\win\\React Based Electron 0.1.0.exe' , 'C:\\Users\\wrxue\\source\\nodejs\\react-based-electron\\electron-build\\win\\React Based Electron Setup 0.1.0.exe.blockmap' , 'C:\\Users\\wrxue\\source\\nodejs\\react-based-electron\\electron-build\\win\\React Based Electron Setup 0.1.0.exe' ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 wrxue@ip233 react-based-electron % npm run electron-build > react-based-electron@0.1 .0 electron-build /Users /wrxue/Desktop /nodejs/react-based-electron > npm run build && node build.js > react-based-electron@0.1 .0 build /Users /wrxue/Desktop /nodejs/react-based-electron > react-scripts build Creating an optimized production build...Compiled successfully.File sizes after gzip : 41.34 KB build/static /js/2. e86009e0.chunk .js 1.63 KB build/static /js/3. a8f12dc9.chunk .js 1.18 KB build/static /js/runtime-main.6c97c200.js 600 B build/static /js/main.6d3c4ff6.chunk .js 556 B build/static /css/main.a617e044 .chunk .css The project was built assuming it is hosted at ./.You can control this with the homepage field in your package.json .The build folder is ready to be deployed.Find out more about deployment here : https : • electron-builder version=22.11 .7 os=20.5 .0 • description is missed in the package.json appPackageFile=/Users/ wrxue/Desktop /nodejs/react-based-electron/package.json • author is missed in the package.json appPackageFile=/Users/ wrxue/Desktop /nodejs/react-based-electron/package.json • writing effective config file=electron-build/win/builder-effective-config.yaml • rebuilding native dependencies dependencies=fsevents@1.2 .13 , fsevents@1.2 .13 platform=darwin arch=x64 • packaging platform=darwin arch=x64 electron=13.1 .7 appOutDir=electron-build/win/mac • signing file=electron-build/win/mac/React Based Electron .app identityName=Apple Development : a0981355215@gmail.com (PZRJD74VXK ) identityHash=755CB8F653511BDB2E6C567A905176EE278DD9D8 provisioningProfile=none • building target=DMG arch=x64 file=electron-build/win/React Based Electron -0.1 .0 .dmg • rebuilding native dependencies dependencies=fsevents@1.2 .13 , fsevents@1.2 .13 platform=win32 arch=x64 • packaging platform=win32 arch=x64 electron=13.1 .7 appOutDir=electron-build/win/win-unpacked • building block map blockMapFile=electron-build/win/React Based Electron -0.1 .0 .dmg .blockmap • building target=portable file=electron-build/win/React Based Electron 0.1 .0 .exe archs=x64 • building target=nsis file=electron-build/win/React Based Electron Setup 0.1 .0 .exe archs=x64 oneClick=true perMachine=false • building block map blockMapFile=electron-build/win/React Based Electron Setup 0.1 .0 .exe .blockmap [ '/Users/wrxue/Desktop/nodejs/react-based-electron/electron-build/win/React Based Electron-0.1.0.dmg.blockmap' , '/Users/wrxue/Desktop/nodejs/react-based-electron/electron-build/win/React Based Electron-0.1.0.dmg' , '/Users/wrxue/Desktop/nodejs/react-based-electron/electron-build/win/React Based Electron 0.1.0.exe' , '/Users/wrxue/Desktop/nodejs/react-based-electron/electron-build/win/React Based Electron Setup 0.1.0.exe.blockmap' , '/Users/wrxue/Desktop/nodejs/react-based-electron/electron-build/win/React Based Electron Setup 0.1.0.exe' ]
查看執行檔 由於我們在 build.js
中有指定 'output': 'electron-build/win'
,所以 electron-builder
會將打包好的安裝檔放置於 electron-build/win
目錄下
portable
與 nsis
在 Windows 上才可以使用,portable
執行檔啟動較慢但不需安裝,nsis
則是安裝一次後便能啟動快速
打包好的安裝檔
portable
與 nsis
在 Windows 上才可以使用,portable
的執行檔啟動較慢但不需安裝,nsis
則是安裝一次後便能啟動快速。而 dmg
是給 MacOS 使用的,開啟後將應用程式拖曳到 Applications
目錄便安裝完成
打包好的安裝檔
原始碼
Windows
MacOS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 * 1338c5d (macos) 加入打包腳本 * 56b90c1 建立 build.js * 9dc95f5 加入 icon.png * 1398a05 安裝 electron-builder * 6e4ed7c 入口點與啟動腳本 | * 928d60b (windows) 加入打包腳本 | * 890669a 建立 build.js | * a98f6c3 加入 icon.png | * 6cb08c7 安裝 electron-builder | * b61b238 入口點與啟動腳本 |/ * 06de8dd (master) main.js/preload.js * f9cc184 安裝 Electron 相關套件 * aad6a81 Initialize project using Create React App
在實作中遇到困難是難免的,這裡提供原始碼作為參考,若仍然無法解決歡迎至下方討論區留言。