适用webpack3。
loader
loader主要用于预处理
源文件,类似于构建工具中的任务
概念
开始一段简单的loader
编写
- 编写一段js代码,如
function loader (source) {
var self = this;
return source.replace(/<div(.*?)>/, function (str) {
var value = convertStr(self.resource)
return str.substring(0, str.length - 1) + ' data-source="' + value.substring(value.indexOf('src')) + '">'
})
}
function convertStr (str) {
return str.replace(/\\/g, function (v) {
return '/'
})
}
module.exports = loader;
其中source
返回的是源文件内容
或者上一个loader返回的内容
。没错,loader
可以有多个,并且按照从后往前
的顺序执行。
this
是webpack的实例,this.resource
获得当前的文件地址。
- 在webpack配置文件中,配置
resolveLoader: {
modules: [
path.resolve(__dirname, '../build/rules'),
'node_modules'
]
},
因为是本地自制的loader,需要声明地址。默认会直接寻找node_modules
中的loader
。
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: vueLoaderConfig
},
{
loader: 'vue-source-loader'
}
]
},
和vue-loader
一起监听.vue
文件。vue-source-loader
是第一个执行的loader
plugin
plugin主要完成loader
无法完成的事情
plugin的主要执行apply
方法, 在plugin中存在很多hook
钩子,即生命周期
- 一个小栗子(完成后效果和上面的
loader
一致,但是十分复杂且不利于阅读,仅供了解,因为是修改打包后的文件,定有不足之处)
function MixBase () {
}
MixBase.prototype.apply = function (compiler) {
compiler.plugin('emit', function (compilation, callback) {
var arr = new Set()
compilation.chunks.forEach(function (chunk) {
chunk.modules.forEach(function (module) {
module.fileDependencies.forEach(function (filepath) {
if (/\.vue$/.test(filepath)) {
arr.add(filepath)
}
})
})
chunk.files.forEach(function (filename) {
if (/\.js$/.test(filename)) {
var source = compilation.assets[filename].source(),
name = source.match(/name:[\'|\"](.*?)[\'|\"]/g),
isApp = false,
finalSource,
componentsArr = []
if (name) {
for (var i = 0; i < name.length; i++) {
var item = name[i].match(/name:[\'|\"](.*?)[\'|\"]/)[1]
if (item === 'App') isApp = true
componentsArr.push(item)
}
if (isApp) {
finalSource = source.replace(/;return [a-z|A-Z]\([\"|\'](.*?);/, function (v) {
return v.replace(/attrs:\{id:(.*?)\}/, function (k) {
return k.substring(0, k.length - 1) + ',"data-source":"src/app.vue"}'
})
})
} else {
finalSource = source.replace(/;return [a-z|A-Z]\([\"|\'](.*?),/, function (v) {
var newStr
for (var k of arr) {
if (k.indexOf(componentsArr[0]) !== -1) {
newStr = k.replace(/\\/g, function (str) {
return '/'
})
newStr = newStr.substring(newStr.indexOf('src'))
}
}
return v + '{attrs:{"data-source":"' + newStr + '"}},'
})
for (var j = 1; j < componentsArr.length; j++) {
if (componentsArr[j].trim()) {
var reg = new RegExp(`,[a-z|A-Z]\\([\\"|\\']${componentsArr[j].toLocaleLowerCase()}(.*?)\\)`)
console.log(`,[a-z|A-Z]\\([\\"|\\']${componentsArr[j].toLocaleLowerCase()}(.*?)\\)`)
finalSource = finalSource.replace(reg, function (v) {
var newStr
for (var k of arr) {
if (k.indexOf(componentsArr[j]) !== -1) {
newStr = k.replace(/\\/g, function (str) {
return '/'
})
newStr = newStr.substring(newStr.indexOf('src'))
}
}
return v.substring(0, v.length - 1) + ',{attrs:{"data-source":"' + newStr + '"}})'
})
}
}
}
compilation.assets[filename] = {
source: function () {
return finalSource
},
size: function () {
return finalSource.length
}
}
}
}
})
})
callback()
})
}
module.exports = MixBase
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。