94

I am using Vite (https://vitejs.dev/) for a static multipage site. This is the default project folder structure after the build command.

my-app/
├─ node_modules/
├─ dist/
│  ├─ assets/
│  ├─ index.html
├─ index.html
├─ main.js
├─ style.scss
├─ package.json

But I want to make this a multipage site and change the input and output directory for a better organizable way like this

my-app/
├─ node_modules/
├─ package.json
├─ src/
│  ├─ about.html
│  ├─ index.html
│  ├─ main.js
│  ├─ style.scss
├─ dist/
│  ├─ assets/
│  ├─ about.html
│  ├─ index.html

Basically, it should take the src as an input folder and output dist as a child of the my-app. When I try to do this it shows errors, then I change the scripts of the package.json into this

  "scripts": {
    "dev": "vite src",
    "build": "vite build src",
    "serve": "vite preview"
  },

This way the devcommand works fine. But the 'build' command makes the dist folder inside the src folder and does not generate other HTML files except index.html.

Now how can I fix this? Any suggestion?

2
  • If you want to know the reason of this behavior (dist folder inside src instead of the project root folder), you can read this anser: stackoverflow.com/a/69540835/774432 Commented Oct 14, 2021 at 12:33
  • 1
    the fact that vite works out of the box so well that when trying to make a static multipage site the first thing you need to configure is the outdir is amazing! imagine your webpack config before you got to this question lol Commented Jun 20, 2023 at 0:06

8 Answers 8

149

Create a vite.config.js file and define your project root and output directory as such:


module.exports = {
  root: 'src',
  build: {
    outDir: '../dist',
    emptyOutDir: true, // also necessary
  }
}

For more info, checkout config.

Sign up to request clarification or add additional context in comments.

3 Comments

You also need to set build.emptyOutDir to true.
See DrSiemer answer. The missing point here is that the vite.config.js file needs to be in the src folder, otherwise even with the configs set properly, it won't output the dist folder outside of the src folder.
the use of emptyOutDir: true is, this removes the outDir before building so that there is no leftover files from previous builds
26

For multipage apps you need to specify each entry point.

To dynamically specify all .html files in src/ directory as the entry points you can set up your vite.config.js like this:

import path from "path";
import glob from "glob";

export default {
  root: path.join(__dirname, "src"),
  build: {
    outDir: path.join(__dirname, "dist"),
    rollupOptions: {
      input: glob.sync(path.resolve(__dirname, "src", "*.html")),
    },
  },
};

Make sure to install glob like this

npm install glob -D

4 Comments

For other vite noobs like me, glob refers to an external npm package glob and you need to install it as a dev dependency first.
This is the only answer I was looking for since the release of Vite. I just wanted to use Vanilla HTML with Vite just for the live preview. But multiple HTML files makes it difficult to implement. This answer solved my year long mystery. Thanks man!
Do you know how to specify the chunk names? If each of your different html pages shares any code/components how can you get a duplicated chunk file for each html page or how can you preset what the chunk name should be? I'm trying to make each page of the multi page app independent, but I can't figure out the naming nomenclature. Thanks.
Because I have nested paths I needed to modify glob to the following: input: glob.sync(path.resolve(__dirname, "src", "**/*.html"))
18

Make sure you add vite.config.js inside your Vite root directory (src).

    module.exports = defineConfig({
      base: '',
      root: 'src',
      build: {
        outDir: '../dist'
      }
    });

Don't forget to update your package scripts. You'll need to add the --emptyOutDir flag if you want the same behavior as in the default project structure (clear output folder before building).

    "scripts": {
      "dev": "vite src",
      "build": "vite build src --emptyOutDir",
    }

2 Comments

It should be noted that 'emptyOutDir' is a build option as well and can be used instead of the cli flag. build: { outDir: '../dist', emptyOutDir: true }
The most important step is what you said: the vite.config.js file MUST be in the src folder. Otherwise, I tried everything and it won't work.
12

If you want to use defineConfig in your vite.config.ts you can use it like this:

    import { defineConfig } from 'vite'
    import reactRefresh from '@vitejs/plugin-react-refresh'
    import eslintPlugin from 'vite-plugin-eslint'
    
    // https://vitejs.dev/config/
    export default defineConfig({
        plugins: [reactRefresh(), eslintPlugin({ cache: false })],
        root: 'src',
        build: {
            outDir: '../dist'
        }
    })

Comments

7

You can set up your vite.config.js like this:

import path from 'path'

export default {
  root: path.resolve(__dirname, 'src'),
  build: {
    outDir: path.resolve(__dirname, 'dist'),
    rollupOptions: {
      input: {
        index: path.resolve(__dirname, 'src/index.html'),
        about: path.resolve(__dirname, 'src/about.html')
      }
    }
  }
}

Comments

2

Create a vite.config.js file and specify it's location in your package.json scripts using the --config flag:

  "scripts": {
    "dev": "vite --config ./config/vite.config.js",
    "build": "vite build --config ./config/vite.config.js
    "preview": "vite preview --config ./config/vite.config.js"
  },

Inside your vite config file include the following:

import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({
  root: 'src',
  build: {
    outDir: '../dist',
    emptyOutDir: true,
  },
});

1 Comment

Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?
1

I tested on Mac OS with Vite for React
If you want to change output dist -> build (for expample) when you run npm run build project, you should add in your vite.config.js build.outDir property.

export default defineConfig({
  plugins: [react()],
  build: {
    outDir: './build'
  }
})

Comments

0

another example, on my vite project

my-app/
├─ node_modules/
├─ dist/
│  ├─ registerSW.js
│  ├─ index.html
├─ index.html
├─ index.ts
├─ style.css
├─ vite.config.ts
├─ index.ts
├─ package.json

Depending on the structure project as above, the URL was https://domain_name.com/my-app/dist/. The default "index.html" file is located in "dist" folder. How to display it without subfolder in URL ? I mean how to convert from https://domain_name.com/my-app/dist/ to just https://domain_name.com/

My solution ^^ here we have slight changes in the configuration file. Pay attention, if you set emptyOutDir to true, that will remove all files on your server

export default defineConfig({
  base: "./",
  root:"../my-app",
  build: {
    emptyOutDir: **false**, //Pay attention !
    outDir: '../',
    rollupOptions: {
      output: {
        assetFileNames: "[name].[ext]",
        chunkFileNames: "[name].[ext]",
        entryFileNames: "[name].js",
      },
    },
  },

The structure project will be like this

    ├─ my-app/
    │  ├─ node_modules/
    │  ├─ index.html
    │  ├─ index.ts
    │  ├─ style.css
    │  ├─ vite.config.ts
    │  ├─ index.ts
    │  ├─ package.json
    ├─ registerSW.js
    ├─ index.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.