likes
comments
collection
share

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简

作者站长头像
站长
· 阅读数 29

🕵️‍♂️前面两篇分析了webpack的编译结果和编译过程,可以看出,webpack做的事情,仅仅是分析出各种模块的依赖关系,然后形成资源列表,最终打包生成到指定的文件中。 🌟而更多的功能需要借助webpack loaders和webpack plugins完成。

先看一下官网对loader的解释:Loaders | webpack

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

上面一段话我的理解是,loader是用来预处理的

下面进入正文

webpack loader

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

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简

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

上篇文章中有webpack编译的全流程,其中有chunk中解析模块的流程

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简

事实上,chunk中解析模块还有更详细的流程:

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简

上图可以看到,loaders数组运行是从下往上的(从后往前),loader一次运行,经过loader处理过返回的代码交给上一个,最后交给抽象语法树。

module.exports = {
    module: { //针对模块的配置,例如rules、noParse(是否不要解析某个模块)
        rules: [ //模块匹配规则,可以存在多个规则
            { //每个规则是一个对象
                test: /\.js$/, //正则,匹配模块的路径
                use: [ //匹配到后应用的规则模块(匹配到之后使用哪些loaders)
                    {  //其中一个规则
                        loader: require('...'), //loader模块(加载器)的路径
                        options: { //向对应loader传递的额外参数(自己写loader时才需要)
                        }
                    } // 每个加载器的使用是一个对象
                ]
            }
        ]
    }
}

扩展

自己写一个loader,感受一下loader的运行过程

先来个最简单的:

./src/index.js

AAA a = 1;

./loaders/my-loader.js

module.exports = function(sourceCode){
    // sourceCode: AAA a = 1;
    console.log("test-loader运行了")
    return sourceCode.replace(/AAA/g, "var")
}

这就是一个简单的loader,可以进行匹配AAA转化为var的预处理

./webpack.config.js

const path = require('path');
module.exports = {
  mode: "development",
  module: {
    rules: [
      {
        test: /index\.js$/, //匹配index.js
        use: [
          {
            loader: path.resolve(__dirname, './loaders/my-loader.js')
          }
        ]
      }, 
    ], //模块的匹配规则
  }
}

打包:

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简 打包出来的main.js中,AAA已经替换为var

进阶版-多个loader的执行顺序

目录结构:

|—— project
    |—— loaders   
        |—— loader1.js 
        |—— loader2.js 
        |—— ...
    |——src   
        |—— index.js 
        |—— ...
    |——webpack.config.js 

这个示例主要是为了感受多个loader的执行顺序,所以loader只写简单的输出,例如loader1:

module.exports = function(sourceCode){
    console.log("loader1");
    return sourceCode;
}

webpack.config.js

module.exports = {
    mode: "development",
    module: {
        rules: [
            {
                test: /index\.js$/, //正则表达式,匹配模块的路径
                use: ["./loaders/loader1", "./loaders/loader2"] //匹配到了之后,使用哪些加载器
                // 这里是简化的写法,字符串会被放到require里
            }, //规则1
            {
                test: /\.js$/, //正则表达式,匹配模块的路径
                use: ["./loaders/loader3", "./loaders/loader4"] //匹配到了之后,使用哪些加载器
            } //规则2
        ], //模块的匹配规则
    }
}

打包:

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简

可以看到,在rules中,两个规则均能匹配到index.js,顺序是从loader1到loader4。而打包的输出是相反的:

开始时,loader数组为空数组[]。在匹配时,先匹配到了规则1,加入loader数组:["loader1", "loader2"],之后规则2也匹配到,两个数组合并为["loader1", "loader2","loader3", "loader4"],这些loader加载出来都是一个函数。

使用这些loader时,是从后往前的,文件内容先交给loader4,loader4返回的内容交给loader3...

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简 所以输出的顺序为4-3-2-1。

那么,如果index.js有依赖关系,loader的运行顺序怎么判断呢?

在src中新增一个a.js文件,并在index.js引入a.js

// ./src/index.js
require("./a");

打包:

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简

过程分析:

Webpack——loader的运行过程loader是用来预处理的,本文使用流程图分析loader的运行过程,并自定义简 参考文章最开始的chunk解析流程图,入口模块为index.js,先运行入口模块进行loader,使用index.js与规则进行匹配,都能匹配到,于是像上个示例一样先输出loader4-loader3-loader2-loader1

接下来进行抽象语法树分析、记录依赖的a.js,替换依赖函数,处理依赖(即为处理a.js模块)

然后读取a.js的文件内容,处理loaders,使用a.js与规则进行匹配,只能匹配到["loader3", "loader4"],从后往前运行,输出loader4-loader3

所以最终输出顺序为4-3-2-1-4-3

注:以上自定义loader仅用于帮助理解loader的处理过程,在实际开发中一般不会自定义loader

转载自:https://juejin.cn/post/7382223729198579746
评论
请登录