已发布·持续改进
Electron 指南 · 2/6
本章目前仅提供英文版。
An Electron app is made of several pieces of code running with different privileges. This chapter shows where the main process, preload script, and renderer live, and what package.json and the Forge configuration control.
| Piece | Runs in | Has access to | Typical file |
|---|---|---|---|
| Main process | Node.js, one per app | Electron main APIs, all of Node.js | main.js |
| Preload script | Inside the renderer, before the page loads | A limited set such as contextBridge and ipcRenderer | preload.js |
| Renderer | A Chromium web page, one per window | Web platform APIs plus whatever the preload exposes | index.html, renderer.js |
The main process manages the app lifecycle and windows and talks to the operating system. A renderer behaves like a browser tab with no Node.js access by default. The preload script bridges the two and exposes only what the page needs.
Adding a preload and a renderer script to the previous chapter's project gives this layout:
my-electron-app/
├── package.json # name, version, main, scripts, dependencies
├── main.js # main process
├── preload.js # preload script
├── index.html # renderer page
├── renderer.js # script that runs in the renderer
└── node_modules/The preload script is attached when a window is created, through webPreferences.preload, as an absolute path. Build the path from __dirname so it still resolves after packaging.
const { app, BrowserWindow } = require('electron')
const path = require('node:path')
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)The preload uses contextBridge to attach a single object to the renderer's window, and the page uses only that object.
// preload.js
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
})// renderer.js, loaded from index.html with <script src="./renderer.js"></script>
const info = document.getElementById('info')
info.innerText = `Chrome ${versions.chrome()}, Node.js ${versions.node()}, Electron ${versions.electron()}`A project created from the vite-typescript template keeps its sources in src/ and builds the main, preload, and renderer code separately with Vite.
my-app/
├── forge.config.ts # packaging, installers, plugins
├── forge.env.d.ts # types for globals injected by Forge
├── index.html # renderer page
├── package.json
├── src/
│ ├── main.ts # main process
│ ├── preload.ts # preload script
│ ├── renderer.ts # renderer entry
│ └── index.css
├── tsconfig.json
├── vite.main.config.ts
├── vite.preload.config.ts
└── vite.renderer.config.tsIn development the renderer comes from the Vite dev server; in a packaged app it is loaded from the built files. The template's main.ts tells them apart with globals defined by Forge:
if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL)
} else {
mainWindow.loadFile(path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`))
}The top of the template's main.ts also checks electron-squirrel-startup, so the app exits immediately when the Windows installer (Squirrel) launches it during install or uninstall.
In a Forge project, package.json holds scripts that call the Forge CLI, and main points at the built main process file (.vite/build/main.js in the Vite templates).
{
"main": ".vite/build/main.js",
"scripts": {
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish"
}
}forge.config.ts defines packaging options (packagerConfig), the installer formats to build (makers), and build plugins (plugins).
import type { ForgeConfig } from '@electron-forge/shared-types'
import { MakerSquirrel } from '@electron-forge/maker-squirrel'
import { MakerZIP } from '@electron-forge/maker-zip'
import { MakerDeb } from '@electron-forge/maker-deb'
import { VitePlugin } from '@electron-forge/plugin-vite'
const config: ForgeConfig = {
packagerConfig: { asar: true },
makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerDeb({})],
plugins: [
new VitePlugin({
build: [
{ entry: 'src/main.ts', config: 'vite.main.config.ts', target: 'main' },
{ entry: 'src/preload.ts', config: 'vite.preload.config.ts', target: 'preload' },
],
renderer: [{ name: 'main_window', config: 'vite.renderer.config.ts' }],
}),
],
}
export default configipcRenderer object.__dirname or app.getAppPath() so they keep working after packaging.main field in package.json points at the main process entry file.webPreferences.preload and expose features with contextBridge.src/, Vite config files, and forge.config.ts.
0 条评论
登录 · 登录后即可发表评论。
来发表第一条评论吧。