Loader可以看作具有文件转换功能的翻译员,告诉webpack在遇到哪些文件时用哪些Loader去加载和转换。
loader特点
1.单一职责。一个Loader只做一件事情,正因为职责越单一,所以Loaders的组合性强,可配置性好。
2.loader支持链式调用。上一个loader的处理结果可以传给下一个loader接着处理,直到最后一个loader,返回Webpack所期望的JavaScript。
3.顺序:从右到左,从下到上执行。
// less-loader先执行,再执行css-loader,最后执行style-loader。
rules: [
{
test: /\.less$/,
use: ['style-loader','css-loader','less-loader']
},
],
或者
rules: [
{
test: /\.less$/,
use:[
{
loader:'style-loader'
},
{
loader:'css-loader'
},
{
loader:'less-loader'
}
]
},
],
或者
rules: [
{
test: /\.less$/,
loader:'style-loader',
},
{
test: /\.less$/,
loader:'css-loader',
},
{
test:/\.less$/,
loader:'less-loader'
}
],
常用的loader
- 转换样式文件:style-loader、css-loader、sass-loader、less-loader、postcss-loader
- 加载图片、字体等文件:raw-loader、file-loader、url-loader
- 编译转换脚本语言:babel-loader、ts-loader、coffee-loader
- 检查测试代码:eslint-loader、tslint-loader、mocha-loader测试用例代码
loader的使用方式
一般loader的使用方式分为三种:
1:[配置](推荐)在配置文件webpack.config.js中配置
module.exports = {
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
}
}
2:[CLI]:通过命令行参数方式
webpack --module-bind 'txt=raw-loader'
3:[内联]:通过内联使用
import txt from 'raw-loader!./file.txt'
loader配置
通过module.rules来配置,module.rules的含义是创建模块的规则, rules是个数组,其中每一项都是一项规则。loader是用来生成符合Webpack的模块的。然后Webpack把这些模块打包起来生成对应的js文件。loader是在打包前执行的。
module.rules每一项规则为rule,rule配置如下:
1.rule的条件
Rule.test
作用:是筛选资源,符合条件的资源让这项规则中的loader处理。
值:字符串、数组、函数、正则表达式。
- 字符串:可以是资源所在目录绝对路径 、资源的绝对路径
- 函数: 接收的参数为资源的绝对路径。返回true表示该资源可以交给
user选项里面的loader处理一下。 - 数组:数组每一项可以为字符串、正则表达式、函数,只要符合数组中任一项条件的资源就可以交给
user选项里面的loader处理一下。 - 正则表达式
1.字符串
const path = require('path');
module.exports = {
module: {
rules: [
{
test: path.resolve(__dirname, 'src/css'),
//test: path.resolve(__dirname, 'src/css/index.css'),
use: ['style-loader','css-loader']
},
],
},
}
2.函数 \project\03personal\05Webpack_demo\src\css\index.css
module.exports = {
module: {
rules: [
{
test: function (path) {
return path.indexOf('.css') > -1
},
use: ['style-loader','css-loader']
},
],
},
}
3.数组
const path = require('path');
module.exports = {
module: {
rules: [
{
test: [/\.css$/,path.resolve(__dirname, 'src/css')]
use: ['style-loader','css-loader']
},
],
},
}
Rule.include
符合条件的资源让这项规则中的loader处理,用法和Rule.test一样。
const path = require('path');
module.exports = {
module: {
rules: [
{
include:/\.css$/,
//include: path.resolve(__dirname, 'src/css'),
//include: path.resolve(__dirname, 'src/css/index.css'),
//include: [/\.css$/,path.resolve(__dirname, 'src/css')],
//include:function (content) {
//return content.indexOf('src/css') > -1
//},
use: ['style-loader','css-loader']
},
{
test:/\.js$/, // 命中js文件
use: ['babel-loader?cacheDirectory'], // ?cacheDirectory 表示传给 babel-loader 的参数,用于缓存babel 编译结果加快重新编译速度
include: path.resolve(__dirname, 'src') // 只命中src目录里的js文件,加快 Webpack 搜索速度
},
],
},
}
Rule.exclude
符合条件的资源要排除在外,不能让这项规则中的loader处理,用法和Rule.test一样。
例如:排除node_modules中的css文件。
const path = require('path');
module.exports = {
module: {
rules: [
{
exclude:/node_modules/,
//exclude: path.resolve(__dirname, 'node_modules'),
//exclude: [/node_modules/ , path.resolve(__dirname, 'node_modules')],
//exclude:function (content) {
//return content.indexOf('node_modules') > -1
//},
use: ['style-loader','css-loader']
},
],
},
}
Rule.issuer
用法和Rule.test一样,但是要注意是匹配引入资源的文件路径,
如在main.js中引入css/index.css
const path = require('path');
module.exports = {
module: {
rules: [
{
issuer: /\main\.js$/,
//issuer: path.resolve(__dirname, 'main.js'),
//issuer: [/\main\.js$/ , path.resolve(__dirname, 'main.js')],
//issuer:function (content) {
//return content.indexOf('main.js') > -1
//},
use: ['style-loader', 'css-loader']
},
],
},
}
Rule.issuer 和 Rule.test、Rule.include 、Rule.exclude同时使用时候,也是“与”的关系。
Rule.resource
此选项也可筛选资源,符合条件的资源让这项规则中的loader处理。
但配置resource选项后,test、include、exclude选项不能使用。issuer选项不生效。
resource选项中有以下子选项
test选项,用法和Rule.test一样。exclude选项,用法和Rule.exclude一样。include选项,用法和Rule.include一样。not选项,值为数组,数组每一项可以为字符串、正则表达式、函数,只要符合数组中任一项条件的资源就不能交给user选项里面的loader处理一下。and选项,值为数组,数组每一项可以为字符串、正则表达式、函数,必须符合数组中每一项条件的资源才能交给user选项里面的loader处理一下。or选项,值为数组,数组每一项可以为字符串、正则表达式、函数,只要符合数组中任一项条件的资源就可以交给user选项里面的loader处理一下。
const path = require('path');
module.exports = {
module: {
rules: [
{
resource:{
test:/\.css$/,
include: path.resolve(__dirname, 'src/css'),
exclude: path.resolve(__dirname, 'node_modules'),
},
use: ['style-loader', 'css-loader']
},
],
},
}
Rule.resourceQuery
匹配资源引入路径上从问号开始的部分。例
import './ass/main.css?inline'
上面代码中Rule.resourceQuery要匹配?inline,例
const path = require('path');
module.exports = {
module: {
rules: [
{
resourceQuery:/inline/,
// resourceQuery:function (content) {
//return content.indexOf('inline') > -1
// },
//resourceQuery:[/inline/],
use: ['style-loader', 'css-loader']
},
],
},
}
注意
-
Rule.test、Rule.include、Rule.exclude、Rule.issuer、Rule.resourceQuery同时使用时候,是“与”的关系,必须同时符合以上所有配置的条件才可以让这项规则中的loader处理。
-
Rule.issuer、Rule.resourceQuery、Rule.resource同时使用时候,也是“与”的关系。必须同时符合以上所有配置的条件才可以让这项规则中的loader处理。
2.rule的loader
Rule.use
意思是使用哪些loader处理符合条件的资源。use的值:数组或者函数。
use: ['style-loader']其实是use: [ { loader: 'style-loader'} ]的简写。
use每一项是一个UseEntry数组或者一个loaderName字符串,每个入口指定使用一个loader。
UseEntry:
- loader:必填,字符串类型
- options:字符串或对象,值可以传递到 loader 中。具体参数详见个loader
还可以通过options传入loader,可以理解为loader的选项。
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
]
},
],
},
}
use的值为函数时,返回一个数组,参数为info,info中有以下内容
-
compiler:当前webpack的编译器(可以是undefined值)。 -
issuer:引入被处理资源的所在文件的绝对路径。 -
realResource:被处理资源的绝对路径。 -
resource:被处理资源的绝对路径,它常常与realResource替代,只有当资源名称被请求字符串中的!=!覆盖时才不近似。 -
resourceQuery:被处理资源的绝对路径中?后面的部分。
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: (info) =>{
console.log(info)
return [
'style-loader',
{
"loader": 'css-loader',
},
]
},
},
],
},
}
Rule.loader
loader: 'css-loader' 是 use: [ { loader: 'css-loader'} ]的简写。
module.exports = {
module: {
rules: [
{
test: /\.css$/,
loader: 'css-loader',
},
],
},
}
Rule.oneOf
当规则匹配时,只使用第一个匹配规则。
例如说要处理css文件资源时,one.css要用url-loader处理,two.css要用file-loader处理。可以用Rule.oneOf来配置,其用法和module.rules一样。
module.exports = {
module: {
rules: [
{
test: /\.css$/,
oneOf: [
{
resourceQuery: /one/, // one.css?one
//test: /one\.css/,
use: 'url-loader'
},
{
resourceQuery: /two/, // two.css?two
//test: /one\.css/,
use: 'file-loader'
}
]
},
],
},
}
Rule.enforce
可以用Rule.enforce来控制loader的执行顺序:
pre:优先执行post:最后执行
rules: [
{
test:/\.less$/,
loader:'less-loader',
enforce:'pre'
},
{
test: /\.less$/,
loader:'css-loader',
},
{
test: /\.less$/,
loader:'style-loader',
enforce:'post'
},
],
常用loader详解
1.style-loader
定义:将模块导出的内容作为样式并添加到 DOM 中。
内部使用了模块热替换功能来加载css,幕后使用了module.hot.accept。
安装: npm install style-loader --save-dev
建议:建议将 style-loader 与 css-loader 结合使用
2.css-loader
原理:webpack是用JS写的,运行在node环境,所以默认webpack打包的时候只会处理JS之间的依赖关系,不原生支持解析css文件。要支持非js类型的文件,需要使用webpack的Loader机制。 .css文件需要css-loader去处理。
定义:加载 CSS 文件并解析 import 的 CSS 文件,最终返回 CSS 代码。css-loader会处理 import / require() @import / url 引入的内容。
css-loader支持使用CSS Modules,参数: modules:false(默认) 启用/禁用 CSS 模块和设置模式
注意:style-loader应该在css-loader前面(use里的loader从左到右被配置,从右到左先配置,即loader执行顺序为从右到左)。
先使用css-loader读取css文件,再使用style-loader把css内容注入到js里。
module.exports={
module:{
rules:[
{
test:/\.css$/i,
use:['style-loader']
},
{
test: /\.css$/i,
exclude: /node_modules/,
loader: 'css-loader',
options: {modules: { localIdentName: '[local]--[hash:base64:5]' } },
},
]
}
}
3.less-loader
安装: npm install less-loader --save-dev(npm i less-loader -D)
定义:处理 less 的 webpack loader。将 Less 编译为 CSS。
// webpack.config.js
module.exports = {
...
module: {
rules: [{
test: /\.less$/i,
loader: 'less-loader' // 将 Less 编译为 CSS
}]
}
};
4.sass-loader
安装:npm install sass-loader node-sass --save-dev
// webpack.config.js
module.exports = {
...
module: {
rules: [{
test: /\.scss$/i,
use: [
"style-loader", // 将 JS 字符串生成为 style 节点
"css-loader", // 将 CSS 转化成 CommonJS 模块
"sass-loader" // 将 Sass 编译成 CSS,默认使用 Node Sass
]
}]
}
};
5.postcss-loader
安装: npm i -D postcss-loader
注意:如果要使用最新版本的话,你需要使用 webpack v5。如果使用 webpack v4 的话,你需要安装 postcss-loader v4。
配置:新建postcss.config.js文件。
原理:webpack把css文件的内容传送给postcss-loader,postcss-loader会解析配置文件postcss.config.js文件中的插件,传输给postcss,postcss会解析传入的css,将其转换为一个AST,然后通过各种不同的插件来对这个AST进行操作,最终序列化一个新的css,然后将结果返回给postcss-loader,进行webpack下一个loader的操作。
配置:
- 在项目跟目录建postcss.config.js配置文件(推荐)
- 在webpack loader中配置
6.babel-loader
作用:babel-loader这个loader主要作用是在Webpack打包的时候,用Babel将ES6的代码转换成ES5版本的。
安装:
npm install babel-loader --save-devnpm i --save-dev @babel/core:babel核心包npm i --save-dev @babel/preset-env:预设即一组插件,用来转码
module: {
rules: [
{
test: /\.js[x]?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-react',
[
'@babel/preset-env',
{
targets:{
chrome: '40',
ie: '11',
},
},
],
],
plugins: [
['react-activation/babel'],
['@babel/plugin-transform-runtime', { corejs: 3 }],
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-proposal-nullish-coalescing-operator',
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
['@babel/plugin-proposal-class-properties', { loose: true }],
],
},
},
],
},
7.file-loader
安装:npm install file-loader --save-dev
作用:从名字就上大概可以猜测出来,是一个通用文件处理loader。
- 用import/require 语法引入一个文件时,原生的JS并不支持这种import语法引入文件的。配置file-loader就可以实现
- 可以指定该文件生成的输出目录,并在代码中返回该文件的地址
- 处理css引入的图片
生成文件名:file-loader生成的文件默认的文件名是"[contenthash].[ext]"。
- [contenthash]:资源内容hash值
- [ext]:文件扩展名
- [hash]:也是根据内容计算出的hash值
- [name]:文件的原始名称
注意:file-loader不仅仅可以处理图片资源,它本质功能是复制资源文件并替换访问地址,音视频等资源也可以使用它。
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(ttf|eot|woff|woff2)$/,
use: [
{
loader: 'file-loader',
options: {
name: `assets/[name].[hash:8].[ext]`,
},
},
],
},
],
},
};
8.url-loader
安装:npm install --save-dev url-loader
url-loader是file-loader的增强版,它支持file-loader的所有功能,另外还有一个特殊的功能。
作用:url-loader的特殊功能是可以计算出文件的base64编码,在文件体积小于我们指定的值(单位 byte)的时候,可以返回一个base64编码的DataURL来代替访问地址。(在CSS中引入图片也是同样的道理。)。
这也是url-loader起这个名字的原因,因为它可以使用base64编码的URL来加载图片。
// 例子
// 正常img引入图片地址是
<img src="be735c18be4066a1df0e48a1173b538e.jpg">
// 使用base64编码后,引入图片地址是"data:image/jpg;base64,iVBORw0KGgoA…"这种格式的,这样就不用去请求存储在服务器上的图片了,而是使用图片资源的base64编码。
<img src="data:image/jpg;base64,iVBORw0KGgoA..."> <!-- 省略号...表示省略了剩下的base64编码数据 -->
limit参数,对于图片体积小于8KB(1024 * 8)的,我们转成base64编码的URL直接写入打包后的JS文件里。
module: {
rules: [
{
test: /\.(jpg|png|gif|svg)$/,
loader: 'url-loader',
options: {
limit: 1024 * 8,
name: `assets/[name].[hash:8].[ext]`,
},
},
importLoaders
定义:css文件中如果有@import 语句,importLoaders的作用是决定@import模块在使用css-loader前,要使用几个其它的loaders处理。
// a.css
@import './b.css';
body{color: red}
module: {
rules: [
{
test: /.css$/,
use: [
"style-loader",
{ loader: "css-loader", options: { importLoaders: 0 } },
"postcss-loader",
],
},
],
},
// 由于importLoaders为0,所以postcss-loader不处理b.css,只有css-loader处理b.css,如果importLoaders为1,那么postcss-loader,css-loader都会处理b.css。
注意事项
- 每一个Loader可以通过URL querystring的方式传入参数,例如css-loader?minimize中的minimize告诉css-loader要开启css压缩。