Plugin execution order control
Plugin Execution Order Control
Vite.js's plugin system is based on Rollup's plugin mechanism, where the execution order of plugins directly affects the build results. Understanding and controlling plugin execution order is key to optimizing the build process. Issues with plugin order typically arise when multiple plugins need to work together, such as when one plugin transforms code and another needs to process the result.
Basics of Plugin Execution Order
Vite plugins execute in two phases: hooks like resolveId
, load
, and transform
belong to the build phase, while hooks like buildStart
and buildEnd
belong to the output phase. By default, plugins execute in the order they are listed in the array:
// vite.config.js
export default {
plugins: [
pluginA(), // executes first
pluginB() // executes later
]
}
However, certain hooks support modes like sequential
(execute in order), parallel
(execute in parallel), or first
(terminate early). For example, the transform
hook defaults to sequential
, while resolveId
defaults to first
.
Methods to Control Execution Order
1. Explicit Sorting
Adjust the position using the enforce
property:
// vite.config.js
export default {
plugins: [
{
...pluginA(),
enforce: 'pre' // executes early
},
pluginB(), // normal order
{
...pluginC(),
enforce: 'post' // executes late
}
]
}
Possible values for enforce
:
pre
: Executes before core pluginsdefault
: Normal orderpost
: Executes after core plugins
2. Hook Priority
Some hooks can explicitly pass control by returning null
:
function myPlugin() {
return {
name: 'my-plugin',
resolveId(source) {
if (source.startsWith('@/')) return null // let subsequent plugins handle it
return source
}
}
}
3. Conditional Execution
Use the apply
property to control when a plugin is active:
// vite.config.js
export default {
plugins: [
{
...pluginA(),
apply: 'build' // only executes during build
}
]
}
Practical Examples
CSS Preprocessing Scenario
Compile Sass first, then add browser prefixes:
import sass from 'sass'
import autoprefixer from 'autoprefixer'
export default {
plugins: [
{
name: 'vite-sass-preprocessor',
transform(code, id) {
if (id.endsWith('.scss')) {
return sass.compileString(code).css
}
},
enforce: 'pre'
},
{
name: 'vite-autoprefixer',
transform(code, id) {
if (id.endsWith('.css')) {
return autoprefixer.process(code).css
}
}
}
]
}
Multi-Plugin Collaboration Example
Typical order when processing Vue SFCs:
export default {
plugins: [
vue(), // first parse Vue single-file components
{
...imageOptimizer(),
enforce: 'post' // optimize images last
}
]
}
Debugging Plugin Order
Use the --debug
flag to inspect plugin execution:
vite build --debug
The output will show the execution order and time consumption of each plugin hook, which is very helpful for optimizing plugin order.
Advanced Control Techniques
1. Manually Triggering Hooks
function myPlugin() {
return {
name: 'manual-hook',
buildStart() {
this.emitFile({
type: 'chunk',
id: 'virtual-module',
name: 'virtual-module'
})
}
}
}
2. Dynamically Adjusting Order
export default {
plugins: [
{
name: 'dynamic-order',
config(config) {
if (config.mode === 'development') {
return {
plugins: [devPlugin()]
}
}
}
}
]
}
3. Hook Interception
function interceptorPlugin() {
return {
name: 'hook-interceptor',
transform(code, id) {
if (id.includes('intercept')) {
return code.replace('foo', 'bar')
}
}
}
}
Common Problem Solutions
Handling Plugin Conflicts
When two plugins process the same type of file:
export default {
plugins: [
{
...markdownPlugin(),
enforce: 'pre',
apply: 'serve' // only process markdown during development
},
{
...anotherMarkdownPlugin(),
enforce: 'post'
}
]
}
Performance Optimization Order
Place time-consuming plugins last:
export default {
plugins: [
basicTransforms(),
{
...expensivePlugin(),
enforce: 'post'
}
]
}
Plugin Order and Build Modes
Different orders may be needed for development and production modes:
export default {
plugins: [
mode === 'production' ? productionPlugin() : null,
devOnlyPlugin()
].filter(Boolean)
}
Plugin Metadata Exchange
Pass information via the meta
property:
function firstPlugin() {
return {
name: 'first',
transform(code) {
this.meta.myData = 'processed'
}
}
}
function secondPlugin() {
return {
name: 'second',
transform(code) {
console.log(this.meta.myData) // retrieve data from upstream plugins
}
}
}
Virtual Module Processing Order
Special attention is needed for virtual modules:
function virtualModulePlugin() {
const virtualId = 'virtual:module'
return {
name: 'virtual-module',
resolveId(id) {
if (id === virtualId) return virtualId
},
load(id) {
if (id === virtualId) return 'export default "content"'
}
}
}
Such plugins typically require enforce: 'pre'
to ensure they execute first.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn