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

回到顶部