其实你爱我像谁,扮演什么角色我都会。
前情回顾
上篇文章简单介绍了一下loader
,今天谈一谈自己对loader
的理解。
什么是loader
loader
的定义:一个导出了一个函数的node模块儿。当某些资源或文件需要转换时这个函数被调用。并且这个函数或方法有权调用webpack提供的Loader API
。
loader的配置
通常情况下loader
的配置在webpack的module.rules
对象中,例如:
module: {
rules: [
{
// test: /.vue$/,
// use: [
// {
// loader: 'iview-loader',
// options: {
// prefix: true
// }
// }
// ]
test:/.vue/,
loader: 'test-loader'
},
],
},
test
表示匹配到哪些文件,loader
表示使用哪个loader对这些文件进行转换。这里我写了个test-loader
,用来测试我本地自己写的一个demo。
测试自己的loader
自己的电脑里有之前的项目,随便起了一个基于vue
的项目,在项目的根目录创建文件夹test-loader
。我项目的文件夹名称为h5_pay
。所以直接执行了以下命令:
# h5_pay 是我自己的项目名称 这个可以根据自己的改
cd h5_pay
mkdir test-loader && npm init
然后在test-loader
文件夹下的index.js
中添加如下代码:
module.exports = function(content) {
console.log('content',content)
return content && content.replace(/terrence/gi, 'Javascript高级程序设计')
}
这个函数接受一个参数content
,表示匹配到的文件内容。如果内容中匹配到terrence
这个单词,就替换为Javascript高级程序设计
。
接下来执行:
代码语言:javascript复制npm link test-loader
npm link
这个命令会将本地的测试包放入node_modules
中。放入的动作其实是个软连接或者硬链接,应该是个软连接。如图:
执行完这个命令以后,重启本地服务,打开页面,就会发现代码中的terrence
已经被替换为Javascript高级程序设计
。
而对于index.js
中函数接收的参数content
,打印出来就是接收到的整个vue
文件的代码,如图:
content是什么
再举个例子 iview-loader
iview-loader
的主要功能是将带有前缀i-
的组件替换为驼峰,例如i-affix
替换为Affix
。
iview-loader
中有两个文件,tag-map.js
和loader.js
。
tag-map.js
定义了带前缀组件和驼峰组件(暂且怎么叫吧)的映射关系。
// tag-map.js
exports.tag = {
'Switch': 'i-switch',
'Circle': 'i-circle'
};
exports.prefixTag = {
'i-affix': 'Affix',
'i-alert': 'Alert',
'i-anchor': 'Anchor',
'i-anchor-link': 'AnchorLink',
'i-auto-complete': 'AutoComplete',
'i-avatar': 'Avatar',
'i-back-top': 'BackTop',
'i-badge': 'Badge',
'i-breadcrumb': 'Breadcrumb',
'i-breadcrumb-item': 'BreadcrumbItem',
'i-button': 'Button',
'i-button-group': 'ButtonGroup',
'i-card': 'Card',
'i-carousel': 'Carousel',
'i-carousel-item': 'CarouselItem',
'i-cascader': 'Cascader',
...
};
loader.js
定义了组件名称的替换法则,并在匹配到vue
文件时进行替换。
// loader.js
"use strict";
const loaderUtils = require('loader-utils');
const { tag, prefixTag } = require('./tag-map');
function replaceTag(source, tagMap) {
Object.keys(tagMap).forEach(i => {
source = source.replace(new RegExp(`<${i}(?!-)`, 'g'), `<${tagMap[i]}`)
.replace(new RegExp(`</${i}>`, 'g'), `</${tagMap[i]}>`);
})
return source;
}
module.exports = function (source) {
const options = loaderUtils.getOptions(this);
this.cacheable();
let newSource = source;
newSource = replaceTag(newSource, tag);
if ('prefix' in options && options.prefix) {
newSource = replaceTag(newSource, prefixTag);
}
return newSource;
};
这里需要注意的是引用了一个新的包loader-utils
。loader-utils是一个webpack工具类,通过一些方法配合loader处理文件。大致内容如图:
这个包在开发loader
时非常重要。
总结
- 自己如何开发一个
loader
- 简单分析下
iview-loader
- 加深对
loader
的理解
javascript基础知识总结