盒子
盒子
文章目录
  1. 问题
  2. 排查
    1. 是否是插件的使用顺序问题?
    2. stage: Infinity
  3. 结论

webpack插件的stage-Infinity选项

问题

最近在使用 vue-server-renderer 时,输出的vue-ssr-client-manifest.json中多了一些js文件,而这些js并非是入口文件产生的。

排查

因为添加了插件 webpack-external-entry-plugin 的关系,所以当时我直接确认了问题的方向,即vue-server-renderer并没有使用更新过后的chunks。

是否是插件的使用顺序问题?

将external-entry-plugin移到vue-server-renderer前,问题依旧。

plugins: [
ExternalEntryPlugin: {
assets: [Path.join(ENV.srcPath, 'assets/img/favicon.ico')]
}
new VueSSRClientPlugin(),
]

将webpack-manifest-plugin的顺序与ExternalEntryPlugin更换后,webpack-manifest-plugin输出的assets.json也出现了这个问题。

stage: Infinity

于是我去仔细比较了webpack-manifest-plugin和VueSSRClientPlugin的不同,最终发现了两者之间的不同在于,注册事件的第一个参数:pluginOption。
webpack-manifest-plugin的pluginOption中stage为Infinity,而VueSSRClientPlugin并没有设置该参数。
由于并没有在网上查找到该参数的确切作用,所以只能改变该参数的值去验证事件触发的顺序。
当两个插件的stage均设置为Infinity时,事件触发的顺序与插件使用顺序有关;
当两个插件的stage均不设置Infinity时,事件触发的顺序与插件使用顺序有关;
当只有一个插件的stage设置为Infinity时,事件触发的顺序为设置了Infinity的永远在排在后面;

结论

于是,大概能理解stage参数的作用了。
1、当设置了stage为Infinity,插件会尽可能的等待所有注册在它前面和stage为非Infinity的事件执行完毕,对于那些不改变chunks的插件来说,设置Infinity是有必要的,比如webpack-manifest-plugin插件,它其实不关心chunks的变化,它只需要等待其他插件执行完毕再将最新的chunks输出到json文件就行。
2、当不设置stage为Infinity,插件会在所有注册在它后面的和stage为Infinity的事件之前执行。对于一些会动态改变chunks的插件来说,不设置Infinity可以避免其他插件没有及时得到更新后的chunks,即这次出现的问题。
我没法更改VueSSRClientPlugin插件,所以只能修改自己的插件webpack-external-entry-plugin,取消stage。

const pluginOptions = {
name: 'ExternalEntryPlugin',
// stage: Infinity
};

现在,问题完美解决,特此记录。