Webpack
中的loader
是用于处理一些非JavaScript`文件的代码转换器,例如将ES6/ES7转换成ES5,将SCSS/Sass/less转换成CSS。loader可以让webpack支持更多的文件类型,并且也可以通过loader将一些资源打包成JS文件中。
loader
是针对module
级别的,即针对每个待打包的文件进行转换处理,并最终输出打包后的文件。在webpack.config.js
文件中配置loader
,可以指定不同的文件类型使用不同的loader
进行处理,也可以通过链式调用多个loader完成某种特定的处理。例如:
module: {
rules: [
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'] //链式调用loader
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader' //单一loader
}
]
}
以上代码中,第一个rule
用于处理.scss
文件,使用了三个不同的loader
,分别是style-loader、css-loader和sass-loader
,链式调用实现了将scss文件转换成浏览器可识别的CSS文件。第二个rule
用于处理.js
文件,只使用了一个babel-loader
,将ES6/ES7转换成ES5,这里的exclude
选项用于排除node_modules
目录下的文件。
Webpack中的loader可以分为两类:普通loader和enforce-loader。普通loader是指在webpack配置文件中没有设置enforce属性的loader,而enforce-loader是指在webpack配置文件中设置了enforce属性的loader。
普通loader执行的顺序是从右向左,从下往上。也就是说,在webpack配置文件中,最后一次加入的loader会最先执行,然后依次向上执行。
而enforce-loader则有更高的优先级,会先于普通loader执行。enforce属性可设置为pre或post,如果设置为pre,表示在普通loader之前执行;如果设置为post,表示在普通loader之后执行。这样就可以确保enforce-loader在所有loader中优先执行,并且能够准确地对文件进行处理。
常用的enforce-loader有以下几种:
pre-loader:在执行普通loader之前处理文件,常用于代码检查和格式化等操作;
post-loader:在执行普通loader之后处理文件,常用于对文件进行压缩、优化等操作;
noParse-loader:当文件匹配指定规则时,忽略指定文件的递归解析和处理,提升webpack性能;
ignore-loader:忽略指定文件的解析和处理。
Webpack中普通loader的执行顺序是从右到左、从下到上的。也就是说,在webpack配置文件中,loader的引入是按照从右到左的顺序进行的,loader的执行顺序是从下到上的。
举个例子,假设我们在webpack的配置文件中使用了以下loader:
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
从上面的配置代码可以看出,在解析js文件的时候,使用了babel-loader转换成浏览器兼容的代码,然后在加载css文件的时候,使用style-loader和css-loader进行处理。
从loader的配置顺序来看,先解析js文件的babel-loader要放到后面,即在css-loader和style-loader的前面。另外,由于loader的执行顺序是从下到上的,所以css-loader要放在style-loader的前面,才能正确地将css代码转换为JavaScript代码。
在 webpack 中,loader 是用来处理各种类型的文件的工具。而 enforce-loader 是一个特殊的 loader,它可以强制在之前的 loader 执行后、下一个 loader 执行之前执行。
在 webpack 中,loader 的执行顺序是从右到左、从下往上的。也就是说,当一个模块需要被多个 loader 处理时,它的代码会被从下往上、从右往左依次传递给这些 loader。而在这个过程中,每一个 loader 都可以对该模块进行处理。但是,如果使用了 enforce-loader,那么它会被直接放在 loader 的最前面执行。
举个例子,假如我想使用 Babel 对我的 JavaScript 代码进行编译。那么,我需要安装 babel-loader,并在 webpack.config.js 中进行配置:
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
},
],
},
这段代码表示,当 webpack 遇到 js 文件时,会使用 babel-loader 进行编译。但是,如果我的代码中有些部分是不需要编译的,比如说我想保持某个模块的代码不变。这时候可以使用 enforce-loader:
module: {
rules: [
{
test: /\.js$/,
enforce: 'pre', // 注意这里
loader: 'some-other-loader',
},
{
test: /\.js$/,
loader: 'babel-loader',
},
],
},
这段代码中,我把 enforce-loader 放在了 babel-loader 的前面。这就意味着,在执行 babel-loader 前,我的代码会被先传递给 enforce-loader。如果 enforce-loader 不对该模块进行处理,那么它会继续向下传递给 babel-loader。反之,如果 enforce-loader 对该模块进行了处理,那么它就会直接把处理后的代码传递给下一个 loader,而不会再让 babel-loader 对其进行处理。这样,我就可以通过 enforce-loader 来控制哪些模块需要编译,哪些模块不需要编译。