18个常用webpack plugin

webpack的流程

其中绿色蓝色红色都是常用的阶段
compile:编译开始
compilation:准备编译的过程
make:开始编译
afterCompile:编译结束
seal:对代码进行封装(优化合并)
codeGenerate:生成最终代码
emit:发射一个文件出来,把他写到硬盘里
done:完成

这些阶段也是写插件常用的阶段

看一下别人的插件怎么写的:

imagemin-webpack-plugin

首先要知道这个插件是干嘛的,文档:https://github.com/Klathmon/imagemin-webpack-plugin#readme
这是一个简易的插件:使用imagemin来压缩你项目中的所有图片
用法:

  1. var ImageminPlugin = require('imagemin-webpack-plugin').default
  2. // Or if using ES2015:
  3. // import ImageminPlugin from 'imagemin-webpack-plugin'
  4. module.exports = {
  5. plugins: [
  6. // Make sure that the plugin is after any plugins that add images
  7. new ImageminPlugin({
  8. disable: process.env.NODE_ENV !== 'production', // Disable during development
  9. pngquant: {
  10. quality: '95-100'
  11. }
  12. })
  13. ]
  14. }

就是在plugins加上new ImageminPlugin,然后写上选项,选项是最重要的。

apply是webpack规定的,用于写插件的主要逻辑
思路:
首先这个插件会监听emit事件,在emit里面对所有的asset进行检查,如果发现它是图片,就优化。优化之后,把这个图片替换原来的图片。
回看上面的webpack流程,emit是在写入硬盘阶段触发的,所以是在项目打包接近尾声去处理图片。

clean-webpack-plugin

https://github.com/johnagan/clean-webpack-plugin
该插件用于清楚你的build目录。
它会清楚所有在webpack output.path里面的文件

  1. const { CleanWebpackPlugin } = require('clean-webpack-plugin');
  2. const webpackConfig = {
  3. plugins: [
  4. /**
  5. * All files inside webpack's output.path directory will be removed once, but the
  6. * directory itself will not be. If using webpack 4+'s default configuration,
  7. * everything under <PROJECT_DIR>/dist/ will be removed.
  8. * Use cleanOnceBeforeBuildPatterns to override this behavior.
  9. *
  10. * During rebuilds, all webpack assets that are not used anymore
  11. * will be removed automatically.
  12. *
  13. * See `Options and Defaults` for information
  14. */
  15. new CleanWebpackPlugin(),
  16. ],
  17. };
  18. module.exports = webpackConfig;

用法:在plugins里面写上new CleanWebpackPlugin()就行了
思路:在开始将文件写入硬盘之前清空dist目录,在所有东西做完之后,就删除所有要用的文件之外的文件

ProveidePlugin

https://webpack.docschina.org/plugins/provide-plugin/
当你想要使用全局的变量(vue,jq这样的变量)时,你不需要import,直接用就行。

比如当你想要使用vue

  1. new webpack.ProvidePlugin({
  2. Vue: ['vue/dist/vue.esm.js', 'default'],
  3. });

想要使用jQ
image.png
应该是在我使用到了jq关键字的地方,它帮我自动import了jq。所以应该会在编译过程make阶段中帮我们做这件事。因为make才会做文件的处理

image.png
它遍历了所有的表达式,如果找到了对应的字符,比如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/

  1. //规定:必须是一个class
  2. class MyExampleWebpackPlugin {
  3. // Define `apply` as its prototype method which is supplied with compiler as its argument
  4. //必须拥有一个apply来写主要逻辑
  5. apply(compiler) {
  6. // Specify the event hook to attach to
  7. //监听某后hook去进行操作
  8. compiler.hooks.emit.tapAsync(
  9. 'MyExampleWebpackPlugin',
  10. (compilation, callback) => {
  11. console.log('This is an example plugin!');
  12. console.log(
  13. 'Here’s the `compilation` object which represents a single build of assets:',
  14. compilation
  15. );
  16. // Manipulate the build using the plugin API provided by webpack
  17. compilation.addModule(/* ... */);
  18. callback();
  19. }
  20. );
  21. }
  22. }