何为loader

由于webpack自身只能理解 JavaScriptJSON 文件,因此需要 loader 去处理其他类型的文件,并将它们转换为有效 模块,以供webpack使用。loader的机制可以很大程度上拓展webpack的能力边界,这也是webpack如此强大的原因之一

loader用于对模块的源代码进行转换,可以使在 importload(加载) 模块时预处理文件。loader类似于其他构建工具中的任务(task),并提供了处理前端构建步骤的得力方式,具体来说就是可以同时使用多个loader来转化目标模块,执行的时候按照书写的顺序 倒序执行,每一个loader处理后的结果都会交给下一级的loader继续处理,最后一级的loader会返回webpack所支持的javascript代码,从而形成流水线

bg-pic

loader配置示例

一个基本的loader配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* webpack.config.js */
module.exports = {
...
module: {
rules: [
{ test: /\.js$/, use: 'babel-loader' },
{ test: /\.scss$/, use: [
'style-loader',
'css-loader',
'sass-loader'
] }
]
}
...
}

上述scss文件的loader处理顺序为:sass-loader => css-loader => style-loader

需要注意的是使用正则表达式匹配文件时,不要为它添加引号。也就是说,/.txt$/ 与 ‘/.txt$/‘ 或 “/.txt$/“ 不一样。前者指示 webpack 匹配任何以 .txt 结尾的文件,后者指示 webpack 匹配具有绝对路径 ‘.txt’ 的单个文件

如何编写一个自定义的loader

loader其实就是一个 导出函数 的模块,当需要使用loader转换资源模块时,这个导出的函数就会被调用,在这个函数中可以通过 this 来使用Loader API

起始的loader只有一个入参:源文件的内容,后面loader的入参会根据前一级loader的返回值决定,每一个loader的处理结果应该为 String 或者 Buffer 类型,代表了源文件的JavaScript代码

一个简单的自定义loader示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* my-loader.js */

/*
@param {string|Buffer} content 源文件的内容
@param {object} [map] 可以被 https://github.com/mozilla/source-map 使用的 SourceMap 数据
@param {any} [meta] meta 数据,可以是任何内容
*/
export default (content, map, meta) => {
// 自己的loader逻辑代码

return doSomeThing(source)
}


/* webpack.config.js */
const path = require('path')

module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: path.resolve('path/to/my-loader.js')
}
]
}
]
}
}

通常loader分为两种

上述中多次提到callback,这里专门说明下它的各个参数含义

1
2
3
4
5
6
this.callback(
err: Error | null, /* 第一个参数必须是 Error 或者 null */
content: string | Buffer, /* 第二个参数是一个 string 或者 Buffer */
sourceMap?: SourceMap,/* 第三个参数必须是一个可以被 this module 解析的 source map */
meta?: any /* 第四个参数,会被 webpack 忽略,可以是任何东西(例如一些元数据,通俗点说就是自定义数据 */
)

结语

loader是webpack核心概念之一,因此必须掌握它,这样才能更好地去理解webpack的工作机制,从而构建起关于webpack的知识体系,好了,就写到这啦,over!