Search code examples
javascriptvue.jsviterollup

How to tell Vite to exclude a subset of files in a directory from build?


I created a new Vue app using npm create vue. During runtime this app fetches a configuration and reads a string from it. This string represents the name of a component to render inside the app. Those dynamic components live inside a "pluggable" directory

.
└── src
    ├── App.vue
    └── pluggables
        ├── ThisFoo.vue
        └── ThatBar.vue

So basically what the App.vue file does is

<script setup lang="ts">
import { onMounted, shallowRef, defineAsyncComponent } from "vue";

const pluggableComponent = shallowRef();

onMounted(() => {
  // fetch configuration
  const componentName = "ThisFoo"; // extract from configuration

  pluggableComponent.value = defineAsyncComponent(() => import(`./pluggables/${componentName}.vue`));
});
</script>

<template>
  <div>Pluggable below:</div>
  <component :is="pluggableComponent" />
</template>

I have access to the configuration file during build time and know which components I need during runtime and which ones to consider as "dead code" based on this configuration. Is there a way to tell Vite to exclude the unused components from the build?

E.g. exclude the whole pluggables directory but include the required components from the pluggables directory

vite build --exclude ./src/pluggables/** --include ./src/pluggables/ThisFoo.vue

or by creating a custom Vite build function I can call during CI/CD and pass in an array of component names.


Solution

  • To exclude some files from the build process you can mark them as external files by using the external config of Rollup

    // vite.config.js
    import { defineConfig } from "vite";
    import vue from "@vitejs/plugin-vue";
    import * as path from "path";
    import { fileURLToPath } from "node:url";
    
    const filesNeedToExclude = ["src/pluggables/Comp1.vue", "src/pluggables/Comp2.vue"];
    
    const filesPathToExclude = filesNeedToExclude.map((src) => {
      return fileURLToPath(new URL(src, import.meta.url));
    });
    
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [vue()],
      resolve: {
        alias: {
          "@": path.resolve(__dirname, "./src"),
        },
      },
    
      build: {
        manifest: true,
        rollupOptions: {
          external: [
            ...filesPathToExclude
          ],
        },
      },
    });