gotchajavascriptModerate
Vite plugins: execution order with enforce and apply
Viewed 0 times
Vite 3+
vite plugin orderenforce pre postapply build serveplugin transformvite plugin api
Problem
Custom Vite plugins run in an unpredictable order relative to built-in transforms and other plugins, causing transforms to receive input in the wrong format or to miss files that were already processed.
Solution
Use the 'enforce' property to pin a plugin before ('pre') or after ('post') Vite's core plugins. Use 'apply' to restrict the plugin to 'build' or 'serve' mode.
// vite.config.ts
import { defineConfig, Plugin } from 'vite';
function myPrePlugin(): Plugin {
return {
name: 'my-pre-plugin',
enforce: 'pre', // runs before Vite core
apply: 'build', // only during vite build
transform(code, id) {
if (!id.endsWith('.vue')) return;
return code.replace(/__VERSION__/g, '1.0.0');
},
};
}
export default defineConfig({ plugins: [myPrePlugin()] });
// vite.config.ts
import { defineConfig, Plugin } from 'vite';
function myPrePlugin(): Plugin {
return {
name: 'my-pre-plugin',
enforce: 'pre', // runs before Vite core
apply: 'build', // only during vite build
transform(code, id) {
if (!id.endsWith('.vue')) return;
return code.replace(/__VERSION__/g, '1.0.0');
},
};
}
export default defineConfig({ plugins: [myPrePlugin()] });
Why
Vite applies plugins in three phases: 'pre' plugins, Vite core transforms, then 'post' plugins. Without enforce, the order among user plugins matches the array order, which is often not deterministic enough for transforms that depend on raw source.
Gotchas
- Rollup hooks like buildStart, generateBundle run only during 'build', not 'serve'
- The 'apply' field also accepts a function: apply(config, { command }) for fine-grained control
- A plugin that returns null/undefined from transform is a no-op and passes the code unchanged
Context
Writing custom Vite plugins or debugging unexpected transform ordering
Revisions (0)
No revisions yet.