什么是loader

loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中

  1. 处理一个文件可以使用多个loader,loader的执行顺序和配置中的顺序是相反的,即最后一个loader最先执行,第一个loader最后执行
  2. 第一个执行的loader接收源文件内容作为参数,其它loader接收前一个执行的loader的返回值作为参数,最后执行的loader会返回此模块的JavaScript源码 ```bash // 进入webpack工程中 是你自己的目录地址 npm install /force-strict-loader

// 修改webpack配置 / module: { rules: [ test:/.js$/, use: ‘force-strict-loader’ options: { // 可以自定义参数 } ] } /

  1. ```javascript
  2. // mkdir force-strict-loader
  3. // npm init -y
  4. // create index.js
  5. // vi index.js
  6. var loaderUtils = require("loader-utils");
  7. var SourceNode = require("source-map").SourceNode;
  8. var SourceMapConsumer = require("source-map").SourceMapConsumer;
  9. module.exports = function (content, sourceMap) {
  10. if (this.cacheable) {
  11. this.cacheable();
  12. }
  13. var useStrictPrefix = '\'use strict\'; \n\n';
  14. // 获取options的方式
  15. var options = loaderUtils.getOptions(this) || {};
  16. console.log(options);
  17. if (options.sourceMap && sourceMap) {
  18. // 设置sourceMap的方式
  19. console.log("sourceMap");
  20. var currentRequest = loaderUtils.getCurrentRequest(this);
  21. var node = SourceNode.fromStringWithSourceMap(
  22. content,
  23. new SourceMapConsumer(sourceMap)
  24. );
  25. node.prepend(useStrictPrefix);
  26. var result = node.toStringWithSourceMap({
  27. file: currentRequest
  28. });
  29. var callback = this.async();
  30. callback(null, result.code, result.map.toJSON());
  31. }
  32. return useStrictPrefix + content;
  33. }


什么是plugin

在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果。

loader和plugin的区别

对于loader,它是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将A.scss转换为A.css,单纯的文件转换过程
plugin是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务
https://webpack.docschina.org/concepts/plugins/
https://v4.webpack.docschina.org/api/compiler-hooks/#root 4 compiler
https://webpack.docschina.org/api/compiler-hooks/#root 5 compiler
https://webpack.docschina.org/api/ compiler 介绍

  1. class MyPlugin{
  2. constructor(options){
  3. console.log("MyPlugin constructor:", options);
  4. }
  5. apply(compiler) {
  6. if (compiler.hooks) {
  7. // 钩子
  8. // https://www.webpackjs.com/api/compiler-hooks/
  9. // 新版本 webpack 5.x
  10. compiler.hooks.compile.tap('MyPlugin', params => {
  11. console.log('以同步方式触及 compile 钩子。一个新的编译(compilation)创建之后')
  12. })
  13. compiler.hooks.done.tap('MyPlugin', params => {
  14. console.log('以同步方式触及 compile 钩子。编译完成时')
  15. })
  16. } else {
  17. // 旧版本
  18. // console.log(compiler);
  19. compiler.plugin("compilation", compilation => {
  20. console.log("MyPlugin");
  21. });
  22. }
  23. }
  24. }
  25. module.exports = MyPlugin;
  26. // webpack.config.js配置:
  27. module.exports = {
  28. //...
  29. plugins: [
  30. new MyPlugin({param: "my plugin"})
  31. ]
  32. }

使用该plugin后,执行的顺序:

  1. webpack启动后,在读取配置的过程中会执行new MyPlugin(options)初始化一个MyPlugin获取其实例
  2. 在初始化compiler对象后,就会通过compiler.plugin(事件名称,回调函数)监听到webpack广播出来的事件
  3. 并且可以通过compiler对象去操作webpack

webpack plugins

  1. const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin')
  2. const HtmlWebpackPlugin = require('html-webpack-plugin'); // 自动生成index.html
  3. // 自动清理,清理dist旧文件
  4. // const CleanWebpackPlugin = require('clean-webpack-plugin');
  5. // 升级版本后,自动清理,清理dist旧文件
  6. const {CleanWebpackPlugin} = require('clean-webpack-plugin');
  7. module.exports = {
  8. //...
  9. plugins: [
  10. // 在js中使用_ , 不需要导入
  11. new webpack.ProvidePlugin({
  12. // _: 'lodash'
  13. join: ['lodash', 'join'], // 这种方式会引入 lodash.join方法 而不会加载其他的方法,按需加载效果好
  14. }),
  15. // 替换公共值
  16. new webpack.DefinePlugin({
  17. 'process.env.BASE_BUILD': `'${process.env.BASE_BUILD}'`
  18. }),
  19. new ServiceWorkerWebpackPlugin({
  20. // 注意这个项,打包时这个会加上webpack output.path
  21. // 期望生成目录时 /static 目录
  22. filename: '../../../static/hibobi-service-sw.js',
  23. entry: path.resolve(__dirname, './static/service-sw.js')
  24. }),
  25. new CleanWebpackPlugin(), // 自动删除webpack output 对应目录
  26. new HtmlWebpackPlugin({
  27. title: 'VISION-CANVAS-L', // 设置输出文件标题名
  28. filename: 'index.html', // 设置输出文件名
  29. template: 'view/index.html', // 设置模板
  30. })
  31. ]
  32. }