本节进一步讲解Webpack的loader配置与使用,学习本节前确保已学习https://www.jiangruitao.com/webpack/loader/一节。
一、Loader的关键配置
我们先看一下之前使用过的Webpack配置,我们使用style-loader和css-loader这两个loader来处理CSS。
webpack.config.js里配置上这两个loader
const path = require('path');
module.exports = {
entry: './a.js', // a.js里引入了CSS文件
output: {
path: path.resolve(__dirname, ''),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}]
},
mode: 'none'
};
配置loader是在Webpack配置项module里进行的,这个配置项名为何叫module?Module是模块的意思,因此用这个名字可以表示这个配置项是用来解析与处理模块的。
Module配置项里最重要的一个配置子项就是rules了,它定义了loader的处理法则。
Rules是一个数组,数组每一项是一个JS对象,该对象有两个关键属性test和use。
Test是一个正则表达式或正则表达式数组,模块文件名与正则匹配的会被use里的loader处理。
Use可以是字符串,对象或数组,表示要使用的loader。
如果使用单一loader,那么可以取字符串,例如 use: 'babel-loader'。
如果该loader额外配置参数,那么可以取对象,额外参数放在options里(有部分loader放query里),例如 use: {loader: 'babel-loader', options: {…}}。
如果使用多个loader进行链式处理,那么可以取数组,数组每一项可以是字符串或对象,字符串或对象的使用同上。
二、rules其它参数
除了test和use这两个关键配置参数,rules还有exclude、include、resource、issure和enforce等参数。
1.exclude与include
如果我们有一些文件不想被正则匹配到的loader处理,那么我们可以配置exclude项,exclude的中文意思是排除。
Exclude的值是字符串或正则表达式,字符串需要是绝对路径。
我们来看一个例子
rules: [{
test: /\.js$/,
use: ['babel-loader'],
exclude: /node_modules/,
}]
上面的配置表示,除了node_modules文件夹,对所有的以js为后缀名的文件模块使用babel-loader处理。
Include表示的意思正好与exclude相反,它表示只对匹配到的文件处理。
rules: [{
test: /\.js$/,
use: ['babel-loader'],
include: /src/,
}]
上面的配置表示,只对src目录下以js为后缀名的文件模块使用babel-loader处理。
2.Enforce
对同一类后缀名类型的文件,我们可以使用多个loader处理,例如处理CSS时使用['style-loader', 'css-loader'],loader的处理顺序是数组项从后向前。
如果我们想强制某个loader最先处理或最后处理,可以使用enforce项。
Webpack推荐使用的enforce项有两个,'pre'和'post'。
Pre表示这个loader在所有的loader之前执行,post表示这个loader在所有的loader执行后再执行。
我们来看一个例子
rules: [{
test: /\.js$/,
use: ['eslint-loader'],
enforce: 'pre',
exclude: /node_modules/,
}]
这个配置表示在所有处理js文件模块loader之前执行eslint-loader,这样我们可以在js代码未被处理的时候就进行eslint代码规范校验。
3.resource与issuer
Resource的中文意思是资源,issuer中文意思是发行人。在Webpack中被加载的模块我们称之为resource,而实施加载的模块我们称之为issuer。
例如,我们在一个JS模块里引入了CSS模块,那么JS模块就是issuer,CSS模块就是resource。
// app.js import './src/reset.css'
我们在app.js里引入了reset.css,这里app.js是issuer,reset.css是resource。
在我们之前使用过的loader配置里,其实已经使用了resource,那些test和exclude等配置是使用了默认resource。下面的配置是等效的
rules: [{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
exclude: /node_modules/
}]
rules: [{
use: ['style-loader', 'css-loader'],
resource: {
test: /\.css$/,
exclude: /node_modules/
}
}]
我们来看一个例子,配套github仓库 https://github.com/jruit/webpack-tutorial 的webpack3-1
这个例子和Webpack入门一章Webpack loader的webpack1-3例子相似,都是简单的在一个JS文件里引入一个CSS文件。我们把rules换成了其用resource项的等价写法。执行npx webpack后,在浏览器打开引用了打包后JS文件的HTML,文字颜色显示正常。
module.exports = {
entry: './a.js', // a.js引入了CSS文件,该CSS将文字颜色改为蓝色
output: {
path: path.resolve(__dirname, ''),
filename: 'bundle.js'
},
module: {
// rules: [{
// test: /\.css$/,
// use: ['style-loader', 'css-loader']
// }]
rules: [{
use: ['style-loader', 'css-loader'],
resource: {
test: /\.css$/
}
}]
},
mode: 'none'
};

下面说一下issuer的使用。
如果想指定只有src目录下的JS引用的CSS可以被相应的loader处理,那么可以配置issuer,下面的配置是等效的。
rules: [{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
exclude: /node_modules/,
issuer: {
test: /\.js$/,
include: /src/
}
}]
rules: [{
use: ['style-loader', 'css-loader'],
resource: {
test: /\.css$/,
exclude: /node_modules/
},
issuer: {
test: /\.js$/,
include: /src/
}
}]
三、其它loader写法
在Webpack版本更新的过程中,出现过不同的loader写法。
下面是一个例子,是vue-cli里的配置,这里没有使用use项而是直接使用了loader项指定loader。
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
]
在Webpack1.x的时候,还有使用loaders项的方式,现在已经被rules取代了。
module: {
loaders: [
{
test: /\.json$/,
loader: "json"
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel'
}
]
}
一些其它的loader写法这里就不列举了,本节内容关键是掌握loader的使用本质,见到其它写法的时候知道查一下资料就可以了。
小结
本节进一步讲解Webpack的loader配置与使用,把一些常用配置都进行了讲解。
// body.css
.yellow {
color: yellow;
}
// index.css
@import './body.css';
.blue {
color: blue;
}
import style from '../assets/style/index.css'
const element = `
CSS Modules
CSS Modules
`
document.getElementById('app').innerHTML = element
我这里能取到 .blue,但是为什么这里 .yellow 是 undefined?
一个 css Module 【A】 导入另一个 css Module【B】,A 里面已经有了 B 中的样式,但是经过 loader 加载后,类名发生了改变,导致 html 只能取到直接引入的 【A】 中的类,【B】中的取不到,这个怎么解决呢
@import ‘./body.css’; 改成标准css引入语法 @import url('./body.css');
import style from '../assets/style/index.css'
const element = `
CSS Modules
CSS Modules
`
document.getElementById('app').innerHTML = element