loader在webpack打包流程中,有着比较重要的地位,很多资源类型需要经过loader的转化改变成浏览器能够识别的资源类型。

1,loader的本质是一个node模块,它输出了一个函数,当某个资源需要用这个loader转换时,该函数就会被调用。

形式如下:

module.exports  = function(src){
  //可以通过 this 访问Loader API
  //this是由webpack提供的,可以直接使用
}

第一个 loader 的传入参数只有一个:资源文件(resource file)的内容。compiler 需要得到最后一个 loader 产生的处理结果。这个处理结果应该是 String 或者 Buffer(被转换为一个 string),代表了模块的 JavaScript 源码。另外还可以传递一个可选的 SourceMap 结果(格式为 JSON 对象)。

如果是单个处理结果,可以在同步模式中直接返回。如果有多个处理结果,则必须调用 this.callback()。在异步模式中,必须调用 this.async(),来指示 loader runner 等待异步结果,它会返回 this.callback()回调函数,随后 loader 必须返回 undefined 并且调用该回调函数。

2,loader分为同步loader和异步loader

同步loader  sync-loader.js

module.exports = function(content, map, meta) {
  return someSyncOperation(content);
};

异步loader  async-loader.js

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);
  });
};

3,loader实例

使用const loaderUtils = require('loader-utils');获取loader的配置项

module.exports = function(source) {
  // 通过 this.callback 告诉 Webpack 返回的结果
  this.callback(null, source, sourceMaps);
  // 当你使用 this.callback 返回内容时,该 Loader 必须返回 undefined,
  // 以让 Webpack 知道该 Loader 返回的结果在 this.callback 中,而不是 return 中 
  return;
};
this.callback(
    // 当无法转换原内容时,给 Webpack 返回一个 Error
    err: Error | null,
    // 原内容转换后的内容
    content: string | Buffer,
    // 用于把转换后的内容得出原内容的 Source Map,方便调试
    sourceMap?: SourceMap,
    // 如果本次转换为原内容生成了 AST 语法树,可以把这个 AST 返回,
    // 以方便之后需要 AST 的 Loader 复用该 AST,以避免重复生成 AST,提升性能
    abstractSyntaxTree?: AST
);

转换异步:

module.exports = function(source) {
    // 告诉 Webpack 本次转换是异步的,Loader 会在 callback 中回调结果
    var callback = this.async();
    someAsyncOperation(source, function(err, result, sourceMaps, ast) {
        // 通过 callback 返回异步执行后的结果
        callback(err, result, sourceMaps, ast);
    });
};

处理二进制数据:

module.exports = function(source) {
    // 在 exports.raw === true 时,Webpack 传给 Loader 的 source 是 Buffer 类型的
    source instanceof Buffer === true;
    // Loader 返回的类型也可以是 Buffer 类型的
    // 在 exports.raw !== true 时,Loader 也可以返回 Buffer 类型的结果
    return source;
};

// 通过 exports.raw 属性告诉 Webpack 该 Loader 是否需要二进制数据 
module.exports.raw = true;

以上代码中最关键的代码是最后一行 module.exports.raw = true ,没有该行 Loader 只能拿到字符串。

4,编写一个loader

在项目根目录建一个loaders文件夹

webpack中配置:ResolveLoader

module.exports = {
  resolveLoader:{
    // 去哪些目录下寻找 Loader,有先后顺序之分
    modules: ['node_modules','./loaders/'],
  }
}

或者使用npm link


1,确保正在开发的本地 Npm 模块(也就是正在开发的 Loader)的 package.json 已经正确配置好;
2,在本地 Npm 模块根目录下执行 npm link,把本地模块注册到全局;
3,在项目根目录下执行 npm link loader-name,把第2步注册到全局的本地 Npm 模块链接到项目的 node_moduels 下,
   其中的 loader-name 是指在第1步中的 package.json 文件中配置的模块名称。

上面两种方法是用来调试本地loader

编写去除console.log()调试代码

delete-console-loader

function deleteConsole(content){
    return content.replace('console','//console')
}


module.exports = function(source){
    return deleteConsole(source)
}

参考:https://blog.csdn.net/wu5229485/article/details/96475954

https://www.jianshu.com/p/cb888d69ca34

 

 

 

 

 

 

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐