9. loader

101 阅读2分钟

webpack做的事情,仅仅是分析出各种模块的依赖关系,然后形成资源列表,最终打包生成到指定的文件中。 更多的功能需要借助webpack loaders和webpack plugins完成。

webpack loader: loader本质上是一个函数,它的作用是将某个源码字符串转换成另一个源码字符串返回。

2020-01-13-10-39-24.png

loader函数的将在模块解析的过程中被调用,以得到最终的源码。

全流程: 2020-01-13-09-28-52.png

chunk中解析模块的流程: 2020-01-13-09-29-08.png

chunk中解析模块的更详细流程: 2020-01-13-09-35-44.png

处理loaders流程: 2020-01-13-10-29-54.png

loader配置:

完整配置

module.exports = {
    module: { //针对模块的配置,目前版本只有两个配置,rules、noParse
        rules: [ //模块匹配规则,可以存在多个规则
            { //每个规则是一个对象
                test: /\.js$/, //匹配的模块正则
                use: [ //匹配到后应用的规则模块
                    {  //其中一个规则
                        loader: "模块路径", //loader模块的路径,该字符串会被放置到require中
                        options: { //向对应loader传递的额外参数

                        }
                    }
                ]
            }
        ]
    }
}

简化配置

module.exports = {
    module: { //针对模块的配置,目前版本只有两个配置,rules、noParse
        rules: [ //模块匹配规则,可以存在多个规则
            { //每个规则是一个对象
                test: /\.js$/, //匹配的模块正则
                use: ["模块路径1", "模块路径2"]//loader模块的路径,该字符串会被放置到require中
            }
        ]
    }
}

配置案例

  1. 下面的loader1 - 3都是自己编写的loader
module.exports = {
    mode: "development",
    module: {
        rules: [
            {
                test: /index\.js$/, //正则表达式,匹配模块的路径
                use: ["./loaders/loader1", "./loaders/loader2"] //匹配到了之后,使用哪些加载器
            }, //规则1
            {
                test: /\.js$/, //正则表达式,匹配模块的路径
                use: ["./loaders/loader3", "./loaders/loader4"] //匹配到了之后,使用哪些加载器
            } //规则2
        ], //模块的匹配规则
    }
}

  1. 自己编写的处理样式的loader
module.exports = {
    mode: "development",
    devtool: "source-map",
    module: {
        rules: [{
            test: /\.css$/,
            use: ["./loaders/style-loader"]
        }]
    }
}

module.exports = function (sourceCode) {
    var code = `var style = document.createElement("style");
    style.innerHTML = \`${sourceCode}\`;
    document.head.appendChild(style);
    module.exports = \`${sourceCode}\``;
    return code;
}


  1. 自己编写的处理图片loader
module.exports = {
    mode: "development",
    devtool: "source-map",
    module: {
        rules: [
            {
                test: /\.(png)|(jpg)|(gif)$/, use: [{
                    loader: "./loaders/img-loader.js",
                    options: {
                        limit: 3000, //3000字节以上使用图片,3000字节以内使用base64
                        filename: "img-[contenthash:5].[ext]"
                    }
                }]
            }
        ]
    }
}

var loaderUtil = require("loader-utils")

function loader(buffer) { //给的是buffer
    console.log("文件数据大小:(字节)", buffer.byteLength);
    var { limit = 1000, filename = "[contenthash].[ext]" } = loaderUtil.getOptions(this);
    if (buffer.byteLength >= limit) {
        var content = getFilePath.call(this, buffer, filename);
    }
    else{
        var content = getBase64(buffer)
    }
    return `module.exports = \`${content}\``;
}

loader.raw = true; //该loader要处理的是原始数据

module.exports = loader;

function getBase64(buffer) {
    return "data:image/png;base64," + buffer.toString("base64");
}

function getFilePath(buffer, name) {
    var filename = loaderUtil.interpolateName(this, name, {
        content: buffer
    });
    this.emitFile(filename, buffer);
    return filename;
}