webpack的自定义loader

152 阅读2分钟

自定义loader

1.什么是loader

loader对Webpack原生无法处理的内容进行处理(CSS 图片等),将源文件经过传化后输出能被webpack处理的新内容,并且可以进行链式操作。

2.使用方法

在webpack.config.js中配置处理规则,例如处理SCSS

module.exports = {
  module: {
    rules: [
      {
        // 增加对 less 文件的支持
        test: /.less/,
        // less 文件的处理顺序为先 less-loader 再 css-loader 再 style-loader
        use: [
          'style-loader',
          {
            loader:'css-loader',
            // 给 css-loader 传入配置项
            options:{
              minimize:true, 
            }
          },
          'less-loader'],
      },
    ]
  },
};
  1. less 源代码会先交给 less-loader 把 less 转换成 CSS
  2. 然后把 less-loader 输出的 CSS 交给 css-loader 处理,找出 CSS 中依赖的资源、压缩 CSS 等
  3. 最后将 css-loader 输出的内容交给 style-loader 处理,转换成 style 将 CSS 插入到HTML页面中

编写时的顺序和真正加载时的顺序是相反的,最后use的loader最先使用

3. 自定义loader的模板

loader 本质上是一个函数,对输入的资源进行处理,返回处理之后的结果 同步:

const { getOptions } = require('loader-utils')

module.exports = function (source) {
    let options = getOptions(this)
    const result = source.replace("hello", "您好");

    return result;
}

callback法:

module.exports = function (source) {
  // 处理 source
  const content = source.replace("hello", "哈哈");
  // 使用 this.callback 返回内容
  this.callback(null, content);
  // 使用 this.callback 返回内容时,该 loader 必须返回 undefined,
  // 以让 Webpack 知道该 loader 返回的结果在 this.callback 中,而不是 return 中 
  return
};

异步

我们可以使用 webpack 为 loader 提供的 this.async() 将这个 loader 变成是一个异步 loader:

module.exports = function (source) {
  // 调用 this.async() API,告诉 webpack本次转换是异步的,loader 会在 callback 中返回结果 
  const callback = this.async();
  // 使用 setTimeout 模拟异步过程
  setTimeout(() => {
    const content = source.replace("hello", "哈哈");
    // 通过 callback 返回执行异步后的结果
    callback(null, content);
  }, 3000);
};

4.怎么配置自定义loader

1. 直接指定路径

直接在loader中确认路径

{
                test: /\.js$/,
                use: [
                    {
                        loader: path.resolve(__dirname, "loaders/replace-loader.js"),
                        options: {
                            name: "abc"
                        }
                    }
                ]
            }

2. 写loader名

假设loader 放在 ./myLoaders 目录下:

module.exports = {
    resolveLoader: {
    // 去哪些目录下寻找 loader ,有先后顺序之分
    // 如下配置中,查找顺序是:先在 node_modules 目录下寻找,若找不到,再到 ./myLoaders 目录下寻找
    modules: ["node_modules", "./myLoaders"],
  },
}