Skip to content

electron-vite/vite-plugin-electron-renderer

Repository files navigation

vite-plugin-electron-renderer

Support use Node.js API in Electron-Renderer

English | 简体中文


Warning

nodeIntegration is not recommended in Electron, and this plugin is not a solution to the security issues it may cause. If you want to use this plugin, please make sure you understand the security implications of enabling nodeIntegration and take appropriate measures to mitigate potential risks.

In short, vite-plugin-electron-renderer is responsible for polyfilling Electron, Node.js built-in modules and other npm packages for the Renderer process.

Install

npm i vite-plugin-electron-renderer -D

Usage

Important

This plugin is currently in v1 beta development. Use it at your own risk.

Breaking change (v1):

  • Drop Vite < 8 support.
  • resolve.*.type: 'esm' now uses createRequire() for pure-ESM packages. Electron 35+ (Node 22+) is required; prebuildEsm: true is the compatibility option for Electron < 35.

For old behavior, use v0.14.7 instead.

  1. This just modifies some of Vite's default config to make the Renderer process works.
import renderer from 'vite-plugin-electron-renderer'

export default {
  plugins: [renderer()],
}
  1. Using the third-part C/C++, esm package in the Renderer process.
import renderer from 'vite-plugin-electron-renderer'

export default {
  plugins: [
    renderer({
      // Compatibility option for Electron < 35
      prebuildEsm: true,
      resolve: {
        // C/C++ modules should stay on require()
        serialport: { type: 'cjs' },
        // Pure ESM modules can be loaded through dynamic import()
        got: { type: 'esm' },
        // Pure CJS modules can opt into production bundling
        somePureCjsPackage: { type: 'cjs', bundle: true },
      },
    }),
  ],
}

By default, type: 'cjs' modules stay on runtime require() and should be put into dependencies. type: 'esm' modules are bundled in production builds unless bundle: false is set.

API (Define)

renderer(options: RendererOptions)

export interface RendererOptions {
  /**
   * Compatibility option for Electron < 35.
   * Pre-build `resolve.*.type = 'esm'` deps to CJS during dev so the shim can
   * stay on plain `require()`.
   */
  prebuildEsm?: boolean
  /**
   * Explicitly tell Vite how to load modules, which is very useful for C/C++ and `esm` modules
   *
   * - `type.cjs` loads through `require()` and exposes statically known names when possible
   * - `type.esm` loads through `createRequire()` and exposes statically known names when possible (falls back to dynamic `export *` when introspection fails)
   *
   * @experimental
   */
  resolve?: {
    [module: string]: {
      type: 'cjs' | 'esm'
      /**
       * Whether this dependency should be bundled in production builds.
       *
       * Defaults to `true` for `type: 'esm'`, and `false` for `type: 'cjs'`.
       */
      bundle?: boolean
      /** Full custom how to generate the shim module */
      build?: (args: {
        cjs: (module: string) => Promise<string>
        esm: (module: string) => Promise<string>
      }) => Promise<string>
    }
  }
}

How to work

Load Electron and Node.js cjs-packages/built-in-modules (Schematic)

 ┏————————————————————————————————————————┓                 ┏—————————————————┓
 │ import { ipcRenderer } from 'electron' │                 │ Vite dev server │
 ┗————————————————————————————————————————┛                 ┗—————————————————┛
                 │                                                   │
                 │ 1. Generate electron shim on first resolve        │
                 │    node_modules/.vite-electron-renderer/electron  │
                 │                                                   │
                 │ 2. HTTP(Request): electron module                 │
                 │ ————————————————————————————————————————————————> │
                 │                                                   │
                 │ 3. resolveId() redirects to                       │
                 │    node_modules/.vite-electron-renderer/electron  │
                 │    ↓                                              │
                 │    const { ipcRenderer } = require('electron')    │
                 │    export { ipcRenderer }                         │
                 │                                                   │
                 │ 4. HTTP(Response): electron module                │
                 │ <———————————————————————————————————————————————— │
                 │                                                   │
 ┏————————————————————————————————————————┓                 ┏—————————————————┓
 │ import { ipcRenderer } from 'electron' │                 │ Vite dev server │
 ┗————————————————————————————————————————┛                 ┗—————————————————┛

Dependency Pre-Bundling

In general. Vite will pre-bundle all third-party modules in a Web-based usage format, but it can not adapt to Electron Renderer process especially C/C++ modules. So we must be make a little changes for this.

const _M_ = require('serialport')

export default _M_.default || _M_
export const SerialPort = _M_.SerialPort
// export other members ...

Modules configured as esm are bundled in production builds by default. Set bundle: false to keep them on the runtime shim path, where they are wrapped with createRequire() (Electron's embedded Node 22+ supports require(esm)) and re-exported with their statically introspected names. If introspection fails at build time, the shim falls back to a dynamic export *.

prebuildEsm: true is a compatibility option for Electron < 35. In that mode, the plugin reuses its internal dependency build path to pre-build configured type: 'esm' dependencies to CJS during dev, then serves the usual renderer shim on top of that CJS output.

dependencies vs devDependencies

Classify e.g. dependencies devDependencies
Node.js C/C++ native modules serialport, sqlite3
Node.js CJS packages electron-store
Node.js ESM packages execa, got, node-fetch ✅ (Recommend)
Web packages Vue, React ✅ (Recommend)

Why is it recommended to put properly buildable packages in devDependencies?

Doing so will reduce the size of the packaged APP by electron-builder.

About

Ployfill Node.js API for Renderer process

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors