vite-electron-plugin
High-performance, esbuild-based Vite Electron plugin

- π High-performance (Not Bundle, based on esbuild)
- π― Support Plugin (Like Vite's plugin)
- π± What you see is what you get
- π₯ Hot restart
Quick Setup
- Add dependency to project
npm i -D vite-electron-plugin
- Add
vite-electron-plugin
into vite.config.ts
import electron from 'vite-electron-plugin'
export default {
plugins: [
electron({
include: [
'electron',
],
}),
],
}
- Create
electron/main.ts
and type the following code
import { app, BrowserWindow } from 'electron'
app.whenReady().then(() => {
const win = new BrowserWindow()
if (process.env.VITE_DEV_SERVER_URL) {
win.loadURL(process.env.VITE_DEV_SERVER_URL)
} else {
win.loadFile('dist/index.html')
}
})
- Add entry into
package.json
{
+ "main": "dist-electron/main.js"
}
Recommend Structure
Let's use the official template-vanilla-ts created based on create vite
as an example
+ βββ¬ electron
+ β βββ main.ts
βββ¬ src
β βββ main.ts
β βββ style.css
β βββ vite-env.d.ts
βββ .gitignore
βββ favicon.svg
βββ index.html
βββ package.json
βββ tsconfig.json
+ βββ vite.config.ts
Conventions
- Any file ending with
reload.ext
(e.g. foo.reload.js
, preload.ts
) after an update,
will trigger a reload of the Electron-Renderer process, instead of an entire Electron App restart.
Which is useful when updating Preload-Scripts.
Configuration
electron(config: Configuration)
include | Array |
directory or filename or glob Array.
Must be a relative path, which will be calculated based on the root .
If it is an absolute path, it can only be a subpath of root.
Otherwise it will cause the output file path to be calculated incorrectly.
| β
| |
root | string | | | process.cwd() |
outDir | string | Output Directory. | | dist-electron |
api | Record<string, any> | Useful if you want to pass some payload to the plugin. | | |
plugins | Plugin[] | See the Plugin API. | | |
logger | { [type: string], (...message: string[]) => void } | Custom log. If logger is passed, all logs will be input this option | | |
transformOptions | import('esbuild').TransformOptions | Options of esbuild.transform() | | |
watch | import('chokidar').WatchOptions | Options of chokidar.watch() | | |
Plugin API
The design of plugin is similar to Vite's plugin. But simpler, only 4 hooks in total.
configResolved
- Type:
(config: ResolvedConfig) => void | Promise<void>
- Kind:
async
, sequential
You can freely modify the config
argument in ths hooks or use.
onwatch
serve only
- Type:
(envet: 'add' | 'change' | 'addDir' | 'unlink' | 'unlinkDir', path: string) => void
- Kind:
async
, parallel
Triggered by include
file changes. You can emit some files in this hooks. Even restart the Electron App.
transform
- Type:
(args: { filename: string, code: string, done: () => void }) => string | import('esbuild').TransformResult | void | Promise<string | import('esbuild').TransformResult | void>
- Kind:
async
, sequential
Triggered by changes in extensions
files in include.
ondone
- Type:
(args: { filename: string, distname: string }) => void
- Kind:
async
, parallel
Triggered when transform()
ends or a file in extensions
is removed.
Builtin Plugin
import path from 'node:path'
import electron from 'vite-electron-plugin'
import {
alias,
copy,
dest,
esmodule,
customStart,
loadViteEnv,
} from 'vite-electron-plugin/plugin'
export default {
plugins: [
electron({
plugins: [
alias([
{ find: '@', replacement: path.join(__dirname, 'src') },
]),
copy([
{ from: 'foo/*.ext', to: 'dest' },
]),
dest((_from, to) => to?.replace('dist-electron', 'dist-other')),
customStart(({ startup }) => {
startup()
}),
esmodule({
include: ['execa', 'node-fetch', 'got'],
}),
loadViteEnv(),
],
}),
],
}
JavaScript API
import {
type Configuration,
type ResolvedConfig,
type Plugin,
build,
watch,
startup,
defineConfig,
default as electron,
} from 'vite-electron-plugin'
Example
watch({
include: [
'electron',
],
plugins: [
{
name: 'plugin-electron-startup',
ondone() {
startup()
},
},
],
})
build({
include: ['electron'],
})