【webpack核心】- 10、loader-1理论 -转换代码

  • webpack做的事情,仅仅是分析出各种模块的依赖关系,然后形成资源列表,最终打包生成到指定的文件中
  • webpack也不知道我们需要什么样的功能,所以更多的功能需要借助webpack loaders-加载器webpack plugins- 插件完成。
  • loders 和 plugins是webpack的扩展,webpack只是打包、合并,更过的功能需要用loders 和 plugins去扩展。

1、什么是 webpack loader-加载器

loader本质上是一个函数,它的作用是将某个源码字符串转换成另一个源码字符串返回
在这里插入图片描述

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

loader的出现

npm init -y 
npm i webpack webpack-cli -D 

入口文件src/index.js里写如下内容,然后npx webpack运行,报错如下:

// var a = 1; 
变量 a = 1; 

在这里插入图片描述

  • 变量 a = 1; webpack把这句话当作js来解析,不是运行,是解析,解析时遇到了一些看不懂的东西
  • webpack中解析模块的过程中,抽象语法树 这一步发生了错误,因为上面的代码不合法,解析不出来抽象语法树,所以直接在打包文件中抛出错误
    在这里插入图片描述
  • 如果我们就想这样写,在打包时将其视为正确代码,webpack提供了扩展机制,让用户可以进行配置 – 使用loader
  • loader本质上就是一个函数,通常我们把loader写成一个一个模块

2、手写test-loader

这就是一个loader/一个模块,它导出一个函数,这个函数传入一个参数sourceCode,然后返回一个字符串

module.exports = function(sourceCode){    //导出一个函数,这个函数传入一个参数sourceCode --源码字符串
    //sourceCode: 变量 a = 1;
    return sourceCode.replace(/变量/g,"var");    //返回一个字符串,使用字符串的replace方法,进行替换	--loader就是这样,将源码字符串进行处理返回新的字符串
}

webpack 打包过程中会调用loader这个函数,调用函数的时候,会把源代码做为字符串传进来,然后函数返回新的代码格式,然后webpack拿这个新的代码格式去做抽象语法树分析

1、webpack全流程:

在这里插入图片描述

  1. 根据配置分成很多个chunk
  2. 每个chunk根据一个或者几个入口模块分析出依赖的模块,然后生成资源列表
  3. 最终按资源列表打包生成文件

chunk解析出依赖的模块,形成一个个模块(模块列表),然后把这些模块打包,捆绑到一起,形成一个单独的js文件 – bundle(捆)

2、chunk中解析模块的流程(解析模块的具体流程):

在这里插入图片描述
所以loader的位置在 上图中 读取文件内容后,–把文件内容读出来,然后把文件内容传递给loader函数,然后拿loader函数的返回结果,去做抽象语法树分析

我们按上面的写法写好loader,还需要应用进webpack打包过程中,否则webpack不知道这是个loader,不知道要去调用loader这个函数,那我们怎么告诉webpack哪个是需要用到的loader?

3、chunk中解析模块的更详细流程

在这里插入图片描述

[4-重要]、处理loaders流程:

在这里插入图片描述

  1. 判断规则,看模块是否需要loader来处理,并不是每个模块都需要loader来处理,如果不需要则得到一个loaders的空组,循环的时候,不会做任何处理,就会把源代码拿去做AST 语法树分析
  2. 根据配置的规则,如果需要loader来处理,则从规则里读取出一个loaders数组,loaders数组里,每个loader都是一个函数
  3. 读取到loaders数组后,让里面的每一个loader函数去处理:把文件内容交个数组里的最后一个loader,然后将loader返回的代码,交给上一个代码,直至第一个loader处理后,得到一个最终的代码,然后进行抽象语法树分析
    在这里插入图片描述

3、loader配置:

1、完整配置

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

                        }
                    }
                ]
            }
        ]
    }
}
  1. module:{} 针对模块的配置 ---- 在这个对象里配置模块怎么去解析,解析时用到哪些loader,目前只有rules、noParse两个配置

  2. rules:[] 模块的匹配规则 ---- 是一个数组,webpack根据这里规则判断模块是否需要用到规则中的loaders
    在这里插入图片描述

module:{
	rules:[
		{},//规则1,每个规则都是一个对象
		{
			test:/index\.js$/, //test属性,属性值是正则表达式,匹配模块的路径
			use:[
				{},//每个加载器的使用是一个对象
				{
					loader:'./loaders/test-loader'  //加载器的路径,webpack会自动用require加载 loader加载器里的内容
					options:{    //给loader写的参数,自定义的内容
						changevar:'未知数'
					}
				}
			],  //匹配到后,使用哪些加载器,use数组里是一项项要用到的加载器
		}//规则2
	], //模块匹配的规则,从下往上匹配,先看是否需要规则2,然后再看规则1
}
  1. rules数组里是一个个规则,每个规则都是一个对象模块匹配的规则,从下往上匹配,先看是否需要规则2,然后再看规则1
  2. test:正则表达式 – 规则里的test属性匹配模块的路径。eg:拿入口文件的路径./src/index.js和正则表达式/index\.js$/匹配上,就要使用对应的loaders
  3. use:[] use数组里是一项项用到的加载器`匹配到后,使用哪些加载器,每一项(每个加载器的使用)是一个对象
  4. use:[ { loader:'./loaders/test-loader' //加载器的路径,webpack会自动用require加载 loader加载器里的内容 },{} ]
  5. noParse 是否不要匹配某个规则
module.exports = {
    mode: "development",
    module: {
        rules: [
            {
                test: /index\.js$/, //正则表达式,匹配模块的路径
                use: ["./loaders/loader1", "./loaders/loader2"] //匹配到了之后,使用哪些加载器
            }, //规则1
            {
                test: /\.js$/, //正则表达式,匹配模块的路径
                use: ["./loaders/loader3", "./loaders/loader4"] //匹配到了之后,使用哪些加载器
            } //规则2
        ], //模块的匹配规则
    }
}
  1. 上面的代码中匹配规则得到loaders数组[loader1,loader2,loader3,loaders4],运行处理的时候先loader4 然后依次把结果往前传
  2. 在这里插入图片描述

2、简化配置

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

3、问题

loader中能不能使用es6 模块化规范,eg:import ?

不能,loader本质是一个函数,它在webpack打包的过程中被执行,因为webpack打包是在node环境下运行,所以loader必须是commonjs规范

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值