如何配置Vite在构建时排除目录中未使用的子集文件
如何配置Vite在构建时排除目录中未使用的子集文件
我来给你梳理几个可行的方案,刚好能解决你这种构建时已知需保留组件、要排除目录中其他未使用文件的需求:
方案一:利用Rollup配置精准过滤(推荐用于复杂场景)
Vite底层依赖Rollup,所以我们可以直接在vite.config.ts里通过Rollup的配置规则,精准控制哪些文件需要打包、哪些要排除:
// vite.config.ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' // 这里可以从你的配置文件读取需要保留的组件名,CI/CD时也可以动态传入 const requiredComponents = ['ThisFoo'] // 替换为你的目标组件列表 export default defineConfig({ plugins: [vue()], build: { rollupOptions: { external: (id) => { // 只排除pluggables目录中不在白名单里的组件 if (id.includes(path.resolve(__dirname, 'src/pluggables'))) { const componentFileName = path.basename(id) const componentName = componentFileName.replace('.vue', '') return !requiredComponents.includes(componentName) } return false } } } })
这个配置的逻辑是:对所有模块路径进行判断,如果是pluggables目录下的文件,且不在我们的白名单里,就标记为外部依赖(不会被打包进最终产物)。
方案二:把动态导入转为静态可分析的形式(最简单,利用Tree Shaking)
你现在用的是import(./pluggables/${componentName}.vue)这种完全动态的导入,Vite会默认打包目录下所有可能的组件,因为它没法提前推断componentName的值。但既然你构建时就知道要加载哪个组件,可以把导入逻辑改成静态可被Tree Shaking分析的形式:
步骤1:在Vite配置中注入构建时已知的组件名
// vite.config.ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import fs from 'fs' // 从你的配置文件读取目标组件名 const config = JSON.parse(fs.readFileSync('./your-config-file.json', 'utf-8')) const targetComponent = config.componentName export default defineConfig({ plugins: [vue()], // 把组件名注入为全局常量,构建时会被替换成具体值 define: { '__TARGET_COMPONENT__': JSON.stringify(targetComponent) } })
步骤2:修改App.vue的导入逻辑
<script setup lang="ts"> import { onMounted, shallowRef } from "vue"; const pluggableComponent = shallowRef(); onMounted(() => { // 因为__TARGET_COMPONENT__是构建时的常量,Vite会把这个导入解析为静态路径 import(`./pluggables/${__TARGET_COMPONENT__}.vue`).then(mod => { pluggableComponent.value = mod.default }); }); </script> <template> <div>Pluggable below:</div> <component :is="pluggableComponent" /> </template>
这样Vite在构建时就能精准识别到只需要打包指定的组件,其他未用到的会被Tree Shaking自动排除,非常简洁。
方案三:自定义Vite插件过滤文件(灵活度最高)
如果需要更复杂的过滤逻辑,可以写一个简单的Vite插件,直接在构建过程中忽略不需要的文件:
// vite.config.ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' const requiredComponents = ['ThisFoo'] export default defineConfig({ plugins: [ vue(), { name: 'filter-unused-pluggables', transform(code, id) { // 判断当前文件是否在pluggables目录下 if (id.includes(path.resolve(__dirname, 'src/pluggables'))) { const componentName = path.basename(id, '.vue') // 如果不在白名单里,返回空内容,Rollup会忽略这个文件 if (!requiredComponents.includes(componentName)) { return '' } } } } ] })
额外:CI/CD中动态指定组件的脚本方案
如果你想在CI/CD过程中通过命令行参数传入需要保留的组件,可以写一个简单的Node脚本,动态生成Vite配置再执行构建:
// build-with-components.js const fs = require('fs') const { execSync } = require('child_process') // 从命令行参数获取需要保留的组件名(比如node build-with-components.js ThisFoo ThatBar) const requiredComponents = process.argv.slice(2) // 生成临时Vite配置文件 const viteConfigContent = ` import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' export default defineConfig({ plugins: [vue()], build: { rollupOptions: { external: (id) => { if (id.includes(path.resolve(__dirname, 'src/pluggables'))) { const componentName = path.basename(id, '.vue') return !${JSON.stringify(requiredComponents)}.includes(componentName) } return false } } } }) ` fs.writeFileSync('./vite.config.temp.ts', viteConfigContent) // 执行构建 execSync('vite build --config vite.config.temp.ts', { stdio: 'inherit' }) // 清理临时文件 fs.unlinkSync('./vite.config.temp.ts')
然后在package.json里添加脚本:
{ "scripts": { "build:custom": "node build-with-components.js" } }
CI/CD时直接运行npm run build:custom ThisFoo就能只打包指定组件了。
备注:内容来源于stack exchange,提问作者baitendbidz




