webpack loader 转换器

380 阅读2分钟

定义

webapck loader 是一种将所有类型的文件,转换为应用程序的依赖图(和最终的bundle)可以直接引用的模块的函数,然后利用webpack的打包能力,对它们进行处理。

简单用法

当一个loader在资源中使用,这个loader只能传入一个参数 —— 一个包含资源文件内容的字符串同步loader可以简单的返回一个代表模块转化后的值。在更复杂的情况下,loader也可以通过使用this.callback(err, values...) 函数,返回任意数量的值。错误要么传递给这个this.callback 函数,要么扔进同步loader中。loader会返回一个或者两个值。第一个值的类型是JavaScript 代码的字符串或者buffer。第二个参数值是SourceMap,它是个JavaScript 对象

复杂用法

当链式调用多个loader的时候,请记住它们会以相反的顺序执行。取决于数组写法格式,从右向左或者从下向上执行。

  • 最后的 loader 最早调用,将会传入原始资源内容。
  • 第一个 loader 最后调用,期望值是传出 JavaScript 和 source map(可选)。
  • 中间的 loader 执行时,会传入前一个 loader 传出的结果。

loader 用法和设计准则

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

制作loader

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

const schema = {
  type: 'object',
  properties: {
    test: {
      type: 'string'
    }
  }
};

module.exports =  function(source) {
  // javaScript 代码的字符串或buffer,具体参数是什么取决于loader间传参是什么
  console.log("打印source:", source);
  const options = getOptions(this);
  console.log("打印options:", options); // {}
  
  validateOptions(schema, options, 'Example Loader');
  // 对资源应用一些转换……
  // return `export default ${ JSON.stringify(source) }`;
  return source
};

用法

示例1:使用已安装loader

const path = require('path');
const config = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  resolveLoader: { // resolveLoader.modules 配置,webpack 将会从这些目录中搜索这些 loaders
  modules: [
    'node_modules',
    path.resolve(__dirname, 'loaders')
  ]
},
  module: {
    rules: [
      { 
        test: /\.txt$/, // 标识出应该被对应的 loader 进行转换的某个或某些文件
         use: 'raw-loader' // 表示进行转换时,应该使用哪个 loader
      },
      {
          test: /\.js$/
          use: [
                {
                  loader: path.resolve('path/to/loader.js'), // 使用本地loader
                  options: {/* ... */}
                }
              ]
      },
      { 
        test: /\.txt$/,
        use: 'a-loader'// 可以使用在resolveLoader查找到的a-loader
      },
    ]
  }
};
module.exports = config;

示例2:使用本地loader(略)