You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何配置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

火山引擎 最新活动