虽然webpack现有的loader插件可以满足大部分情况下的开发需求,还是有一些特殊的需求自己写loader实现更方便一些,本篇文章列出来一些loader demo,希望对入门loader开发的程序员有所启发。
loader本地开发
在webpack中添加如下配置
module: {
rules: [
{
test: /\.html$/,
use: [
{
loader: 'loader-demo'
}
]
}
]
},
resolveLoader: {
alias: {
"loader-demo": require.resolve("./loaderDemo")
}
}
loaderDemo.js是loader的源文件
往html里插入js代码
作用是可以往index.html文件里面插入一段js代码,本质上就是webpack 会把html内容以字符串的形式传过来,用正则找到tag,添加一些字符串
module.exports = function(source) {
const index = RegExp('</body>').exec(source).index
return source.slice(0, index) + "<script>function a(){console.log('hhh')} a()</script>" + source.slice(index)
}
git地址:https://github.com/hellofriday/webpackloaderdemo/tree/insert-html-demo
往html文件插入另一个文件的内容
这个还是插入内容,不过会涉及到文件读取,异步操作
const fs = require('fs')
const path = require('path')
const loaderUtils = require('loader-utils')
module.exports = async function(source) {
const result = RegExp('(@include\\()(.*?)\\)').exec(source)
let filePath = result[2] // 获取需要插入的文件路径 需要把它处理成绝对路径
const request = loaderUtils.urlToRequest(filePath)
const url = await resolvePath(this, path.resolve(__dirname, 'src'), request)
const res = await readFile(url, {encoding: "utf8"})
return source.replace(result[0], res)
}
function readFile(url, options) {
return new Promise((resolve, reject) => {
fs.readFile(url, options, (err, data)=>{
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
function resolvePath(_this, fullPath, request) {
return new Promise((resolve, reject) => {
_this.resolve(fullPath, request, (err, url)=>{
if (err) {
reject(err)
} else {
resolve(url)
}
})
})
}
demo地址:https://github.com/hellofriday/webpackloaderdemo/tree/demo2
参考:
https://juejin.cn/post/6844904176250519559
https://imweb.io/topic/5baca58079ddc80f36592f1a