webpack loader自定义编写

loader

  • 文档定义

loader 用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!

  • 编写
    • 本质上一个loader就是一个node模块,也就是一个js文件。
    • 这个文件导出一个函数, 导出的这个函数接收一个 source参数, 用来接受,webpack传过来的文件源码
    • 这个函数返回一个新的source 供链式调用。
    • 以字符串替换为例, loader代码如下
const  loaderUtils = require('loader-utils')
module.exports = function (source) {
        const  options = loaderUtils.getOptions(this)  || {}
        const {key = 'like', value = '❤'} = options;
        const  re = new RegExp(key,'ig')
        const res = source.replace(re,value)
        return res
}
  1. loader-utilswebpack内置的模块, 不需要安装, 可以直接使用。
  2. 通过 loader-utils下的 getOptions方法,获取 webpack配置loader时的参数。
  • 自定义loader的使用
  1. 可以发布npm包(参考npm发布包的相关使用)
  2. 本地使用
  • 本地使用

  • 创建loader文件夹 专门存放自定义的loader文件

  • 由于webpack默认的loader是从 node_modules文件夹下查找的。所以需要配置路径, 让webpack能找到你本地的loader:

  • 有两个方式配置loader路径

     module:{
            rules:[
                    {
                            test:/\.js$/,
                            use:[
                                    {
                                            loader:path.resolve('./loader/k-loader.js'),
                                            options:{
                                                    value:'LIKE'
                                            }
                                    }
                            ]
                    }
            ]
     }
    

    通过webpack的 resolveLoader扩展 loader目录。

     resolveLoader:{
    modules:[
            'node_modules',
            path.resolve(__dirname, './loader')
    ]
    },
    module:{
    rules:[
            {
                    test:/\.js$/,
                    use:[
                            {
                                    loader:'k-loader', 
                                    options:{
                                            value:'LIKE'
                                    }
                            }
                    ]
            }
    ]
    }
    
  • 返回多个值

    • 上面的loader返回了一个结果。有些场景下 需要返回多个值, 可以用 this.callback()来返回多个值。
     module.exports = function(source) {
      this.callback(err|| null, source, sourceMap,meta)
      return; // 当调用 callback() 时总是返回 undefined
     }
    
    1. 第一个参数是 Error或者null
    2. 第二个参数是 String或 BUffer
    3. 第三个必须是一个可以被这个模块解析的 source map。【可选】
    4. 会被 webpack 忽略,可以是任何东西比方元数据。 【可选】
  • 同步&异步

  1. 无论是return 还是 this.callback都可以同步的返回转换后的content内容。this.callback方法更灵活,可以传递更多参数。
  2. 对于异步loader, 使用this.async 获取callback函数
  module.exports = function(content, map, meta) {
    var callback = this.async();
    someAsyncOperation(content, function(err, result) {
      if (err) return callback(err);
      callback(null, result, map, meta);
    });
  };
<!-- 多个返回值-->
module.exports = function(content, map, meta) {
  var callback = this.async();
  someAsyncOperation(content, function(err, result, sourceMaps, meta) {
    if (err) return callback(err);
    callback(null, result, sourceMaps, meta);
  });
};