Unplugin (original) (raw)
Getting Started
Overview
Unplugin is a library that offers an unified plugin system for various build tools. It extends the excellent Rollup plugin API to serve as the standard plugin interface, and provides a compatibility layer based on the build tools employed.
Unplugin current supports:
Trying It Online
You can try Unplugin in your browser directly.
Creating an Unplugin package
Templates
Check repositories above for more details.
Plugin Installation
Pre-requisites
- Node.js 18.12.0 or later.
- webpack 5 or later, if you are using webpack.
Install package
npmyarnpnpmbun
bash
npm install unplugin-starter --save-dev
bash
yarn add unplugin-starter -D
bash
pnpm add unplugin-starter -D
bash
bun add unplugin-starter -D
Bundler & Framework Integration
ViteRollupRolldownwebpackRspackesbuildFarmVue-CLINuxtAstro
ts
// vite.config.ts
import Starter from 'unplugin-starter/vite'
export default defineConfig({
plugins: [
Starter({
/* options */
}),
],
})
js
// rollup.config.js
import Starter from 'unplugin-starter/rollup'
export default {
plugins: [
Starter({
/* options */
}),
],
}
js
// rolldown.config.js
import Starter from 'unplugin-starter/rolldown'
export default {
plugins: [
Starter({
/* options */
}),
],
}
js
// webpack.config.js
module.exports = {
/* ... */
plugins: [
require('unplugin-starter/webpack')({
/* options */
}),
],
}
js
// rspack.config.js
module.exports = {
/* ... */
plugins: [
require('unplugin-starter/rspack')({
/* options */
}),
],
}
js
// esbuild.config.js
import { build } from 'esbuild'
import Starter from 'unplugin-starter/esbuild'
build({
plugins: [Starter()],
})
ts
// farm.config.ts
import Starter from 'unplugin-starter/farm'
export default defineConfig({
plugins: [
Starter({
/* options */
}),
],
})
js
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
require('unplugin-starter/webpack')({
/* options */
}),
],
},
}
js
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
[
'unplugin-starter/nuxt',
{
/* options */
},
],
],
})
js
// astro.config.mjs
import { defineConfig } from 'astro/config'
import Starter from 'unplugin-turbo-console/astro'
// https://astro.build/config
export default defineConfig({
integrations: [Starter()],
})
Supported Hooks
Hook | Rollup | Vite | webpack | esbuild | Rspack | Farm | Rolldown |
---|---|---|---|---|---|---|---|
enforce | ❌ 1 | ✅ | ✅ | ❌ 1 | ✅ | ✅ | ✅ |
buildStart | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
resolveId | ✅ | ✅ | ✅ | ✅ | ✅ 5 | ✅ | ✅ |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
load | ✅ | ✅ | ✅ | ✅ 3 | ✅ | ✅ | ✅ |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
transform | ✅ | ✅ | ✅ | ✅ 3 | ✅ | ✅ | ✅ |
watchChange | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
buildEnd | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
writeBundle4 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Notice
- Rollup and esbuild do not support using
enforce
to control the order of plugins. Users need to maintain the order manually. - Webpack's id filter is outside of loader logic; an additional hook is needed for better performance on Webpack and Rolldown. However, it is now deprecated. Please use
transform/load/resolveId.filter
instead. In Rollup, this hook has been polyfilled to match the behaviors. See the following usage examples for reference. - Although esbuild can handle both JavaScript and CSS and many other file formats, you can only return JavaScript in
load
andtransform
results. - Currently,
writeBundle
is only serves as a hook for the timing. It doesn't pass any arguments. - Rspack supports
resolveId
with a minimum required version of v1.0.0-alpha.1.
Usage
ts
import type {
UnpluginFactory
} from 'unplugin'
import {
createUnplugin
} from 'unplugin'
export interface Options {
// define your plugin options here
}
export const
unpluginFactory
:
UnpluginFactory
<Options | undefined> =
options
=> ({
name
: 'unplugin-starter',
transform
: {
// an additional hook is needed for better perf on webpack and rolldown
filter
: {
id
: /main\.ts$/
},
handler
(
code
) {
return
code
.
replace
(/<template>/, '<template><div>Injected</div>')
},
},
// more hooks coming
})
export const
unplugin
= /* #__PURE__ */
createUnplugin
(
unpluginFactory
)
export default
unplugin
export const
vitePlugin
=
unplugin
.
vite
export const
rollupPlugin
=
unplugin
.
rollup
export const
rolldownPlugin
=
unplugin
.
rolldown
export const
webpackPlugin
=
unplugin
.
webpack
export const
rspackPlugin
=
unplugin
.
rspack
export const
esbuildPlugin
=
unplugin
.
esbuild
export const
farmPlugin
=
unplugin
.
farm
Filters
To optimize performance in native bundlers, leverage the filter
option in resolveId
, transform
, and load
hooks to exclude files that don’t require processing.
ts
import {
createUnplugin
} from 'unplugin'
type
FilterPattern
= string | RegExp |
Array
<string | RegExp>
const
plugin
=
createUnplugin
(() => ({
name
: 'unplugin-starter',
transform
: {
filter
: {
id
: {
include
: [/\.js$/, '**/*.ts'],
exclude
: /node_modules/,
},
code
: {
include
: 'foo',
exclude
: 'bar',
},
},
handler
(
code
) {
// ...
},
}
}))
More details can be found in the Rolldown's documentation.
Supported Context
Context | Rollup | Vite | webpack | esbuild | Rspack | Farm | Rolldown |
---|---|---|---|---|---|---|---|
this.parse | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
this.addWatchFile | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
this.emitFile1 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
this.getWatchFiles | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
this.warn | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
this.error | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Notice
- Currently, this.emitFile only supports the
EmittedAsset
variant.
Nested Plugins
Unplugin supports constructing multiple nested plugins to behave like a single one.
Bundler Supported
Rollup | Vite | webpack | Rspack | esbuild | Farm | Rolldown |
---|---|---|---|---|---|---|
✅ >=3.11 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Notice
- Rollup supports nested plugins since v3.1.0. Plugin author should ask users to have a Rollup version of
>=3.1.0
when using nested plugins. For single plugin format, Unplugin works for any version of Rollup.
Usage
ts
import type {
UnpluginFactory
} from 'unplugin'
import {
createUnplugin
} from 'unplugin'
export interface Options {
// define your plugin options here
}
export const
unpluginFactory
:
UnpluginFactory
<Options | undefined> =
options
=> [
{
name
: 'plugin-a',
transform
(
code
) {
return
code
.
replace
(/<template>/, '<template><div>Injected</div>')
},
},
{
name
: 'plugin-b',
resolveId
(
id
) {
return
id
},
},
]
export const
unplugin
= /* #__PURE__ */
createUnplugin
(
unpluginFactory
)
export default
unplugin
Bundler-Specific Logic
While Unplugin provides compatible layers for some hooks, the functionality of it is limited to the common subset of the build's plugins capability. For more advanced bundler-specific usages, Unplugin provides an escape hatch for that.
Hooks
ts
import type {
UnpluginFactory
} from 'unplugin'
import {
createUnplugin
} from 'unplugin'
export interface Options {
// define your plugin options here
}
export const
unpluginFactory
:
UnpluginFactory
<Options | undefined> = (
options
,
meta
,
) => {
console
.
log
(
meta
.
framework
) // vite rollup webpack esbuild rspack...
return {
name
: 'unplugin-starter',
transform
: {
// an additional hook is needed for better perf on webpack and rolldown
filter
: {
id
: /main\.ts$/
},
handler
(
code
) {
return
code
.
replace
(/<template>/, '<template><div>Injected</div>')
},
},
vite
: {
// Vite plugin
configureServer
(
server
) {
// configure Vite server
},
},
rollup
: {
// Rollup plugin
},
rolldown
: {
// Rolldown plugin
},
webpack
(
compiler
) {
// Configure webpack compiler
},
rspack
(
compiler
) {
// Configure Rspack compiler
},
esbuild
: {
// Change the filter of onResolve and onLoad
// onResolveFilter?: RegExp,
// onLoadFilter?: RegExp,
// Tell esbuild how to interpret the contents. By default Unplugin tries to guess the loader
// from file extension (eg: .js -> "js", .jsx -> 'jsx')
// loader?: (Loader | (code: string, id: string) => Loader)
// Or you can completely replace the setup logic
// setup?: EsbuildPlugin.setup,
},
farm
: {
// Farm plugin
},
}
}
export const
unplugin
= /* #__PURE__ */
createUnplugin
(
unpluginFactory
)
export default
unplugin
Plugins
The package exports a set of functions in place of createUnplugin
that allow for the creation of plugins for specific bundlers. Each of the function takes the same generic factory argument as createUnplugin
.
ts
import {
createEsbuildPlugin,
createFarmPlugin,
createRolldownPlugin,
createRollupPlugin,
createRspackPlugin,
createVitePlugin,
createWebpackPlugin,
} from 'unplugin'
const vitePlugin = createVitePlugin(/* factory */)
const rollupPlugin = createRollupPlugin(/* factory */)
const rolldownPlugin = createRolldownPlugin(/* factory */)
const esbuildPlugin = createEsbuildPlugin(/* factory */)
const webpackPlugin = createWebpackPlugin(/* factory */)
const rspackPlugin = createRspackPlugin(/* factory */)
const farmPlugin = createFarmPlugin(/* factory */)