Search code examples
vue.jscompilationbundlevitebundler

move html files out of src folder in dist vite


I'm currently engaged in a Vue.js project that utilizes Vite as the build tool. My objective is to adjust the Vite configuration in a way that the HTML files are situated directly within the 'dist' folder, alongside the 'assets' folder upon building the project. Presently, the HTML files are being placed in subfolders within the 'dist' directory. Here's the current configuration I'm using in Vite:

import { defineConfig } from 'vite';
import { resolve } from 'path';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  publicDir: false,
  build: {
    outDir: resolve(__dirname, 'dist'),
    emptyOutDir: true,
    rollupOptions: {
      input: {
        login: resolve(__dirname, 'src/login/login.html'),
        cadastro: resolve(__dirname, 'src/cadastro/cadastro.html'),
        home: resolve(__dirname, 'src/home/home.html')
      }
    }
  },
  plugins: [vue()]
});

my outdir looks like this:

dist/
├── assets/
│   ├── cadastro-118e7637.css
│   ├── cadastro-669bfe7b.js
│   ├── home-7dbac266.js
│   ├── home-a84cd419.css
│   ├── login-572efaa1.css
│   ├── login-9a4f8a3b.js
│   ├── modulepreload-polyfill-3cfb730f.js
│   └── runtime-dom.esm-bundler-4af65d94.js
└── src/
    ├── cadastro/
    │   └── cadastro.html
    ├── home/
    │   └── home.html
    └── login/
        └── login.html

How do I make outdir look like this:

dist/
├── assets/
│   ├── cadastro-118e7637.css
│   ├── cadastro-669bfe7b.js
│   ├── home-7dbac266.js
│   ├── home-a84cd419.css
│   ├── login-572efaa1.css
│   ├── login-9a4f8a3b.js
│   ├── modulepreload-polyfill-3cfb730f.js
│   └── runtime-dom.esm-bundler-4af65d94.js
├── cadastro/
│   └── cadastro.html
├── home/
│   └── home.html
└── login/
    └── login.html

?


Solution

  • From what I understand, Vite does not change html files in multi-page mode, since it might screw with the dev server, as per the docs:

    Note that for HTML files, Vite ignores the name given to the entry in the rollupOptions.input object and instead respects the resolved id of the file when generating the HTML asset in the dist folder. This ensures a consistent structure with the way the dev server works.


    The common approach is to change the project root to the src folder, which has the downside that you have to fix other paths that are evaluated relative to root (like the dist folder):

    // vite.config.js
    export default defineConfig({
      ...
      root: 'src',
      publicDir: '../public', // relative to root
      emptyOutDir: true, // if you still want to clear outDir without warning
      build: {
        outDir: '../dist/', // relative to root
        ...
      }
    })
    

    Alternatively, you can change the file name of the HTML asset manually in a simple inline plugin:

    // vite.config.js
    export default defineConfig({
      plugins: [
        ...
        {
          name: 'remove-src-dir-from-html-path',
          enforce: 'post',
          generateBundle(_,bundle) {
            const htmlFileInSrcFolderPattern = /^src\/.*\.html$/
            for (const outputItem of Object.values(bundle)) {
              if (!htmlFileInSrcFolderPattern.test(outputItem.fileName)) {
                continue
              }
              outputItem.fileName = outputItem.fileName.replace('src/', '')
            }
          }
        }
      ],
    

    I prefer this because despite everything, it still feels less fragile than changing root. But I am not sure if it works for everybody. If you run into issues with this, I'd be curious to know what they are!