Search code examples
javascriptrollupvite

Modify build path of assets in Vite/Rollup?


Let's say I have this folder structure:

parent
|-parent.html
|-parent.js
|-child
|--child.html
|--child.js

I want them to output in the same structure in my dist folder. By default this is what gets output:

dist/assets/parent.js
dist/assets/child.js

I want them to output like this:

dist/parent/parent.js
dist/parent/child/child.js

I tried changing the assetFileNames option of Rollup but it didn't do anything.


Solution

  • The output filenames are configured in Rollup with build.rollupOptions. Set output.entryFileNames to configure the location of the entry .js files to match their original directory structure:

    // vite.config.js
    import { fileURLToPath } from 'url';
    import { defineConfig } from 'vite';
    import path from 'path';
    
    const rootDir = fileURLToPath(new URL('.', import.meta.url));
    
    export default defineConfig({
      build: {
        rollupOptions: {
          input: {
            parent: './parent/parent.html',
            child: './parent/child/child.html',
          },
          output: {
            entryFileNames: (assetInfo) => {
              // assetInfo.facadeModuleId contains the file's full path
              if (assetInfo.facadeModuleId) {
                const assetPath = path.dirname(assetInfo.facadeModuleId).replace(rootDir, '');
                return assetPath + '/[name]-[hash].js';
    
              } else {
                return 'assets/js/[name]-[hash].js';
              }
            },
          },
        },
      },
    });
    

    demo

    Notes

    • Assets (such as .css files) and shared modules (vendor .js chunks) cannot be redirected with the solution above because the asset info from the related hooks do not provide the file's full path.

    • In a vanilla Rollup project, output.preserveModules=true would've accomplished the original goal, but that option conflicts with Vite's own settings for Rollup.