webpack loader

说明

webpack默认只能处理JavaScript和JSON文件,但前端项目中,文件类型多种多样.比如.vue、.ts、图片、.css等,这就需要各种各样的loader来处理各种文件,最后交给webpack的是js模块(通过loader来弥补webpack处理其他文件的能力)

loader的本质

loader 是导出为一个函数的 node 模块。该函数在 loader 转换资源的时候调用。
//最简单的一个loader,不处理任何文件,直接返回资源

function loader(source) {
    //  一个包含资源文件内容的字符串
    return source;
}
module.exports = loader;

loader 在webpack中的调用时机

Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程 :

1.初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
2.开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译。
3.确定入口:根据配置中的 entry 找出所有的入口文件。
4.编译模块:从入口文件出发,调用所有配置的 loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
5.完成模块编译:在经过第 4 步使用Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系。
6.输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
7.输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

在webpack中使用

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.less/,
        use: ['style-loader','less-loader'],
      },
    ],
  },
};

上面这段代码的意思是匹配后缀为.less的文件依次应用 less-loader=>style-loader

less-loader 的源码的大概样子

// less-loader.js

const less = require('less');
module.exports = function(source) {
    // this.async()表示该loader为异步loader
    const callback = this.async();
    // less 为node的一个模块 该模块的render函数接收两个参数,
    //  source为less文件的字符串,cd()函数为处理完的回调函数
    // render的作用就是把less变为css  也就是一个函数输入less输出css
    less.render(source, function(err, data) {
        callback(err, data.css)
    })
}

// style-loader.js

module.exports = function(source) {
    // source为已经转成的css代码
    // 1.动态的生成style标签
    let style = document.createElement('style');
    // 2.将css代码插入到style标签中
    style.innerHTML = JSON.stringify(source);
    // 3.将style标签插入到head标签中
    document.head.appendChild(style);
    let content= `
        let style = document.createElement('style');
        style.innerHTML = ${JSON.stringify(source)};
        document.head.appendChild(style);
    `;
    return content;
}

自己实现一个webpack loader

// replace-loader.js (将代码中的console.log(xxx)替换为控字符串)

module.export = function(source) {
    const result = source.replace(/console.log(.*)/g, '');
    return result;
}

loader在webpack中的作用

最后执行的loader(例如上面例子中的style-loader):让webpack能够处理非js文件(将非js模块转化为js模块)

中间执行的loader 可以返回一下一个loader能识别的字符格式就可以

loader的分类与用法

loader 分类

同步:

function loader(source) {
    //  一个包含资源文件内容的字符串
    return source;
}
module.exports = loader;

异步:

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

loader返回其他的结果

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

*/


raw loader

在默认的情况下,Webpack 传给 Loader 的原内容都是UTF-8格式编码的字符串。
但有些场景下 Loader 不是处理文本文件,而是处理二进制文件,例如 file-loader,就需要 Webpack 给 Loader 传入二进制格式的数据。 为此,你需要这样编写 Loader

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;

获得option

可以获得给Loader配置的options

const loaderUtils = require('loader-utils');
module.exports = function(source) {
  // 获取到用户给当前 Loader 传入的 options
  const options = loaderUtils.getOptions(this);
  return source;
};

完整API: https://webpack.js.org/api/loaders/

参考

https://juejin.cn/post/6844904038543130637

https://webpack.docschina.org/contribute/writing-a-loader/

https://indexsarrol.cn/2020/12/24/webpack-and-loader/

你可能感兴趣的:(webpack loader)