文章目录
- 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全流程:
根据配置分成很多个chunk
- 每个
chunk根据
一个或者几个入口模块
,分析出依赖
的模块,然后生成资源列表
- 最终按资源列表
打包生成文件
chunk解析出依赖的模块,形成一个个模块(模块列表),然后把这些模块打包,捆绑到一起,形成一个单独的js文件 – bundle(捆)
2、chunk中解析模块的流程(解析模块的具体流程):
所以loader的位置在 上图中 读取文件内容后
,–把文件内容读出来,然后把文件内容传递给loader函数,然后拿loader函数的返回结果,去做抽象语法树分析
我们按上面的写法写好loader
,还需要应用进webpack打包过程中
,否则webpack不知道这是个loader,不知道要去调用loader这个函数,那我们怎么告诉webpack哪个是需要用到的loader?
3、chunk中解析模块的更详细流程
[4-重要]、处理loaders流程:
判断规则,看模块是否需要loader来处理
,并不是每个模块都需要loader来处理,如果不需要则得到一个loaders的空组
,循环的时候,不会做任何处理,就会把源代码拿去做AST 语法树分析- 根据
配置的规则
,如果需要loader来处理
,则从规则里读取出一个loaders数组
,loaders数组里,每个loader都是一个函数
- 读取到loaders数组后,
让里面的每一个loader函数去处理
:把文件内容交个数组里的最后一个loader,然后将loader返回的代码,交给上一个代码,直至第一个loader处理后,得到一个最终的代码,然后进行抽象语法树分析
3、loader配置:
1、完整配置
module.exports = {
module: { //针对模块的配置,目前版本只有两个配置,rules、noParse
rules: [ //模块匹配规则,可以存在多个规则
{ //每个规则是一个对象
test: /\.js$/, //匹配的模块正则
use: [ //匹配到后应用的规则模块
{ //其中一个规则
loader: "模块路径", //loader模块的路径,该字符串会被放置到require中
options: { //向对应loader传递的额外参数
}
}
]
}
]
}
}
-
module:{} 针对模块的配置
---- 在这个对象
里配置模块怎么去解析,解析时用到哪些loader
,目前只有rules、noParse两个配置 -
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
}
rules数组里是
一个个规则
,每个规则都是一个对象
,模块匹配的规则,从下往上匹配
,先看是否需要规则2,然后再看规则1test:正则表达式
– 规则里的test属性匹配模块的路径
。eg:拿入口文件的路径./src/index.js
和正则表达式/index\.js$/
匹配上,就要使用对应的loadersuse:[]
use数组里是一项项用到的加载器`匹配到后,使用哪些加载器,每一项(每个加载器的使用)是一个对象use:[ { loader:'./loaders/test-loader' //加载器的路径,webpack会自动用require加载 loader加载器里的内容 },{} ]
noParse
是否不要匹配某个规则
module.exports = {
mode: "development",
module: {
rules: [
{
test: /index\.js$/, //正则表达式,匹配模块的路径
use: ["./loaders/loader1", "./loaders/loader2"] //匹配到了之后,使用哪些加载器
}, //规则1
{
test: /\.js$/, //正则表达式,匹配模块的路径
use: ["./loaders/loader3", "./loaders/loader4"] //匹配到了之后,使用哪些加载器
} //规则2
], //模块的匹配规则
}
}
- 上面的代码中匹配规则得到loaders数组[loader1,loader2,loader3,loaders4],运行处理的时候先loader4 然后依次把结果往前传
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规范