You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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包自动扫描所有页面:

  1. 安装依赖:npm i -D glob
  2. 修改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.htmlxxx.ts,配置会自动识别,完全不用手动修改。

为什么你的原配置失败?

你之前用TS作为Rollup入口,Vite默认不会主动输出对应的HTML文件(因为入口是脚本文件);而vite-plugin-html-template-mpa的页面路径映射逻辑没有和Rollup的输出规则对齐,导致要么HTML被扁平化,要么直接不输出。改用HTML作为入口后,Vite的核心逻辑会自动处理HTML的路径,再配合插件注入脚本,就完全贴合我们的需求了。

内容来源于stack exchange

火山引擎 最新活动