看完就会的webpack loader开发

379 阅读3分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

webpack使用时间久了,只是会使用loader已经不能让我起飞了。为了在兄弟们面前吹上一把,我决定彻底撸会webpack loader开发。

废话不多说,如果还有对loader使用不太清楚的,建议先去看一下 loader教程 ,不然会让我唠的云里雾里的。

开发loader的正确姿势

编写 loader 时应该遵循以下准则。它们按重要程度排序,但是有些仅适用于某些特殊场景。

  • 简单易用
  • 使用链式传递。
  • 模块化的输出。
  • 确保无状态
  • 使用 loader utilities
  • 记录 loader 的依赖
  • 解析模块依赖关系
  • 提取通用代码
  • 避免绝对路径
  • 使用 peer dependencies

姿势摆好,正式开撸

  1. 入口文件

webpack是基于node环境的,所以我们开发loader的时候,使用commonJs开发规范。

    module.exports = function (source) {
        // 处理 source ...
        return newSource;
    }

需要特别注意的地方

返回的source必需是 string 或者 buffer 类型

module.exports导出的方法不能使用箭头函数,如果使用箭头函数,this将指向global;正常情况下,this指向调用上下文,也就是webpack执行 runLoaders 的时候,传入的loaderContext

  1. 获取loader的options

相信大家配置webpack的rules的时候,肯定或多或少的时候了loader的options属性,那么loader中又是如何拿到大家配置的options呢?下面我们就一起看一下getOptions这个方法。

没错,我承认了,getOptions这个方法就是用来获取配置的options的,那这个方法从哪里获取呢,就是我们前文说到的this上。

当然,还有一种方式哈,可以通过 loader-utils 提供的 getOptions 方法获取。

虽然说结果是一样的,但是小编比较推荐第二种(webpack上dome是这样的,不是乱说的)

  1. 利用缓存

对于某些处理资源非常消耗性能的,推荐使用缓存进行优化。使用缓存之后,如果需要处理的资源和依赖的资源没有发生变化,生成的结果必然是相同的

    // 开启缓存
    this.cacheable(false)
    
    // 关闭缓存
    this.cacheable(true)
  1. 异步方法

通过async方法告诉 webpack 本次转换是异步的,并获取到 callback 方法

    const callback = this.async();

然后,在 webpack 异步执行完成之后,通过 callback 方法,将转换结果通知到 webpack

    callback(err, result, ...);
  1. loader 依赖

如果一个 loader 使用外部资源(例如,从文件系统读取),必须声明它。这些信息用于使缓存 loaders 无效,以及在观察模式(watch mode)下重编译。

    const headerPath = path.resolve('header.js');
    
    this.addDependency(headerPath);

如果不添加this.addDependency的话项目并不会报错,只是在观察模式下,如果依赖的文件发生了变化生成的bundle文件并不能及时更新。

测试姿势

本地调试loader的三种方法

  1. 单个 loader,你可以简单通过在 rule 对象设置 path.resolve 指向这个本地文件
{
    test: /.js$/
    use: [
        {
            loader: path.resolve('path/to/loader.js'),
            options: {/* ... */}
        }
    ]
}
  1. 多个 loaders,你可以使用 resolveLoader.modules 配置,webpack 将会从这些目录中搜索这些 loaders
resolveLoader: {
    modules: [
        'node_modules',
        path.resolve(__dirname, 'loaders')
    ]
}
  1. npm link

首先在打包好的loader项目中执行 npm link命令,然后在测试的项目中通过 npm link xxx 的方式将loader引入,接下来就可以跟npm install安装的依赖一样使用了