A simple vite plugin for electron, supports esm/cjs, support esm in electron v28+
npm install @tomjs/vite-plugin-electron !node-current (scoped) !NPM 
English | 中文
> 一个简单的 electron vite 插件,支持 esm 和 cjs
非常感谢 caoxiemeihao 的 vite-plugin-electron 和 Doubleshotjs 的 doubleshot 这两个优秀库给了我启发。我希望使用它能简化开发配置,只关注业务开发。
- 使用 tsdown 快速构建 main 和 preload
- 配置简单,专注业务
- 支持 main 的 热重启
- 支持 preload 的 热重载
- 支持 esm 和 cjs ,你可以在 electron v28+ 中使用 esm
- 支持 vue 和 react 等其他 vite 支持的框架
- 可选 electron-builder 简单配置打包
``bashpnpm
pnpm add @tomjs/vite-plugin-electron -D
如果使用
builder 打包应用,请安装 electron-builder`bash
pnpm
pnpm add electron-builder -Dyarn
yarn add electron-builder -Dnpm
npm i electron-builder --save-dev
`使用说明
$3
#### 目录结构
- 推荐
electron 和 页面 src 代码目录结构`
|--electron
| |--main // main process code
| | |--index.ts
| |--preload // preload process code
| | |--index.ts
| |--build // electron-builder resources for electron package
| | |--icons
|--src // front-end code
| |--App.vue
| |--main.ts
`- 零配置,默认 dist 输出目录
`
|--dist
| |--main
| | |--index.js
| | |--index.js.map
| |--preload
| | |--index.js
| | |--index.js.map
| |--renderer
| | |--index.html
`#### 默认配置和行为
详细查看 PluginOptions 和
recommended 参数说明$3
electron/main/index.ts`ts
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { ELECTRON_EXIT } from '@tomjs/vite-plugin-electron/electron';
import { app, BrowserWindow } from 'electron';// when package.json "type": module"
globalThis.__dirname = dirname(fileURLToPath(import.meta.url));
const preload = join(__dirname, '../preload/index.mjs');
const url = process.env.VITE_DEV_SERVER_URL;
let win: BrowserWindow | null = null;
async function createWindow() {
win = new BrowserWindow({
title: 'Main window',
width: 800,
height: 700,
webPreferences: {
preload,
nodeIntegration: true,
contextIsolation: false,
},
});
if (isDev) {
win.loadURL(url);
}
else {
win.loadFile(indexHtml);
}
}
app.whenReady().then(createWindow);
process.on('message', (data) => {
// 重启 electron 时,如果 devTools 打开可能会造成 electron 无法正常关闭
if (data === ELECTRON_EXIT) {
if (win) {
win.webContents.closeDevTools();
}
}
});
`$3
以使用
esm 为例,不过要求 Electron>=28-
package.jsonElectron
preload process 必须使用 .mjs 后缀,否则报错,查看官方文档。所以 preload 的 esm 默认输出使用 mjs 后缀。为了保持一致性,main process 也以 .mjs 结尾。`json
{
"type": "module",
"main": "dist/main/index.mjs"
}
`-
vite.config.ts`ts
// import renderer from 'vite-plugin-electron-renderer'; // 启用 nodeIntegration
import electron from '@tomjs/vite-plugin-electron';
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';export default defineConfig({
plugins: [
vue(),
// 如使用约定的目录结构,则不需要配置
electron(),
// 如果自定义了目录结构,则必须根据实际情况赋值
// electron({
// main: {
// entry: 'electron/main/index.ts',
// },
// preload: {
// entry: 'electron/preload/index.ts',
// },
// }),
// renderer(),
],
});
`$3
以使用
cjs 为例-
package.json`json
{
// "type": "commonjs",
"main": "dist/main/index.js"
}
`-
vite.config.ts`ts
import electron from '@tomjs/vite-plugin-electron';
import react from '@vitejs/plugin-react-swc';
import { defineConfig } from 'vite';export default defineConfig({
plugins: [react(), electron()],
});
`文档
- unpkg.com 提供的 index.d.mts.
参数
$3
| 参数名 | 类型 | 默认值 | 说明 |
| ----------- | --------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| recommended |
boolean | true | 这个选项是为了提供推荐的默认参数和行为 |
| external | string[] | | 不打包这些模块,但是 dependencies and peerDependencies 默认排除,详见 |
| main | MainOptions | | electron main 进程选项 |
| preload | PreloadOptions | | electron preload 进程选项 |
| debug | boolean | false | Electron调试模式,不启动Electron。 您还可以使用 process.env.VITE_ELECTRON_DEBUG |
| builder | boolean | false | 如果是boolean类型,是否启用electron-builder。如果是Object,则是electron-builder的配置。 您还可以使用 process.env.VITE_ELECTRON_DEBUG 开启它。 |
| inspect | boolean | false | Electron 将监听指定 port 上的 V8 调试协议消息, 外部调试器需要连接到此端口上。您还可以使用 process.env.VITE_ELECTRON_INSPECT。 有关更多信息,请参阅debugging-main-process。 |
| devtools | boolean \| number | false | 如果为 true,根据 react 插件是否存在,注入 代码用于 react-devtools; 根据 vue 插件是否存在,注入 用于 vue-devtools 调试,如果为 number,则为自定义端口。 |recommended 选项用于设置默认配置和行为,几乎可以达到零配置使用,默认为 true 。如果你要自定义配置,请设置它为false。以下默认的前提条件是使用推荐的 项目结构。- 检查是否存在
electron/main/index.ts 和 electron/main/index.ts,如果有则分别给 main.entry 和 preload.entry 赋值。如果不存在,main.entry 必须主动赋值,负责会报错
- 输出目录根据 vite 的 build.outDir 参数, 将 electron/main、electron/preload、src 分别输出到 dist/main、dist/preload、dist/renderer
- 其他待实现的行为$3
继承自 tsdown 的 Options,添加了一些默认值,方便使用。
| 参数名 | 类型 | 默认值 | 说明 |
| ----------- | ----------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| entry |
string | - | main 入口文件 |
| format | 'cjs' \| 'esm' | - | 打包格式。如果未指定,将使用 package.json 中的 "type" 字段 |
| outDir | string | "dist-electron/main" | main 输出文件夹 |
| watchFiles | string \| string[] | undefined | 监听 electron 相关文件或文件夹。如果 recommended:true,则监听 electron/main 目录,否则需要指定 electron 代码对应目录,如果没有指定可能会造成 electron 无限重启 |
| ignoreWatch | Arrayable | '.history', '.temp', '.tmp', '.cache', 'dist' | 忽略监听的文件或文件夹 |$3
继承自 tsdown 的 Options,添加了一些默认值,方便使用。
| 参数名 | 类型 | 默认值 | 说明 |
| ----------- | ----------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| entry |
string | - | preload 入口文件 |
| format | 'cjs' \| 'esm' | - | 打包格式。如果未指定,将使用 package.json 中的 "type" 字段 |
| outDir | string | "dist-electron/preload" | preload 输出文件夹 |
| watchFiles | string \| string[] | undefined | 监听 electron 相关文件或文件夹。如果 recommended:true,则监听 electron/preload 目录,否则需要指定 electron 代码对应目录,如果没有指定可能会造成 electron 无限重启 |
| ignoreWatch | Arrayable | '.history', '.temp', '.tmp', '.cache', 'dist' | 忽略监听的文件或文件夹 |$3
当
recommended 和 builder.enable 都为 true 时,使用 electron-builder 打包 Electron 应用程序。- 在vite中配置的
build.outDir目录中,根据配置和package.json生成新的package.json。参考 vite-plugin-electron-renderer 和 Two package.json Structure
_不适合所有人使用。_
使用该功能,需要额外安装
electron-builder| 参数名 | 类型 | 默认值 | 说明 |
| ------------- | -------------------------------------------------------------------------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| appId |
string | "com.electron.${name}" | 应用程序 ID。详细 |
| productName | string | | 应用程序名称。详细 |
| builderConfig | Configuration | undefined | electron-builder 的 Configuration |默认配置如下
`ts
const config = {
directories: {
buildResources: 'electron/build',
app: path.dirname(resolvedConfig.build.outDir),
output: 'release/${version}',
},
files: ['main', 'preload', 'renderer'],
artifactName: '${productName}-${version}-${os}-${arch}.${ext}',
electronDownload: {
// when npm registry mirror is 'registry.npmmirror.com'
mirror: 'https://npmmirror.com/mirrors/electron',
},
electronLanguages: ['zh-CN', 'en-US'],
win: {
target: [
{
target: 'nsis',
arch: ['x64'],
},
],
},
mac: {
target: ['dmg'],
},
linux: {
target: ['zip'],
},
nsis: {
oneClick: false,
perMachine: false,
allowToChangeInstallationDirectory: true,
deleteAppDataOnUninstall: false,
},
};
`$3
-
main 和 preload 未配置相关参数时的默认值| 参数 | 开发模式默认值 | 生产模式默认值 |
| --------- | -------------- | -------------- |
| sourcemap |
true | false |
| minify | false | true |环境变量
$3
| 变量 | 描述 |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
VITE_ELECTRON_DEBUG | Electron主进程调试,不启动Electron。 当值为 true 或 1 时启用,为 false 或 0 时禁用。默认值未定义。 |
| VITE_ELECTRON_INSPECT | Electron 将在指定端口上侦听 V8 检查器协议消息,外部调试器需要连接到该端口。 当值为 true 时,默认端口为 5858。 |
| VITE_ELECTRON_BUILDER | 启用 Electron-builder 进行打包。 当值为 true 或 1 时启用,为 false 或 0 时禁用。 默认值未定义。 |$3
Electron
main process 和 renderer process 使用。| 变量 | 描述 |
| --------------------- | --------------------- |
|
VITE_DEV_SERVER_URL | Vite 开发服务器的 URL |调试
$3
Chrome Devtools 插件后像 Web 开发一样使用`ts
import { app } from 'electron';app.whenReady().then(() => {
const { installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } = await import(
'@tomjs/electron-devtools-installer'
);
installExtension([REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS])
.then((exts) => {
// 安装扩展后再开启开发者工具,否则可能会出现扩展加载失败问题
// win.webContents.openDevTools();
console.log(
'Added Extension: ',
exts.map(s => s.name),
);
})
.catch((err) => {
console.log('Failed to install extensions');
console.error(err);
});
});
`$3
通过
vscode 运行 Debug Main Process 调试主线程,调试工具参考 官方文档launch.json 配置如下:`json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Main Process",
"preLaunchTask": "npm:debug",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args": ["."],
"outFiles": [
"${workspaceFolder}/*/.js",
"${workspaceFolder}/*/.cjs",
"${workspaceFolder}/*/.mjs",
"!/node_modules/"
],
"envFile": "${workspaceFolder}/node_modules/@tomjs/vite-plugin-electron/debug/.env"
}
]
}
`tasks.json 配置如下:`json
{
"version": "2.0.0",
"tasks": [
{
"label": "npm:debug",
"type": "npm",
"script": "debug",
"detail": "cross-env VITE_ELECTRON_DEBUG=1 vite",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"fileLocation": "relative",
"pattern": {
"regexp": "^([a-zA-Z]\\:/?([\\w\\-]/?)+\\.\\w+):(\\d+):(\\d+): (ERROR|WARNING)\\: (.*)$",
"file": 1,
"line": 3,
"column": 4,
"code": 5,
"message": 6
},
"background": {
"activeOnStart": true,
"beginsPattern": "^.VITE v. ready in \\d ms.$",
"endsPattern": "^.\\[tomjs:electron\\] startup electron$"
}
}
}
]
}
`$3
使用
DevTools 调试 preload process.示例
先执行以下命令安装依赖,并生成库文件:
`bash
pnpm install
pnpm build
`打开 examples 目录,有
vue 和 react 示例。重要说明
$3
破坏性更新:
recommended:true,需要配置 watchFiles`,详见 MainOptions和 PreloadOptions