本节进一步讲解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