wuhan-gl/vite/plugins/conditional-assets.js

182 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @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`)
}
}
}