Home

Awesome

vite-electron-plugin

High-performance, esbuild-based Vite Electron plugin

NPM version NPM Downloads

Quick Setup

  1. Add dependency to project
npm i -D vite-electron-plugin
  1. Add vite-electron-plugin into vite.config.ts
import electron from 'vite-electron-plugin'

export default {
  plugins: [
    electron({
      include: [
        // The Electron source codes directory
        'electron',
      ],
    }),
  ],
}
  1. 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')
  }
})
  1. Add entry into package.json
{
+ "main": "dist-electron/main.js"
}

Examples

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

Configuration

electron(config: Configuration)
<table> <thead> <th>Key</th> <th>Type</th> <th>Description</th> <th>Required</th> <th>Default</th> </thead> <tbody> <tr> <td>include</td> <td><code>Array</code></td> <td> <code>directory</code> or <code>filename</code> or <code>glob</code> Array.<br/> Must be a relative path, which will be calculated based on the <code>root</code>.<br/> If it is an absolute path, it can only be a subpath of root.<br/> Otherwise it will cause the output file path to be calculated incorrectly.<br/> </td> <td>āœ…</td> <td></td> </tr> <tr> <td>root</td> <td><code>string</code></td> <td></td> <td></td> <td><code>process.cwd()</code></td> </tr> <tr> <td>outDir</td> <td><code>string</code></td> <td>Output Directory.</td> <td></td> <td><code>dist-electron</code></td> </tr> <tr> <td>api</td> <td><code>Record&lt;string, any&gt;</code></td> <td>Useful if you want to pass some payload to the plugin.</td> <td></td> <td></td> </tr> <tr> <td>plugins</td> <td><code>Plugin[]</code></td> <td>See the Plugin API.</td> <td></td> <td></td> </tr> <tr> <td>logger</td> <td><code>{ [type: string], (...message: string[]) => void }</code></td> <td>Custom log. If <code>logger</code> is passed, all logs will be input this option</td> <td></td> <td></td> </tr> <tr> <td>transformOptions</td> <td><code>import('esbuild').TransformOptions</code></td> <td>Options of <code>esbuild.transform()</code></td> <td></td> <td></td> </tr> <tr> <td>watch</td> <td><code>import('chokidar').WatchOptions</code></td> <td>Options of <code>chokidar.watch()</code></td> <td></td> <td></td> </tr> </tbody> </table>

Plugin API

The design of plugin is similar to Vite's plugin. But simpler, only 4 hooks in total.

configResolved

You can freely modify the config argument in ths hooks or use.

onwatch <sub><sup>serve only</sup></sub>

Triggered by include file changes. You can emit some files in this hooks. Even restart the Electron App.

transform

Triggered by changes in extensions files in include.

ondone

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([
          // `replacement` is recommented to use absolute path, 
          // it will be automatically calculated as relative path.
          { find: '@', replacement: path.join(__dirname, 'src') },
        ]),

        copy([
          // filename, glob
          { from: 'foo/*.ext', to: 'dest' },
        ]),

        // Dynamic change the build dist path.
        dest((_from, to) => to?.replace('dist-electron', 'dist-other')),

        customStart(({ startup }) => {
          // If you want to control the launch of Electron App yourself.
          startup()
        }),

        // Support use ESM npm-package in Electron-Main.  
        esmodule({
          // e.g. `execa`, `node-fetch`, `got`, etc.
          include: ['execa', 'node-fetch', 'got'],
        }),

        // https://vitejs.dev/guide/env-and-mode.html#env-files
        // Support use `import.meta.env.VITE_SOME_KEY` in Electron-Main
        loadViteEnv(),
      ],
    }),
  ],
}

JavaScript API

import {
  type Configuration,
  type ResolvedConfig,
  type Plugin,
  build,
  watch,
  startup,
  defineConfig,
  default as electron,
} from 'vite-electron-plugin'

Example

// dev
watch({
  include: [
    // The Electron source codes directory
    'electron',
  ],
  plugins: [
    {
      name: 'plugin-electron-startup',
      ondone() {
        // Startup Electron App
        startup()
      },
    },
  ],
})

// build
build({
  include: ['electron'],
})