Background
I'm migrating a complex multi-page application from Webpack to Vite. Each HTML file has a corresponding .ts script, and the files live in nested directories.
Note: These entry HTML and TS files do not refer to each other (Webpack automate this injection)
src/
index.html
index.ts
user/login/index.html
user/login/index.ts
admin/dashboard.html
admin/dashboard.ts
Goal:
release/
index.html
user/login/index.html
admin/dashboard.html
scripts/
index.js
user/login/index.js
admin/dashboard.js
What I've tried:
I used vite-plugin-html and vite-plugin-html-template-mpa with a list of page definitions. I also defined the input entries using .ts files.
However:
This is my vite.config.js
import { defineConfig } from "vite";
import path from "path";
import htmlTemplateMpa from "vite-plugin-html-template-mpa";
const pages = [
"index",
"user/login/index",
"admin/dashboard"
];
export default defineConfig(() => {
const entries = pages.reduce((acc, page) => {
acc[page] = path.resolve(__dirname, `src/${page}.ts`);
return acc;
}, {});
return {
build: {
outDir: "release",
rollupOptions: {
input: entries,
output: {
entryFileNames: "scripts/[name].js",
chunkFileNames: "scripts/chunks/[name].js",
assetFileNames: "assets/[name].[ext]"
}
}
},
plugins: [
htmlTemplateMpa({
pages: pages.map((page) => ({
template: `src/${page}.html`,
entry: `${page}.ts`,
filename: `${page}.html`
})),
minify: true
})
]
};
});
Problem
How can I configure Vite to:
Solution:
Manually add a <script type="module" src="...">
tag to each entry .html
file pointing to its corresponding .ts
(built as .js
):
<!-- src/user/login/index.html -->
<script type="module" src="/scripts/user/login/index.js"></script>
Set rollupOptions.input
in vite.config.js
to your .html
files:
const entries = pages.reduce((acc, page) => {
acc[page] = path.resolve(__dirname, `src/${page}.html`);
return acc;
}, {});
Remove createHtmlPlugin
or any similar HTML template plugins entirely.
Final vite.config.js
Output:
import { defineConfig } from "vite";
import path from "path";
const pages = [
"index",
"user/login/index",
"admin/dashboard"
];
export default defineConfig(() => {
const entries = pages.reduce((acc, page) => {
acc[page] = path.resolve(__dirname, `src/${page}.html`);
return acc;
}, {});
return {
build: {
outDir: "release",
rollupOptions: {
input: entries,
output: {
entryFileNames: "scripts/[name].js",
chunkFileNames: "scripts/chunks/[name].js",
assetFileNames: "assets/[name].[ext]"
}
}
}
};
});