原文地址

编写 loader 和 plugins

github

一、loader

1.loader 介绍

loader 是什么

loader 作用

  • loader 的执行是有顺序的,支持链式的调用。loader的执行顺序是从下到上,从右到左。比如处理样式类的文件,use:['style-loader', 'css-loader']css-loader处理后的文件返回给 style-loader
  • 一个 Loader 的职责是单一的,只需要完成一种转换。
  • Webpack 会默认缓存所有 Loader 的处理结果,对没有修改的 loader 不会重新加载,关闭webpack 的默认缓存结果需要添加this.cacheable(false);

常见的loader

  • 样式类的 loader:css-loader, style-loader, less-loader, postcss-loader(添加-webkit)
  • 文件类的 loader:url-loader, file-loader, raw-loader等。
  • 编译类的 loader:babel-loader, ts-loader
  • 校验测试类 loader:eslint-loader, jslint-loader

4. loader 的三种使用方式

    1. webpack.config.js 中配置

      module.exports = {
        module:{
         rules:[{
                 test:/\.css$/,
                 use:['css-loader'],
                 // use:{loader:'css-loader',options:{}}
             }
         ]
        }
      }
    1. 通过命令行的参数方式

      webpack --module-bind 'css=css-loader'
    1. 通过内联使用

      import txt from 'css-loader!./file.css';

2. 编写一个 loader

// 在 ./loader/replaceLoader.js 创建一个替换字符串的 loader
module.exports = function(source) {
    return source.replace('a', 'b')
}

// 在webpack.config.js 使用 自己写的loader
module.exports = {
    module:{
        rules:[{
            test:"/\.js$/",
            use:[{
                    loader: path.resolve(__dirname, './loader/replaceLoader.js')
                    options:{
                        name: '林一一'
                    }
                }
            ]
        }]
    }
}

// 或者使用 replaceLoader
module.exports={
    resolveLoader:['node_modules', './loader']
    module:{
        rules:[{
            test:"/\.js$/",
            use:['resolveLoader']
        }]
    }
}
  • loader 还可以接收 options 传入的参数,详情查看 loader API,也可以使用官方提供的 loader-util 接收参数

    const loaderUtil = require('loader-utils')
    module.exports = function(source) {
      console.log(this.query.name) // 林一一
      const options = loaderUtil.getOptions(this)
      return source.replace('a', 'b')
    }
  • 异步:loader 是一个函数自然有同步和异步的区分。使用异步的loader需要添加 this.async() 申明异步操作

    const loaderUtils = require('loader-utils')
    module.exports = function(source) {
      const options = loaderUtils.getOptions(this)
      const callback = this.async()
      setTimeout(()=>{
          console.log(options.name)
          let res = source.replace('a', options.name)
          callback(null, res, sourceMaps, ast)
      }, 4000)
    }
  • 默认情况下 webpack 给 loader 传递的字符串编码是 utf-8,如果需要处理二进制的文件需要添加exports.raw = true
  • 上面提到过 webpack 会默认将loader的加载结果缓存如果需要关闭webpack的缓存结果需要添加this.cacheable(false);
  • Npm link 专门用于开发和调试本地 Npm 模块,在没有发布到 npm 上面也可以在调式本地的loader。具体需要在package.json 中配置 本地loader,在根目录下执行npm link loader-name 就可以在node_modules中使用本地的loader了。同时也可以采用上面的resolveLoader 实现导入 loader 的方式

总结编写 loader 的思路

二、webpack 的构建流程

  1. 初始化参数。从配置文件和 shell 语句中合并的参数
  2. 开始编译。将上一步得到的参数初始化成 complier对象,加载所有的导入插件,执行对象的 run 方法开始执行编译;
  3. 确定入口。从配置的 entry 入口找出所有的入口文件。
  4. 编译模块。根据入口文件的依赖,调用所有配置的loader进行转换。
  5. 完成模块编译并输出。根据入口文件之间的依赖关系,形成一个个代码块 chunk
  6. 输出完成。将形成的代码块 chunk 输出到文件系统。

三、plugin

1 plugin 介绍

plugin 是什么

plugin 作用

常见的 plugin

  • html-webpack-plugin 会在打包后自动生成一个 html 文件,并且会将打包后的 js 文件引入到html 文件内。
  • optimize-css-assets-webpack-plugin 对CSS 代码进行压缩。
  • mini-css-extract-plugin。将写入 style 标签内的 css 抽离成一个 用 link 导入 生成的 CSS 文件
  • webpack-parallel-uglify-plugin。开启多进程执行代码压缩,提高打包的速度。
  • clean-webpack-plugin。每次打包前都将旧生成的文件删除。
  • serviceworker-webpack-plugin。为网页应用增加离线缓存功能。

plugin 的使用方式

const ServiceworkerWebpackPlugin = require('serviceworker-webpack-plugin')
module.exports = {
    plugins:[
        new ServiceworkerWebpackPlugin(),
    ]
}

2 编写一个 plugin

class MyPlugin {
    constructor(params){
        console.log(params)
    }
    // webpack 初始化参数后会调用这个引用函数,闯入初始化的 complier对象。
    apply(complier){
         // 绑定钩子事件
        // complier.hooks.emit.tapAsync()
        compiler.plugin('emit', compilation => {
            console.log('MyPlugin')
        ))
    }
}
module.export = MyPlugin

总结编写 plugin 的思路

四、面试题

1. loader 和 plugin 的区别

2. loader 的编写思路

3. plugin 的编写思路

4. complier 和 compilation 区别

参考

webpack之loader和plugin简介

webpack 构建流程

webpack loader和plugin编写

深入Webpack-编写Loader

03-06 00:07