vue自定义loader运行报错?
写了个loader想对vue单文件的template预先做些处理,不过运行起来会有报错
vue.config.js
const { defineConfig } = require('@vue/cli-service')const path = require('path')
// const { VueLoaderPlugin } = require('vue-loader')
module.exports = defineConfig({
transpileDependencies: true,
chainWebpack: config => {
config.module
.rule('vue')
// .test(/\.vue$/)
.use('vue-loader')
.loader('vue-loader')
.end()
.use('my-loader')
.loader(path.resolve(__dirname, './my-loader.js'))
// .before('vue-loader')
.end()
}
})
my-loader.js
module.exports = function (content) { const templateMatch = content.match(/<template>([\s\S]*?)<\/template>/);
let restContent = content
if (templateMatch) {
const templateContent = templateMatch[1];
restContent = content.replace(/<template>[\s\S]*?<\/template>/, '');
let returnContent = templateContent.replace(/<\/el-/g, '\n</el-')
returnContent = returnContent.replace(/<el-/g, '\n<el-')
returnContent = returnContent.replace(/<input/g, '\n<input')
var regInput = /<(input)([^<>]*)>/g // tmp
let contentArr = returnContent.split('\n')
let resultArr = contentArr.map((item, index) => {
if (regInput.test(item)) {
item = item.replace(/<input/g, '<input name="input_name"')
}
return item
})
const result = resultArr.join('\n')
console.log('result', result)
// return result
return `module.exports = ${JSON.stringify(result + restContent)};`
// this.callback(null, result)
// return
} else {
// return content;
return `module.exports = ${JSON.stringify(content)};`
// this.callback(null, content)
// return
}
}
自定义的loader只是在vue-loader前处理一下template,之后的处理应该会交给vue-loader继续执行。不过实际运行起来,vue单文件的js跟css都会有错误。
ERROR in ./src/App.vue?vue&type=style&index=0&id=7ba5bd90&lang=css
百思不得其解,不知道各位能不能不能帮忙指点迷津。项目代码已上传到github
看过相关文章,暂时不清楚具体原因
回答:
代码微调了下,不报错了
1、自定义的loader要在vue-loader之前
2、loader的链式处理依赖了一个执行顺序,要确保经过所有的loader之后生成一个带module.exports 的js字符串代码文件;自定义的loader只是中间过程,直接返回内容交给vue-loader处理,不需要module.exports
const { defineConfig } = require('@vue/cli-service')const path = require('path')
// const { VueLoaderPlugin } = require('vue-loader')
module.exports = defineConfig({
transpileDependencies: true,
chainWebpack: config => {
config.module
.rule('vue')
// .test(/\.vue$/)
.use('vue-loader')
.loader('vue-loader')
.end()
.use('my-loader')
.loader(path.resolve(__dirname, './my-loader.js'))
.before('vue-loader')
.end()
}
})
const fs = require('fs');const path = require('path');
module.exports = function (content) {
var output = ''
var moudle = this.resource.split('\\src\\')[1]
console.log(moudle)
var dir = moudle.replace(/[?&=]/g, '_')
var type = 'js'
if (moudle.includes('type=style')) {
type = 'css'
}
if (moudle.includes('type=template')) {
type = 'html'
}
if (type == 'html') {
let returnContent = content.replace(/<\/el-/g, '\n</el-')
returnContent = returnContent.replace(/<el-/g, '\n<el-')
returnContent = returnContent.replace(/<input/g, '\n<input')
var regInput = /<(input)([^<>]*)>/g // tmp
let contentArr = returnContent.split('\n')
let resultArr = contentArr.map((item, index) => {
if (regInput.test(item)) {
item = item.replace(/<input/g, '<input name="input_name"')
}
return item
})
const result = resultArr.join('\n')
output = result
createDirAndWriteFile(`.output/${dir}已处理`, `old.${type}`, content);
createDirAndWriteFile(`.output/${dir}已处理`, `new.${type}`, output);
} else {
output = content;
createDirAndWriteFile(`.output/${dir}未处理`, `old.${type}`, content);
createDirAndWriteFile(`.output/${dir}未处理`, `new.${type}`, output);
// for (const key in this) {
// if (Object.hasOwnProperty.call(this, key)) {
// const element = this[key];
// try {
// if (typeof element == 'object') {
// createDirAndWriteFile(`.output/${dir}未处理`, `${key}.json`, JSON.stringify(element, null, 2));
// } else {
// createDirAndWriteFile(`.output/${dir}未处理`, `${key}.txt`, element);
// }
// } catch (error) {
// }
// }
// }
}
return output
}
function createDirAndWriteFile(dirPath, fileName, content) {
// 创建目录
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
// 拼接文件路径
const filePath = path.join(dirPath, fileName);
// 写入文件
fs.writeFileSync(filePath, content);
}
回答:
自定义的loader通过split再拼接,运行会有问题,具体原因不清楚。
不过直接通过正则去操作,就可以运行了
代码如下:
const tagRegList = [ { tag: '<el-input', reg: /<el-input\b(?!-number)[^>]*>/g, attr: 'name' },
{ tag: '<el-input-number', reg: /<el-input-number\b[^>]*>/g, attr: 'name' },
{ tag: '<el-date-picker', reg: /<el-date-picker\b[^>]*>/g, attr: 'name' },
{ tag: '<el-select', reg: /<el-select\b(?!-v2)[^>]*>/g, attr: 'name' },
{ tag: '<el-button', reg: /<el-button\b[^>]*>/g, attr: 'btn-id' },
]
function getModel(str) {
const match = str.match(/v-model="([^"]*)"/)
const modelValue = match ? match[1] : null
return modelValue
}
function getEventName(str) {
const match = str.match(/@click="([^"()]*)/)
const eventName = match ? match[1] : null
return eventName
}
/* eslint-disable no-unreachable */
module.exports = function (content) {
const templateMatch = content.match(/<template>([\s\S]*?)<\/template>/)
if (templateMatch) {
let transformCode = content
tagRegList.forEach(item => {
const matchTagList = content.match(item.reg)
matchTagList?.forEach(matchTag => {
// console.log('match', matchTag)
if (matchTag.length && matchTag.indexOf(item.attr) === -1) {
transformCode = transformCode.replace(
matchTag,
item.tag +
` ${item.attr}="${item.attr === 'btn-id' ? getEventName(matchTag) : getModel(matchTag)}" ` +
matchTag.substring(item.tag.length, matchTag.length)
)
}
})
})
return transformCode
} else {
return content
}
}
以上是 vue自定义loader运行报错? 的全部内容, 来源链接: utcz.com/p/935352.html