说明
- 这套笔记是对于
webpack 5.x进行阐述的。(webpack <= 4用法稍有不同)
概念:
loader 是 webpack 中的预处理器,loader 可以将许多不同后缀名的文件处理成浏览器可以识别运行的文件。
配置 loader
在 webpack.config.js 中,loader 在 config.module.rules 下面使用
{
// ...
module: {
rules: [
// sub loaders
]
},
...
}
配置单个 loader
以配置 babel-loader 解析 *.js 文件为例:
- 安装 babel 相关的依赖
# 安装 babel 相关的依赖
npm install babel babel-loader @babel/core @babel/preset-env --save-dev
- 在
webpack.config.js中配置 babel-loader
const config = {
// ...
module: {
rules: [
{
test: /.js$/, // test -> 表示我要处理什么样的文件
loader: 'babel-loader' // loader -> 表示我要用什么 loader 来处理上述的文件
}
],
}
};
module.exports = config;
总结一下:
loader在module.rules下面配置- 每个 loader 对应的配置项都是一个对象,对象里面需要说明
test(使用正则表达式表示需要处理什么后缀名的文件) 和use(需要使用什么 loader 来进行处理)- 如果没有其他的配置参数,
use可以直接是loader名称的字符串;如果有其它的参数,use需要配制成一个对象:{ loader: 'xxx-loader', options: { /* 需要配置的参数 */ } }- 如果一种后缀名的文件需要配置多个 loader,请参考下面 配置多个 loader
配置多个 loader
loader 从右到左(或从下到上)地取值(evaluate)/执行(execute)。
module.exports = {
module: {
rules: [
{
test: /.css$/,
use: [
// [style-loader](/loaders/style-loader)
{ loader: 'style-loader' },
// [css-loader](/loaders/css-loader)
{
loader: 'css-loader',
options: {
modules: true
}
},
// [sass-loader](/loaders/sass-loader)
{ loader: 'sass-loader' }
]
}
]
}
};
使用内联的方式配置 loader
上述的方式 (配置单个 loader、配置多个 loader 都是在 webpack.config.js 中通用配置。
但是如果需要在单个文件中特殊配置 loader, 可以在 import 语句或任何 与 "import" 方法同等的引用方式 中指定 loader。使用 ! 将资源中的 loader 分开。每个部分都会相对于当前目录解析。
通过为内联 import 语句添加前缀,可以覆盖 配置 中的所有 loader, preLoader 和 postLoader 。
内联的方式配置 loader 的用法如下:
- 使用
!前缀,将禁用所有已配置的 normal loader(普通 loader) - 使用
!!前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader) - 使用
-!前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders
loader 的特性
- loader 支持链式调用。链中的每个 loader 会将转换应用在已处理过的资源上。一组链式的 loader 将按照相反的顺序执行。链中的第一个 loader 将其结果(也就是应用过转换后的资源)传递给下一个 loader,依此类推。最后,链中的最后一个 loader,返回 webpack 所期望的 JavaScript。
- loader 可以是同步的,也可以是异步的。
- loader 运行在 Node.js 中,并且能够执行任何操作。
- loader 可以通过 options 对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。
- 除了常见的通过 package.json 的 main 来将一个 npm 模块导出为 loader,还可以在 module.rules 中使用 loader 字段直接引用一个模块。
- 插件(plugin)可以为 loader 带来更多特性。
- loader 能够产生额外的任意文件。
可以通过 loader 的预处理函数,为 JavaScript 生态系统提供更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如:压缩、打包、语言转译(或编译)和 更多其他特性。
如果我想写一个自己的 loader, 怎么做?
步骤说明
- 在
webpack.config.js配置一下resolveLoader, 告诉 webpack :如果我想使用 loader, 它需要从哪里去获取 - 创建自定义文件在用来装载 loaders
- 写一个 loader 函数,并默认导出
举个例子
项目结构如下
|- src
|- ... # 项目代码
|- webpack.config.js
|- loaders
|- tpl-loader.js # 处理tpl的loader
|- ... # 其他的loader
以处理 *.tpl 文件为例:
- 在 webpack.config.js 中编写接收额外的 loader 配置:
resolveLoader
const path = require('path');
module.exports = {
//...
resolveLoader: {
modules: [
'node_modules', // 不要忘记写上 node_modules
path.resolve(__dirname, 'loaders')
],
},
};
- 在
loaders文件下创建一个 loader 函数my-tpl-loader, 他是一个提供给 webpack 使用的回调函数,形参接收的是文件的字符串内容,并返回需要输出的代码字符串
module.exports = function (source) {
return `
export default () => {
return `${source}`;
}
`;
}
- 配置 loader 规则,添加对于
*.tpl文件的解析规则
const config = {
// ...
module: {
rules: [
{
test: /.tpl$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
browsers: ['last 2 versions', 'ie >= 11']
}
}]
]
}
},
'my-tpl-loader'
]
}
]
},
};
module.exports = config;