Skip to content

vite-plugin/vite-plugin-optimizer

Repository files navigation

vite-plugin-optimizer

Manually Pre-Bundling of Vite

NPM version NPM Downloads awesome-vite

English | 简体中文

  • Compatible Browser, Node.js and Electron
  • Custom Vite Pre-Bundling content

Install

npm i vite-plugin-optimizer -D

Usage

import optimizer from 'vite-plugin-optimizer'

export default {
  plugins: [
    optimizer({
      vue: `const vue = window.Vue; export { vue as default }`,
    }),
  ]
}

Load a local file

optimizer({
  // support nested module id
  // support return Promise
  '@scope/name': () => require('fs/promises').readFile('path', 'utf-8'),
})

Node.js and Electron

optimizer({
  // optimize Electron for using `ipcRenderer` in Electron-Renderer
  electron: `const { ipcRenderer } = require('electron'); export { ipcRenderer };`,

  // this means that both 'fs' and 'node:fs' are supported
  // e.g.
  //   `import fs from 'fs'`
  //   or
  //   `import fs from 'node:fs'`
  fs: () => ({
    // this is consistent with the `alias` behavior
    find: /^(node:)?fs$/,
    code: `const fs = require('fs'); export { fs as default };`
  }),
})

Advance

Optimize Node.js ESM packages as CommonJs modules for Node.js/Electron.
e.g. execa, node-fetch

You can see 👉 vite-plugin-esmodule

API (Define)

optimizer(entries[, options])

function optimizer(entries: Entries, options?: OptimizerOptions): import('vite').Plugin;
export interface OptimizerArgs {
  /** Generated file cache directory */
  dir: string;
}

export interface ResultDescription {
  /**
   * This is consistent with the `alias` behavior.
   * 
   * e.g.  
   *   `import fs from 'fs'`  
   *   or  
   *   `import fs from 'node:fs'`  
   * 
   * @example
   * {
   *   // This means that both 'fs' and 'node:fs' are supported.
   *   find: /^(node:)?fs$/,
   *   replacement: '/project/node_modules/.vite-plugin-optimizer/fs.js',
   * }
   */
  alias?: {
    find: string | RegExp;
    /**
     * If not explicitly specified, will use the path to the generated file as the default.
     */
    replacement?: string;
  };
  code?: string;
}

export interface Entries {
  [moduleId: string]:
  | string
  | ResultDescription
  | ((args: OptimizerArgs) => string | ResultDescription | Promise<string | ResultDescription | void> | void);
}

export interface OptimizerOptions {
  /**
   * @default ".vite-plugin-optimizer"
   */
  dir?: string;
  resolveId?: ((id: string) => string | Promise<string | void> | void);
}

How to work

Let's use Vue as an example

optimizer({
  vue: `const vue = window.Vue; export { vue as default }`,
})
  1. Create node_modules/.vite-plugin-optimizer/vue.js and contains the following code
const vue = window.Vue; export { vue as default }
  1. Register a vue alias item and add it to resolve.alias
{
  resolve: {
    alias: [
      {
        find: 'vue',
        replacement: '/User/work-directory/node_modules/.vite-plugin-optimizer/vue',
      },
    ],
  },
}

/**
 * 🚧
 * If you are using a function and have no return value, alias will not be registered.
 * In this case, you must explicitly specify alias.
 * 
 * e.g.
 * 
 * optimizer({
 *   async vue(args) {
 * 
 *     // ① You can customize the build `vue` and output it to the specified folder.
 *     await require('vite').build({
 *       entry: require.resolve('vue'),
 *       outputDir: args.dir + '/vue',
 *     })
 * 
 *     return {
 *       alias: {
 *         find: 'vue',
 *         // ② Make sure `replacement` points to the `vue` outputDir
 *         replacement: args.dir + '/vue',
 *       }
 *     }
 *   },
 * })
 */
  1. Add vue to the optimizeDeps.exclude by default.
export default {
  optimizeDeps: {
    // 🚧 You can avoid this behavior by `optimizeDeps.include`
    exclude: ['vue'],
  },
}