处理 vue2 + vite 项目 里面的require(...+变量+...) 函数
目前 vite 还不是很成熟,因为他的启动速度快,以至于我们想在开发环境使用它,生产还是继续使用webpack,也就是vite + webpack 共存的情况下:
vite 有个插件 vite-plugin-require-transform 会自动把 require() 函数转化为 import ...from 的方式,但是有一种情况他忽略了,就是 require() 函数里面的路径是变量拼成的,而且该插件也不支持我现在说的这种格式。例如 require("../../assets/img/" + _vm.filePath + ".png") ,这种情况,它就是没有处理的,所以我们自己写一个插件来解决这个问题
1. 插件定义
const path = require('path') const glob = require('glob') export const replaceRequireVariable = (includes = []) => { return { name: 'replaceRequireVariable', apply: 'serve', transform(code, id) { let result = code if (includes.some(item => id.includes(item))) { result = replaceRequrieDynamic(code, id) } return result } } } /** * 替换包含变量的require函数 * @param {*} code * @param {*} id * @returns */ const replaceRequrieDynamic = function(code, id) { // node_modules排除 if (/\/node_modules\//g.test(id)) return code const regex = /require\(\(\s*(["].*["])\s*\)\)/g const requireMatches = code.matchAll(regex) let importString = '' let constObjString = '' for (const item of requireMatches) { /** * item[0] 匹配出来的选项 例如:require(("../../assets/img/" + _vm.filePath + ".png")) * item[1] 匹配出来的路径 例如:"../../assets/img/" + _vm.filePath + ".png" * */ const arr = item[1].split('+') // 组装获取文件夹下边文件的全部路径 let allFilePath = '' arr.forEach((itemStr, index) => { // 去除”和多余的空格 itemStr = itemStr.replace(/"/g, '').trim() if (index === 0) { const lastIndex = itemStr.lastIndexOf('/') allFilePath = insertStr(itemStr, lastIndex + 1, '**/') } else if (index === arr.length - 1 && itemStr.startsWith('.')) { allFilePath += itemStr } else { allFilePath += '*' } }) // 获取最后一个/的位置 const lastIndex = id.lastIndexOf('/') // 获取Id最后一个/之前的全路径 const absoluteDir = id.substr(0, lastIndex + 1) // 根绝id的全路径和相对路径获取要去获取文件的全路径 // /mnt/c/Users/yangyanhui/projects/huiyan-manage-static/src/assets/img/**/icon_*.png const readAbsoluteDir = path.join(absoluteDir, allFilePath) // 拿到所有的指定文件 const allFile = glob.sync(readAbsoluteDir) const fileObj = `_$_file_obj_${randomString(6)}` let fileObjectStr = '' if (allFile.length) { // 拼接文件常量 fileObjectStr = `const ${fileObj} = {` allFile.forEach((file, index) => { // 获取引入文件的相对路径 const relativePath = path.relative(absoluteDir, file) const tempFile = `_$_img_${randomString(6)}` fileObjectStr += `'${relativePath}': ${tempFile},` if (index === allFile.length - 1) fileObjectStr += '}' importString += `import ${tempFile} from '${file}';\n` }) constObjString += `${fileObjectStr};\n` // require(("../../assets/img/" + _vm.filePath + ".png")) 用 fileObj 对象替换 code = code.replace(item[0], `${fileObj}[${item[1]}]`) } } code = importString + constObjString + code return code } /** * * @param {必填,数字} length * @returns hash串 */ function randomString(length) { const code = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' let result = '' for (let index = 0; index < length; index++) { result += code[Math.floor(Math.random() * code.length)] } return result } function insertStr(source, start, newStr) { return source.slice(0, start) + newStr + source.slice(start) }
2. 使用插件
import { replaceRequireVariable } from './plugins.js' export default defineConfig({ plugins: [ replaceRequireVariable(['hyFileStyle.vue?vue&type=template&lang.js']) // 替换 组件里面require加变量的内容 ],
})
该插件需要优化,转发请注明出处。