Vite - 配置多页面应用

发布时间 2023-09-06 11:12:48作者: Himmelbleu

多页面需求

所谓多页面是一个项目下面有多个子项目,其每一个项目都有自己的 index.html 和 main.ts。下图是多页面应用目录结构的一个例子:

多页面应用目录结构

输入 http://localhost:5173 进入的是根目录下的 index.html,而非 apps/subapp-admin 下面的 index.html。

通常在开发客户端和管理端两个项目的时候会弄多页面项目,两个项目可能会共用一些组件、函数、TS 全局类型等,比如上图中的 common 文件夹。

配置主页面

主页面的 index.html 就在根目录下,main.ts 在 apps/mainapp 里。

tip:[start]

只要保证 index.html 在根目录下面,那么这个页面就是主页面。

tip:[end]

主页面的入口函数路径写相对路径,相对于本项目根目录下的 apps/mainapp 下的 main.ts:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="/favicon.ico" />
    <title>Buchstadt</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="apps/mainapp/main.ts"></script>
  </body>
</html>

配置子页面

子页面目录结构

子页面目录下面必须包含 index.html 和 main.ts。子页面的入口函数路径写相对路径,相对于本子页面下的 main.ts:

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="/favicon.ico" />
    <title>Buchstadt - 管理端</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./main.ts"></script>
  </body>
</html>

配置 vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import Icons from "unplugin-icons/vite";
import IconsResolver from "unplugin-icons/resolver";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import UnoCSS from "unocss/vite";
import { resolve } from "path";

export default defineConfig(({ command, mode }) => {
  return {
    build: {
      target: "modules",
      outDir: "dist/",
      assetsDir: "static",
      sourcemap: true,
      rollupOptions: {
        input: {
          mainApp: resolve(__dirname, "index.html"),
          subappAdmin: resolve(__dirname, "apps/subapp-admin/index.html")
        },
        output: {
          entryFileNames: "static/js/[name]-[hash].js",
          chunkFileNames: "static/js/[name]-[hash].js",
          assetFileNames: "static/[ext]/name-[hash].[ext]"
        }
      }
    },
    plugins: [
      vue(),
      UnoCSS(),
      AutoImport({
        include: [
          /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
          /\.vue$/,
          /\.vue\?vue/ // .vue
        ],
        imports: [
          "vue",
          "pinia",
          "vue-router",
          "@vueuse/core",
          {
            // 自动导入函数:不能使用相对路径,必须使用路径别名 @common
            "@common/apis/use-axios": ["axiosInstance"]
          }
        ],
        resolvers: [
          ElementPlusResolver(),
          IconsResolver({
            prefix: "Icon"
          })
        ],
        vueTemplate: true,
        dts: "./auto-imports.d.ts"
      }),
      Components({
        resolvers: [
          ElementPlusResolver(),
          IconsResolver({
            enabledCollections: ["ep"]
          })
        ],
        dirs: [
          // 自动导入组件:不能使用路径别名
          "common/components/**",
          "common/fragments/**",
          `apps/mainapp/views/**`,
          `apps/mainapp/components/**`,
          `apps/mainapp/fragments/**`,
          `apps/subapp-admin/views/**`,
          `apps/subapp-admin/components/**`,
          `apps/subapp-admin/fragments/**`
        ]
      }),
      Icons({
        autoInstall: true
      })
    ],
    resolve: {
      alias: {
        // 配置路径别名
        "@common": resolve(__dirname, "common"),
        "@mainapp": resolve(__dirname, "apps/mainapp"),
        "@subapp-admin": resolve(__dirname, "apps/subapp-admin")
      }
    }
  };
});
  1. 配置路径别名
  2. 在自动导入函数中,如果要导入我们自己写的 .ts 文件里的东西,不能使用相对路径,必须使用路径别名指向。
  3. 在自动导入组件中,和上面第二点不一样,这里必须使用相对路径。

配置 tsconfig.json

在 vite 里面配置了路径别名还不行,ts 不能被识别,导入模块之后会报错。还需要在 tsconfig.json 中进行配置:

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "jsx": "preserve",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "skipLibCheck": true,
    "noEmit": true,
    "strictNullChecks": false,
    "baseUrl": ".",
    "paths": { "@mainapp/*": ["apps/mainapp/*"], "@subapp-admin/*": ["apps/subapp-admin/*"], "@common/*": ["common/*"] }
  },
  "include": [
    "apps/mainapp/**/*.ts",
    "apps/mainapp/**/*.vue",
    "apps/mainapp/**/*.tsx",
    "apps/mainapp/**/*.d.ts",
    "apps/subapp-admin/**/*.ts",
    "apps/subapp-admin/**/*.vue",
    "apps/subapp-admin/**/*.tsx",
    "apps/subapp-admin/**/*.d.ts",
    "common/**/*.ts",
    "common/**/*.vue",
    "common/**/*.tsx",
    "common/**/*.d.ts",
    "uno.config.ts",
    "vite-env.d.ts",
    "./auto-imports.d.ts",
    "./components.d.ts"
  ],
  "references": [{ "path": "./tsconfig.node.json" }]
}
  1. paths 和 include 两个键中配置路径。
  2. paths 就是我们在 vite 中配置的路径别名,让 ts 能够识别我们的模块路径。
  3. include 意思是哪些路径的文件可以被识别,如果不配置这个也会报错。