如何在Vite中配置多HTML入口、自动注入对应TypeScript脚本并保留嵌套输出目录?
如何在Vite中配置多HTML入口、自动注入对应TypeScript脚本并保留嵌套输出目录?
我之前从Webpack转Vite做多页面应用时,也踩过几乎一模一样的坑——Webpack的自动注入和目录处理太省心,换到Vite得完全调整思路。针对你的需求,我们可以通过以HTML为Rollup入口+自动注入TS脚本的方式完美解决,同时1:1保留原有的嵌套目录结构。
1. 核心调整思路
首先放弃vite-plugin-html-template-mpa(它的目录处理逻辑和我们的需求匹配度不高),改用更通用的vite-plugin-html(先安装依赖:npm i -D vite-plugin-html)。核心逻辑是:
- 把HTML文件作为Rollup的构建入口:这是保留HTML嵌套目录的关键,Vite会自动按原路径输出HTML,不会扁平化
- 用
vite-plugin-html给每个HTML自动注入对应的TS脚本,替代Webpack的自动注入功能
2. 完整可运行的vite.config.js配置
import { defineConfig } from "vite"; import path from "path"; import { createHtmlPlugin } from "vite-plugin-html"; // 手动定义所有页面路径(和你原有的pages数组一致) const pages = [ "index", "user/login/index", "admin/dashboard" ]; export default defineConfig(() => { // 1. 构建Rollup的Input对象:key是页面路径(用于保留输出目录结构),value是HTML文件的绝对路径 const rollupInput = pages.reduce((acc, pagePath) => { acc[pagePath] = path.resolve(__dirname, `src/${pagePath}.html`); return acc; }, {}); // 2. 配置vite-plugin-html:给每个HTML自动注入对应的TS脚本 const htmlInjectConfig = { pages: pages.map(pagePath => ({ filename: `${pagePath}.html`, // 强制按原路径输出HTML injectOptions: { // 注入当前页面对应的TS入口脚本,Vite会自动处理打包 entries: [path.resolve(__dirname, `src/${pagePath}.ts`)] } })) }; return { build: { outDir: "release", rollupOptions: { input: rollupInput, output: { // 把JS输出到scripts目录,保留页面的嵌套路径 entryFileNames: "scripts/[name].js", chunkFileNames: "scripts/chunks/[name].js", assetFileNames: "assets/[name].[ext]" } } }, plugins: [ createHtmlPlugin(htmlInjectConfig) ] }; });
3. 关键配置细节说明
- 用HTML作为Rollup入口:
当你把src/admin/dashboard.html绑定到input的admin/dashboard键时,Vite会自动在release/admin/dashboard.html位置输出该文件,完全继承原目录结构,不会出现扁平化问题。 - 自动注入TS脚本:
vite-plugin-html会在每个HTML的<head>或<body>末尾自动插入对应的TS脚本标签,Vite会把这个TS作为入口打包,最终输出到scripts/[页面路径].js(比如scripts/admin/dashboard.js)。 - Output路径的嵌套保留:
entryFileNames: "scripts/[name].js"中的[name]会直接复用Rollup Input的键值(也就是我们的页面路径),所以TS打包后的JS文件也会保留嵌套结构。
4. 最终输出效果
执行vite build后,你会得到完全符合需求的目录结构:
release/ ├── index.html ├── user/ │ └── login/ │ └── index.html ├── admin/ │ └── dashboard.html ├── scripts/ │ ├── index.js │ ├── user/ │ │ └── login/ │ │ └── index.js │ ├── admin/ │ │ └── dashboard.js │ └── chunks/ │ └── ...(公共依赖chunk) └── assets/ └── ...(图片、样式等静态资源)
5. 可选优化:自动扫描页面(无需手动维护pages数组)
如果页面数量多,手动维护pages数组太麻烦,可以用glob包自动扫描所有页面:
- 安装依赖:
npm i -D glob - 修改vite.config.js的pages生成逻辑:
import glob from "glob"; // 自动扫描src下所有HTML文件,生成pages数组 const pages = glob.sync("src/**/*.html").map(filePath => { // 去掉前缀`src/`和后缀`.html`,得到干净的页面路径 return filePath.replace(/^src\/|\.html$/g, ""); });
以后新增页面时,只要在src下创建xxx.html和xxx.ts,配置会自动识别,完全不用手动修改。
为什么你的原配置失败?
你之前用TS作为Rollup入口,Vite默认不会主动输出对应的HTML文件(因为入口是脚本文件);而vite-plugin-html-template-mpa的页面路径映射逻辑没有和Rollup的输出规则对齐,导致要么HTML被扁平化,要么直接不输出。改用HTML作为入口后,Vite的核心逻辑会自动处理HTML的路径,再配合插件注入脚本,就完全贴合我们的需求了。
内容来源于stack exchange




