持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
虽然是五月的尾巴,但是竟然也算6月更文呢!就很棒哟~😄
前言
大家好,我是小阵 🔥,一路奔波不停的码字业务员
身为一个前端小菜鸟,总是有一个飞高飞远的梦想,因此,每点小成长,我都想要让它变得更有意义,为了自己,也为了更多值得的人
如果喜欢我的文章,可以关注 ➕ 点赞,与我一同成长吧~😋
加我微信:zzz886885,邀你进群,一起学习交流,摸鱼学习两不误🌟
开开心心学技术大法~~
来了来了,他真的来了~
正文
开干之前照理说下what
和why
- 什么是loader?
- 我们这里说的
loader
是webpack
中的module>rules>loader
中引入的一个工具方法
- 我们这里说的
- 为什么需要loader
- 因为
webpack
只认识基础的文件,比如js
、json
,怎样让webpack
认识更多的文件资源呢?那loader
就是充当了webpack
的翻译官,可以将webpack
不认识的资源转变成他认识的
- 因为
说了what
与why
,接下来就是关键的how
一、loader的本质
loader的本质就是一个module.exports
暴露出去的一个函数方法
注意
module.exports
暴露出去的一定不要是箭头函数,因为异步loader的使用是需要用到this
的,而箭头函数不存在this
二、实现简单的loader
综合上面了解的,我们只需要return一个结果就行
module.exports = function (content, map, meta) {
// 其中content就是通过loader的test规则匹配到的文件资源内容
// map就是指sourceMap,如果想要遵循webpack的sourceMap规则,用this.callback或者this.async结束loader的时候最好手动传入该map,当然如果是普通的return,那就直接return就好
console.log('loader', content)
return content
}
三、在webpack中如何引入你的loader
// webpack.config.js
const path = require('path');
module.exports = {
module:{
rules:[
{
test:/\.js$/,
loader: path.resolve(__dirname,'loaders/index.js')
}
]
}
}
可以通过配置resolveLoader
来让你的loader引入更加优雅
module.exports = {
module:{
rules:[
{
test:/\.js$/,
loader: 'index'
}
]
},
resolveLoader: {
modules: [resolve(__dirname, 'loaders')]
},
}
四、loader加载顺序
我们都知道,当想要多个loader作用时,需要将loader
属性用use
来代替,通过use:['loader1','loader2']
的方式来实现。
基本的loader执行顺序也是从后向前执行的。
但是loader并不是整体都是从后向前的,loader中注册的pitch
是从前向后执行的。我们来看一下
// loader中pitch的注册写法
module.exports.pitch = function () {
console.log("index1-pitch")
}
我们可以通过注册多个loader的pitch
来看下打印
五、同步loader和异步loader
我们js有同步和异步,那相应的,loader也有自己的同步和异步
同步loader
// 写法一
module.exports = function (content, map, meta) {
console.log('loader-index3', content, map, meta)
// console.log('options', getOptions(this))
return content
}
// 写法二
module.exports = function (content, map, meta) {
this.callback(null, content, map, meta)
}
异步loader
// 写法一
module.exports = function (content, map, meta) {
setTimeout(() => {
this.callback(null, content, map, meta)
}, 2000);
}
// 写法二
module.exports = function (content, map, meta) {
const callback = this.async();
setTimeout(() => {
callback(null, content, map, meta)
}, 2000);
}
六、接收loader传入的options
我们的loader
可能需要传入一些自定义的配置,那怎样在loader
内部接收到这写参数呢?
可以通过loader-utils
这个库来接收,注意库的版本和使用方法,我这里用的是v2.0.0
的版本,所以我就以这个版本来做演示
//webpack.config.js
module.exports = {
///...
module:{
rules:[
{
test:/\.js$/,
loader:'index',
options:{
name: 'zzz',
age: 21
}
}
]
}
}
// loader
const {getOptions} = require('loader-utils');
module.exports = function(content,map,meta){
// 只需要调用暴露出来的getOptions,传入this即可
const options = getOptions(this) || {};
console.log('loader-options',options)
this.callback(content,map,meta)
}
可以看到用法很简单,只需要用暴露出的getOptions
传入this
就会返回我们在webpack.config.js
中定义的options
字段
七、对loader传入的options进行校验
上面我们看了怎样接收到传入的options,那怎样对这些options进行校验呢,如果用户输入的options不是我们符合预期的options的话,可以在进入到loader的时候将错误信息提示给用户
这里我们需要借助一个schema-utils
的库,同样需要注意库的版本和用法,我这里是v2.7.1
,所以就以这个版本举例
首先我们需要定义一个schema.json
的文件来做一些字段的约束
{
// 整体options传入的类型一般都是object
"type": "object",
// 对传入的属性进行约束
"properties": {
// key值为options传入的key,value是一个对象,对传入的value进行约束
"name": {
// 表述传入的options的类型
"type": "string",
// 如果未按照要求传的话,会抛出description中定义的信息
"description": "输入的name必须是string类型"
},
// 同上
"age": {
"type": "number",
"description": "输入的age必须是number类型"
}
},
// 是否允许options中存在以上属性之外的属性,为true允许,false为不允许
"additionalProperties": true
}
然后在loader中通过schema-utils
暴露的方法来约束下用户输入的options
// loader
const loaderUtils = require('loader-utils');
const validate = require('schema-utils');
const schema = require('./schema.json')
module.exports = function (content, map, meta) {
console.log('loader-index3', content)
console.log('laoder-options', loaderUtils.getOptions(this))
const options = loaderUtils.getOptions(this) || {}
// 校验传入参数是否符合你的规范
// 入参第一个是我们指定的约束规则scema.json,第二个是传入的options
validate(schema, options)
this.callback(null, content, map, meta)
// return content
}
module.exports.pitch = function (content, map, meta) {
console.log("loader-index3-pitch")
}
因为上面我们约束了options
的name
和age
的类型,那我们特意来写错一下来看下会是什么样的效果
假设我把name
改成number
类型的123
然后npm run build
来看下效果
可以看到,webpack把loader
中我们通过schema-utils
约束过的options
中有误的信息给抛了出来
八、没有什么八了
看到这里你基本已经会写自己的loader了,发动你的小脑瓜去实践吧!!!嘎嘎嘎~~
结语
往期好文推荐「我不推荐下,大家可能就错过了史上最牛逼vscode插件集合
啦!!!(嘎嘎嘎~)😄」