教你写个webpack的loader

4次阅读

共计 2689 个字符,预计需要花费 7 分钟才能阅读完成。

loader 介绍
loader 是将指定格式的资源文件转化成一定格式输出, 例如 sass-loader 将 scss 文件转化成 css 文件, babel-loader 将 ES6 转化成 ES5. 一个 loader 的结构就是一个函数, 最简单 loader 如下:
module.exports = function(content){// content 就是你要处理文件的内容, 如处理 App.vue 文件,content 就是你在 App.vue 写的代码
//… 中间可以对 content 处理
return content // 这里你也可以用 this.callback(null, content) 导出
}
loader 的使用, 配置 webpack 文件
{
test: /\.css$/,
// easy-css-loader 就是下面我要写的 loader
use: [‘style-loader’, ‘css-loader’, ‘easy-css-loader’]
}
loader 解析顺序是: 从右向左, 上一个 loader 处理完的 content 传递给下一个 loader, 一般每种 loader 功能是单一的
easy-css-loader 实现
easy-css-loader 将实现一些 css 代码的简写 (虽然 sass 等已经有这个功能, 但是每次都要写个.scss 文件在导入, 不大方便).
效果图
例: 对应代码
<div>
<div class=”easy-css”>2</div>
</div>
<style >
.easy-css{
border: 1px solid red;
posC;
wh(100px, 80px);
font(20px, blue, center);
comB(http://ww1.sinaimg.cn/large/b44313e1gy1fyz1li77jzj20q411wdop.jpg);
}
</style>

下面讲讲 font(..) 解析过程
<!– 你代码写的样式 –>
<style >
.easy-css{
font(20px, yellow);
}
</style>
<!– 会解析成 –>
<style >
.easy-css{
font-size: 20px;
color: yellow;
text-align: left;
}
</style>
上面的代码, 如果在 webpack 配置解析.css 的自定义的 loader, 那么在 loader 里, 前面说的 content 就长成这样了
.easy-css{
font(20px, yellow);
}
是不是只要正则匹配 font(20px, yellow), 替换成
font-size: 20px;
color: yellow;
text-align: left;
下面是 loader 的代码
/**
* @param {*} fontStr 待解析字符串的 `font(..)`
* @returns 解析完 css 字体样式
*/
function fontParse(fontStr) {
let start = fontStr.indexOf(‘(‘) + 1 //‘(’后面一个字符位置
let args = fontStr.slice(start, -1) // 就是取 font(..) 括号里面字符串, 按例子 args 为 ’20px, yellow’
let argsList = args.split(‘,’) // 分割成数组 [’20px’, ‘yellow’]
switch (argsList.length) {// 判断开发者传递参数个数
case 2:
argsList.push(‘left’)
break
case 1:
argsList.push(‘#000’, ‘left’)
break
}
cssName = [‘font-size’, ‘color’, ‘text-align’].map((item, index) => {
return `${item}:${argsList[index]}` // 组合成新的样式数组
})
let cssStr = cssName.join(‘;’) // 形成新 css 字符串
return cssStr // 回调
}
module.exports = function (content) {// content 就是在 <style>..</style> 写的里面的内容, 或者引入的.css 文件
content = content.replace(/font\((.|\n)*?\)/ig, (str) => fontParse(str))
this.cacheable() // 缓存
this.callback(null, content) // 回调
}
上面的正则会匹配到 font(..), str 就匹配到的 font(20px, yellow) 字符串, 最终会被 fontParse(str) 值替换. 就已经完成 font 的解析
其它样式的解析可以写成链式
module.exports = function (content) {// content 就是在 <style>..</style> 写的里面的内容, 或者引入的.css 文件
content = content.replace(/font\((.|\n)*?\)/ig, (str) => fontParse(str)) // 解析 font() 字体样式
.replace(/wh\((.|\n)*?\)/ig, (str) => whParse(str)) // 解析 wh() 宽高样式
.replace(/posC(.|\n)*?;/ig, (str) => posCParse(str)) // 解析 posC 居中样式
.replace(/flex(.|\n)*?;/ig, (str) => flexParse(str)) // 解析 flex 布局样式
.replace(/comB(.|\n)*?;/ig, (str) => backParse(str)) // 解析 comB(..) 背景图片样式
.replace(/posL(.|\n)*?;/ig, (str) => posLRParse(str, ‘left’)) // 解析 posL(..) 居左样式
.replace(/posR(.|\n)*?;/ig, (str) => posLRParse(str, ‘right’)) // 解析 posR(..) 居右样式
this.cacheable() // 缓存
this.callback(null, content) // 回调
}
一个 loader 大功告成
说明
具体的可以去看源码, 在 github 上, 觉得可以的话帮忙 star 一下
我发布 npm 包 easy-css-loader 使用如下配置
{
module: {
rules: [
{
test: /\.css$/,
use: [‘style-loader’, ‘css-loader’, ‘easy-css-loader’] // 顺序一定要注意
}
]
}
}

正文完
 0