【webpack 从入门到使用】webpack 中的文件处理器 - loader

76 阅读3分钟

说明

  1. 这套笔记是对于 webpack 5.x 进行阐述的。(webpack <= 4 用法稍有不同)

概念:

loader 是 webpack 中的预处理器,loader 可以将许多不同后缀名的文件处理成浏览器可以识别运行的文件。

配置 loader

webpack.config.js 中,loader 在 config.module.rules 下面使用

{
  // ...
  module: {
    rules: [
      // sub loaders
    ]
  },
  ...
}

配置单个 loader

以配置 babel-loader 解析 *.js 文件为例:

  1. 安装 babel 相关的依赖
# 安装 babel 相关的依赖
npm install babel babel-loader @babel/core @babel/preset-env --save-dev
  1. webpack.config.js中配置 babel-loader
const config = {
  // ...
  module: {
    rules: [
      {
        test: /.js$/, // test -> 表示我要处理什么样的文件
        loader: 'babel-loader' // loader -> 表示我要用什么 loader 来处理上述的文件
      }
    ],
  }
};

module.exports = config;

总结一下:

  1. loadermodule.rules 下面配置
  2. 每个 loader 对应的配置项都是一个对象,对象里面需要说明 test(使用正则表达式表示需要处理什么后缀名的文件) 和 use(需要使用什么 loader 来进行处理)
  3. 如果没有其他的配置参数,use 可以直接是 loader 名称的字符串;如果有其它的参数,use需要配制成一个对象: { loader: 'xxx-loader', options: { /* 需要配置的参数 */ } }
  4. 如果一种后缀名的文件需要配置多个 loader,请参考下面 配置多个 loader

配置多个 loader

loader 从右到左(或从下到上)地取值(evaluate)/执行(execute)。

module.exports = {
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          // [style-loader](/loaders/style-loader)
          { loader: 'style-loader' },
          // [css-loader](/loaders/css-loader)
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          },
          // [sass-loader](/loaders/sass-loader)
          { loader: 'sass-loader' }
        ]
      }
    ]
  }
};

使用内联的方式配置 loader

上述的方式 (配置单个 loader配置多个 loader 都是在 webpack.config.js 中通用配置。

但是如果需要在单个文件中特殊配置 loader, 可以在 import 语句或任何 与 "import" 方法同等的引用方式 中指定 loader。使用 ! 将资源中的 loader 分开。每个部分都会相对于当前目录解析。

通过为内联 import 语句添加前缀,可以覆盖 配置 中的所有 loader, preLoader 和 postLoader 。

内联的方式配置 loader 的用法如下:

  • 使用 ! 前缀,将禁用所有已配置的 normal loader(普通 loader)
  • 使用 !! 前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader)
  • 使用 -! 前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders

loader 的特性

  • loader 支持链式调用。链中的每个 loader 会将转换应用在已处理过的资源上。一组链式的 loader 将按照相反的顺序执行。链中的第一个 loader 将其结果(也就是应用过转换后的资源)传递给下一个 loader,依此类推。最后,链中的最后一个 loader,返回 webpack 所期望的 JavaScript。
  • loader 可以是同步的,也可以是异步的。
  • loader 运行在 Node.js 中,并且能够执行任何操作。
  • loader 可以通过 options 对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。
  • 除了常见的通过 package.json 的 main 来将一个 npm 模块导出为 loader,还可以在 module.rules 中使用 loader 字段直接引用一个模块。
  • 插件(plugin)可以为 loader 带来更多特性。
  • loader 能够产生额外的任意文件。

可以通过 loader 的预处理函数,为 JavaScript 生态系统提供更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如:压缩、打包、语言转译(或编译)和 更多其他特性

如果我想写一个自己的 loader, 怎么做?

步骤说明

  1. webpack.config.js 配置一下 resolveLoader, 告诉 webpack :如果我想使用 loader, 它需要从哪里去获取
  2. 创建自定义文件在用来装载 loaders
  3. 写一个 loader 函数,并默认导出

举个例子

项目结构如下

|- src
    |- ... # 项目代码
|- webpack.config.js
|- loaders
    |- tpl-loader.js # 处理tpl的loader
    |- ... # 其他的loader

以处理 *.tpl 文件为例:

  1. 在 webpack.config.js 中编写接收额外的 loader 配置: resolveLoader
const path = require('path');

module.exports = {
  //...
  resolveLoader: {
    modules: [
      'node_modules', // 不要忘记写上 node_modules
      path.resolve(__dirname, 'loaders')
    ],
  },
};
  1. loaders文件下创建一个 loader 函数 my-tpl-loader, 他是一个提供给 webpack 使用的回调函数,形参接收的是文件的字符串内容,并返回需要输出的代码字符串
module.exports = function (source) {
  return `
    export default () => {

      return `${source}`;
    }
  `;
}
  1. 配置 loader 规则,添加对于 *.tpl文件的解析规则
const config = {
  // ...
  module: {
    rules: [
      {
        test: /.tpl$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', {
                  targets: {
                    browsers: ['last 2 versions', 'ie >= 11']
                  }
                }]
              ]
            }
          },
          'my-tpl-loader'
        ]
      }
    ]
  },
};

module.exports = config;