webpack的流程
其中绿色蓝色红色都是常用的阶段
compile:编译开始
compilation:准备编译的过程
make:开始编译
afterCompile:编译结束
seal:对代码进行封装(优化合并)
codeGenerate:生成最终代码
emit:发射一个文件出来,把他写到硬盘里
done:完成
这些阶段也是写插件常用的阶段
imagemin-webpack-plugin
首先要知道这个插件是干嘛的,文档:https://github.com/Klathmon/imagemin-webpack-plugin#readme
这是一个简易的插件:使用imagemin来压缩你项目中的所有图片
用法:
var ImageminPlugin = require('imagemin-webpack-plugin').default// Or if using ES2015:// import ImageminPlugin from 'imagemin-webpack-plugin'module.exports = {plugins: [// Make sure that the plugin is after any plugins that add imagesnew ImageminPlugin({disable: process.env.NODE_ENV !== 'production', // Disable during developmentpngquant: {quality: '95-100'}})]}
就是在plugins加上new ImageminPlugin,然后写上选项,选项是最重要的。
apply是webpack规定的,用于写插件的主要逻辑
思路:
首先这个插件会监听emit事件,在emit里面对所有的asset进行检查,如果发现它是图片,就优化。优化之后,把这个图片替换原来的图片。
回看上面的webpack流程,emit是在写入硬盘阶段触发的,所以是在项目打包接近尾声去处理图片。
clean-webpack-plugin
https://github.com/johnagan/clean-webpack-plugin
该插件用于清楚你的build目录。
它会清楚所有在webpack output.path里面的文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');const webpackConfig = {plugins: [/*** All files inside webpack's output.path directory will be removed once, but the* directory itself will not be. If using webpack 4+'s default configuration,* everything under <PROJECT_DIR>/dist/ will be removed.* Use cleanOnceBeforeBuildPatterns to override this behavior.** During rebuilds, all webpack assets that are not used anymore* will be removed automatically.** See `Options and Defaults` for information*/new CleanWebpackPlugin(),],};module.exports = webpackConfig;
用法:在plugins里面写上new CleanWebpackPlugin()就行了
思路:在开始将文件写入硬盘之前清空dist目录,在所有东西做完之后,就删除所有要用的文件之外的文件
ProveidePlugin
https://webpack.docschina.org/plugins/provide-plugin/
当你想要使用全局的变量(vue,jq这样的变量)时,你不需要import,直接用就行。
比如当你想要使用vue
new webpack.ProvidePlugin({Vue: ['vue/dist/vue.esm.js', 'default'],});
想要使用jQ
应该是在我使用到了jq关键字的地方,它帮我自动import了jq。所以应该会在编译过程make阶段中帮我们做这件事。因为make才会做文件的处理

它遍历了所有的表达式,如果找到了对应的字符,比如vue,jq,就在module的里添加依赖(相当于帮它写一个import)
监听编译阶段,在此阶段获取nmf,再监听nmf的parser阶段,在parser阶段遍历sat的时候,一旦发现$,就自动引入jq (addDependency(jq))
loader与plugin的区别
看了以上三个插件,可以得知我们可以对webpack的所有阶段进行魔改,把一个文件删掉,修改依赖等操作都是可以的。
loader的话,可能我们会在make阶段run一下loader。
plugin是可以在任何阶段使用的。
再结合之前写的:
loader是一个转换器,将A文件进行编译成B文件,比如:将A.less转换成A.css,单纯的文件转换过程。
plugin是一个拓展器,对webpack的功能拓展,针对的是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛任务
写一个webpack plugin
就知道怎么写,有很多现成的插件可以供我们使用。
文档:https://webpack.js.org/contribute/writing-a-plugin/
//规定:必须是一个classclass MyExampleWebpackPlugin {// Define `apply` as its prototype method which is supplied with compiler as its argument//必须拥有一个apply来写主要逻辑apply(compiler) {// Specify the event hook to attach to//监听某后hook去进行操作compiler.hooks.emit.tapAsync('MyExampleWebpackPlugin',(compilation, callback) => {console.log('This is an example plugin!');console.log('Here’s the `compilation` object which represents a single build of assets:',compilation);// Manipulate the build using the plugin API provided by webpackcompilation.addModule(/* ... */);callback();});}}
