182 lines
6.2 KiB
JavaScript
182 lines
6.2 KiB
JavaScript
/*
|
||
* @Author: 季万俊
|
||
* @Date: 2025-12-05
|
||
* @Description: 根据资源版本条件导入资源和组件
|
||
*/
|
||
|
||
export default function createConditionalAssets(assetsVersion) {
|
||
if (!assetsVersion) {
|
||
return { name: 'vite-plugin-conditional-assets' }
|
||
}
|
||
|
||
// 确定需要排除的版本
|
||
const allVersions = ['wuhan', 'shiyan', 'suzhou']
|
||
const excludeVersions = allVersions.filter(v => v !== assetsVersion)
|
||
|
||
console.log(`\n🎯 条件资源插件已启用`)
|
||
console.log(` 当前版本: ${assetsVersion}`)
|
||
console.log(` 排除版本: ${excludeVersions.join(', ')}\n`)
|
||
|
||
return {
|
||
name: 'vite-plugin-conditional-assets',
|
||
enforce: 'pre',
|
||
|
||
// 拦截模块解析 - 阻止不需要的组件被加载
|
||
resolveId(source, importer) {
|
||
// 忽略样式文件和其他非组件文件
|
||
if (source.includes('.scss') || source.includes('.css') ||
|
||
source.includes('.sass') || source.includes('.less') ||
|
||
source.includes('?url') || source.includes('?raw')) {
|
||
return null
|
||
}
|
||
|
||
// 检查是否是需要排除的 plan 组件
|
||
for (const excludeVersion of excludeVersions) {
|
||
if (source.includes(`/plan/${excludeVersion}.vue`) ||
|
||
source.includes(`\\plan\\${excludeVersion}.vue`)) {
|
||
console.log(` 🚫 阻止加载: plan/${excludeVersion}.vue`)
|
||
// 返回虚拟模块 ID
|
||
return '\0virtual:empty-component'
|
||
}
|
||
}
|
||
return null
|
||
},
|
||
|
||
// 加载虚拟模块 - 返回空组件
|
||
load(id) {
|
||
if (id === '\0virtual:empty-component') {
|
||
// 返回一个空的 Vue 组件
|
||
return `
|
||
export default {
|
||
name: 'EmptyComponent',
|
||
render() {
|
||
return null
|
||
}
|
||
}
|
||
`
|
||
}
|
||
return null
|
||
},
|
||
|
||
// 在构建时转换代码
|
||
transform(code, id) {
|
||
// 只在构建模式且是 dashboard/index.vue 时处理
|
||
if (!id.includes('dashboard/index.vue')) {
|
||
return null
|
||
}
|
||
|
||
// 检测当前导入的 plan 组件
|
||
const planImportRegex = /import\s+plan\s+from\s+['"]\.\.\/\.\.\/plan\/(wuhan|shiyan|suzhou)\.vue['"]/
|
||
const match = code.match(planImportRegex)
|
||
|
||
if (match) {
|
||
const currentPlanType = match[1] // 'wuhan' 或 'shiyan'
|
||
|
||
// 如果导入的不是当前需要的版本,替换它
|
||
if (currentPlanType !== assetsVersion) {
|
||
const newCode = code.replace(
|
||
planImportRegex,
|
||
`import plan from "../plan/${assetsVersion}.vue"`
|
||
)
|
||
console.log(` 🔄 替换组件: plan/${currentPlanType}.vue → plan/${assetsVersion}.vue`)
|
||
return { code: newCode, map: null }
|
||
} else {
|
||
console.log(` ✅ 组件已是目标版本: plan/${assetsVersion}.vue`)
|
||
}
|
||
}
|
||
|
||
return null
|
||
},
|
||
|
||
// 最后阶段:从打包结果中删除不需要版本的资源文件
|
||
generateBundle(options, bundle) {
|
||
const removedFiles = []
|
||
const keptFiles = []
|
||
|
||
// 遍历所有打包的文件
|
||
Object.keys(bundle).forEach(fileName => {
|
||
const fileInfo = bundle[fileName]
|
||
|
||
// 检查是否是资源文件
|
||
if (fileInfo.type === 'asset') {
|
||
// 检查各种可能的路径属性,用于判断文件来源
|
||
const pathsToCheck = [
|
||
fileInfo.facadeModuleId,
|
||
fileInfo.name,
|
||
fileInfo.originalFileName,
|
||
fileInfo.preliminaryFileName,
|
||
fileName, // 构建后的文件名
|
||
].filter(p => p) // 过滤掉空值
|
||
|
||
let fileVersion = null // 文件所属的版本
|
||
let shouldRemove = false
|
||
|
||
// 从路径中提取版本信息
|
||
for (const pathToCheck of pathsToCheck) {
|
||
const pathStr = String(pathToCheck)
|
||
|
||
// 检查路径中是否包含版本目录(如 /assets/wuhan/、/assets/shiyan/、/assets/suzhou/)
|
||
for (const version of allVersions) {
|
||
if (pathStr.includes(`/assets/${version}/`) ||
|
||
pathStr.includes(`\\assets\\${version}\\`) ||
|
||
pathStr.includes(`assets/${version}/`) ||
|
||
pathStr.includes(`assets\\${version}\\`)) {
|
||
fileVersion = version
|
||
break
|
||
}
|
||
}
|
||
|
||
if (fileVersion) break
|
||
}
|
||
|
||
// 根据文件版本决定是否保留
|
||
if (fileVersion) {
|
||
// 文件有明确的版本目录
|
||
if (fileVersion === assetsVersion) {
|
||
// 当前版本的文件,保留
|
||
keptFiles.push({ fileName, version: fileVersion, reason: '当前版本资源' })
|
||
shouldRemove = false
|
||
} else {
|
||
// 其他版本的文件,删除
|
||
removedFiles.push({ fileName, version: fileVersion, reason: '其他版本资源' })
|
||
shouldRemove = true
|
||
}
|
||
} else {
|
||
// 文件没有版本目录(如 /assets/icon/、/assets/beij/ 等公共资源),保留
|
||
keptFiles.push({ fileName, version: 'common', reason: '公共资源(无版本目录)' })
|
||
shouldRemove = false
|
||
}
|
||
|
||
if (shouldRemove) {
|
||
delete bundle[fileName]
|
||
}
|
||
}
|
||
})
|
||
|
||
if (removedFiles.length > 0) {
|
||
console.log(`\n🗑️ 已从打包结果中移除 ${removedFiles.length} 个资源文件:`)
|
||
removedFiles.forEach(({ fileName, version, reason }) => {
|
||
console.log(` - ${fileName} (${version}版本, ${reason})`)
|
||
})
|
||
}
|
||
|
||
if (keptFiles.length > 0) {
|
||
console.log(`\n✅ 保留的资源文件 (${keptFiles.length} 个):`)
|
||
const versionGroups = {}
|
||
keptFiles.forEach(({ fileName, version, reason }) => {
|
||
if (!versionGroups[version]) {
|
||
versionGroups[version] = []
|
||
}
|
||
versionGroups[version].push({ fileName, reason })
|
||
})
|
||
Object.keys(versionGroups).forEach(version => {
|
||
console.log(` ${version === 'common' ? '公共资源' : version + '版本'} (${versionGroups[version].length} 个)`)
|
||
})
|
||
}
|
||
|
||
console.log(`\n✅ 构建完成!只包含 ${assetsVersion} 版本的资源\n`)
|
||
}
|
||
}
|
||
}
|
||
|