资源
正文
进程模型

Note
Electron 应用程序的结构非常相似。 作为应用开发者,你将控制两种类型的进程:主进程 和 渲染器进程。 这类似于上文所述的 Chrome 的浏览器和渲染器进程。
主进程
每个 Electron 应用都有一个单一的主进程,作为应用程序的入口点。 主进程在 Node.js 环境中运行,这意味着它具有 require
模块和使用所有 Node.js API 的能力。
渲染器进程
每个 Electron 应用都会为每个打开的 BrowserWindow
( 与每个网页嵌入 ) 生成一个单独的渲染器进程。 洽如其名,渲染器负责 渲染 网页内容。
Important
Electron 的主进程和渲染进程有着清楚的分工并且不可互换。 这代表着无论是从渲染进程直接访问 Node.js 接口,亦或者是从主进程访问 HTML 文档对象模型 (DOM),都是不可能的。
安装
新建一个项目文件夹,执行下面命令:
之后一阵操作,得到 package.json
。
author
和 description
是必需的,不然将无法打包成 Electron。
cnpm
安装(不然巨慢):
修改 package.json
(添加 "scripts": {"start": "electron ."
}):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "name": "electron", "version": "1.0.0", "description": "A test case.", "license": "MIT", "author": "Zane", "type": "commonjs", "main": "main.js", "scripts": { "start": "electron ." }, "devDependencies": { "electron": "^38.1.0" } }
|
快速开始
创建一个 main.js
:
1 2 3 4 5
| const {app, BrowserWindow} = require('electron')
app.on('ready', () => { new BrowserWindow({width: 800, height: 600}).loadURL('https://www.google.com') });
|
终端里跑一下:

项目中创建一个 index.html
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <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 from Electron renderer!</title> </head> <body> <h1>Hello from Electron renderer!</h1> <p>👋</p> </body> </html>
|
Note
default-src 'self'
- 默认资源加载策略:只允许从当前源(
self
,即本地应用或同源的文件)加载内容。
- 这意味着 图片、字体、CSS、XHR 请求 等都只能来自当前应用打包的文件,而不能随便访问互联网或其他域名。
script-src 'self'
- 限制 JavaScript 的加载来源:只能执行来自应用自身的脚本。
- 禁止从 CDN、第三方域名加载脚本,也禁止内联脚本(除非特别允许
'unsafe-inline'
)。
- 这样可以防止外部恶意脚本注入和执行。
http-equiv="X-Content-Security-Policy"
- 这是 旧版 IE 和部分浏览器 对 CSP 的兼容写法。现代浏览器主要识别
Content-Security-Policy
,但为了兼容性,有些人会同时写上。
修改 main.js
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const {app, BrowserWindow} = require('electron')
const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 })
win.loadFile('index.html') }
app.on('ready', () => { createWindow() });
|
跑一下:

窗口管理
在 Windows/Linux 中,当所有窗口都被关闭时,主进程将被杀死。而 MacOS 则不会,因此可以加一段窗口管理的代码:
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
| const { app, BrowserWindow } = require('electron/main')
const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 })
win.loadFile('index.html') }
app.whenReady().then(() => { createWindow()
app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) })
app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } })
|
预加载脚本
Note
为了将 Electron 的不同类型的进程桥接在一起,我们需要使用被称为 预加载 的特殊脚本。
创建一个 peload.js
:
1 2 3 4 5 6 7
| const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('versions', { node: () => process.versions.node, chrome: () => process.versions.chrome, electron: () => process.versions.electron })
|
修改 main.js
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const { app, BrowserWindow } = require('electron')
const path = require('node:path')
const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js') } })
win.loadFile('index.html') }
app.whenReady().then(() => { createWindow() })
|
创建一个 renderer.js
:
1 2
| const information = document.getElementById('info') information.innerText = `本应用正在使用 Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), 和 Electron (v${versions.electron()})`
|
修改 index.html
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <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>来自 Electron 渲染器的问好!</title> </head> <body> <h1>来自 Electron 渲染器的问好!</h1> <p>👋</p> <p id="info"></p> </body> <script src="./renderer.js"></script> </html>
|

打包(electron-builder)
快被 forge 折磨死了……我跳车了。
先:
然后修改 package.json
:
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
| { "name": "electron", "version": "1.0.0", "description": "A test case.", "license": "MIT", "author": "Zane", "type": "commonjs", "main": "main.js", "scripts": { "start": "electron .", "dist": "electron-builder" }, "devDependencies": { "electron": "^38.1.0", "electron-builder": "^26.0.12" }, "dependencies": {}, "build": { "appId": "com.zane.electronapp", "productName": "ElectronTestApp", "directories": { "output": "dist" }, "files": [ "**/*" ], "win": { "target": [ "zip" ], "signAndEditExecutable": false } } }
|
执行打包命令:
它还是会尝试下载 Electron 的二进制文件……见招拆招吧,这里下载完毕了。
1 2 3 4 5 6 7 8 9 10 11 12
| > electron@1.0.0 dist > electron-builder
• electron-builder version=26.0.12 os=10.0.26100 • loaded configuration file=package.json ("build" field) • writing effective config file=dist\builder-effective-config.yaml • executing @electron/rebuild electronVersion=38.1.1 arch=x64 buildFromSource=false appDir=./ • installing native dependencies arch=x64 • completed installing native dependencies • packaging platform=win32 arch=x64 electron=38.1.1 appOutDir=dist\win-unpacked • updating asar integrity executable resource executablePath=dist\win-unpacked\ElectronTestApp.exe • building target=zip arch=x64 file=dist\ElectronTestApp-1.0.0-win.zip
|
西八,终于搞定了。

如果要加点别的(React/Vue 之类的),去 Github 看看有没有模板吧……