sroxck

sroxck

记录一下 vite-wide 项目搭建经验

搭建一个包含 admin 后台管理系统和 web 前端展示系统,各自独立使用 Vite 构建,仅共享公共组件和方法。项目支持在全局配置之外单独设置各自的 Vite 配置和插件,各项目会单独打包,Vite 会根据引入依赖与公共资源按需构建。

需求整理#

需求就是在一个项目中管理 admin 后台管理系统和 web 前端展示系统,他们各自独立,可以使用 shared 包中的内容,打包的时候各自打包,并且支持 tree sharking

Why Not?#

为什么不使用 pages 方案?#

  1. 构建臃肿pages 方案通常会将所有页面和组件以及依赖项都打包在一起,如 admin 和 web 最终都会打包成一个 bundle, 导致最终构建的文件体积较大,影响加载速度。

    这个项目通过 Tree Shaking 的方式,确保各自项目只引入实际使用的资源和依赖,优化了打包体积。

  2. 灵活性不足:使用 pages 方案时,项目结构与配置往往固定,只能使用统一的配置,难以灵活调整。

    这个项目支持独立的配置和插件管理,开发者可以根据需求自由调整项目结构和构建配置。每个模块都是一个单独的 Vite 项目

  3. 运维复杂性pages 方案需要额外的运维配合

    这个项目仅仅是单独根据变更文件的目录触发部署而已

为什么不使用 Monorepo 方案?#

  1. 项目复杂性:Monorepo 方案适合大型项目,但对于小型或中型项目来说,管理多个包的复杂性可能会导致开发效率下降。

    这个项目提供了独立的模块管理,避免了不必要的复杂性。

  2. 构建时间:在 Monorepo 中,可能需要每次都构建整个仓库,即使只修改了一个模块。这会导致构建时间增加。

    这个项目支持按需构建,能够快速响应开发需求。

  3. 依赖管理:Monorepo 方案需要精细管理各个模块之间的依赖关系,可能会增加维护成本。

    这个项目通过共享目录和独立配置,简化了依赖管理。

项目搭建#

项目目录如下
dir

tsconfig 如下

// [tsconfig.json]
{
  "files": [],
  "compilerOptions": {
    "module": "NodeNext"
  },
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ]
}

// [tsconfig.node.json]
{
  "extends": "@tsconfig/node20/tsconfig.json",
  "include": [
    "vite.config.*",
    "vitest.config.*",
    "cypress.config.*",
    "nightwatch.conf.*",
    "playwright.config.*"
  ],
  "compilerOptions": {
    "composite": true,
    "noEmit": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",

    "module": "ESNext",
    "moduleResolution": "Bundler",
    "types": ["node"]
  }
}


// [tsconfig.app.json]
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": [
    "env.d.ts",
    "packages/**/*",
    "packages/**/*.vue",
    "packages/**/*.tsx",
    "./config.global.ts"
  ],
  "exclude": ["packages/**/__tests__/*"],
  "compilerOptions": {
    "allowImportingTsExtensions": true,
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "baseUrl": ".",
    "paths": {
      "@shared/*": ["./packages/shared/*"]
    }
  }
}

config 如下

// [config.global.ts]
import path from "path";
import { plugins } from "./plugins";
export const sharedConfig = {
  commonPlugins: [...plugins],
  resolve: {
    alias: {
      "@shared": path.resolve(__dirname, "./packages/shared"),
    },
  },
};
// [plugins/index.ts]
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import vue from "@vitejs/plugin-vue";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import { PluginOption } from "vite";
import vueJsx from "@vitejs/plugin-vue-jsx";
export const plugins: PluginOption[] = [
  vue(),
  vueJsx(),
  AutoImport({
    resolvers: [ElementPlusResolver()],
  }),
  Components({
    resolvers: [ElementPlusResolver()],
  }),
];
// [web/vite.config.ts]
import { defineConfig } from "vite";
import path from "path";
import { sharedConfig } from "../../config.global.ts";
const { commonPlugins, ...commonConfig } = sharedConfig;
export default defineConfig({
  plugins: [...commonPlugins],
  root: path.resolve(__dirname),
  ...commonConfig,
});
// [admin/vite.config.ts]
import { defineConfig } from "vite";
import path from "path";
import { sharedConfig } from "../../config.global.ts";
const { commonPlugins, ...commonConfig } = sharedConfig;
export default defineConfig({
  plugins: [...commonPlugins],
  root: path.resolve(__dirname),
  ...commonConfig,
});

类型支持#

统一配置,多模块使用,项目提供完整且结构清晰的类型支持,包括 tsx,vine,macros 的类型支持,任意模块中的 sfc 组件,纯函数组件以及 tsx 组件都会得到完全的类型支持,包含自动的 props 和 emits 的类型强校验以及 ref 实例类型支持。

问题汇总#

  1. 配置问题
    解决方案是 各自拥有各自的 vite 配置,然后根目录配置统一的 vite 配置,各自可以设置各自独立的配置

  2. ts 类型问题
    解决方案是 使用统一的 tsconfig, 将各自的 tsconfig 删除,使用 create-vue 的 tsconfig (直接拿过来,依赖按照 craete-vue 的 package 安装)

  3. tsx 支持
    在 create vue 中使用 tsx 默认就支持了 需要注意的是 在 tsconfig 中的 include 将 admin 和 web 都包裹,不过最佳解决方案是 创建一个 packages 目录 将 admin 和 web 和 shared 都放到 packages 目录下,include 字段只包含这个目录就可以了,不过要把统一的 vite 配置文件包裹

  4. 公共组件类型问题
    在 tsconfig 中配置 paths 字段 在 compilerOptions 中配置 paths 如下

 "paths": {
      "@shared/*": ["./packages/shared/*"]
  }

目录结构#

packages 目录#

packages 为项目模块目录,包含以下内容:

  • admin:后台管理系统,使用 Vite 构建

  • web:前端展示系统,使用 Vite 构建

  • shared:公共目录,存放共享的组件、方法,供 adminweb 系统使用

plugins 目录#

plugins 为集中管理 Vite 插件的目录。自定义插件与第三方插件通过统一的入口文件 index.ts 导出 plugins 对象,方便统一管理和使用。

自定义插件规范

  1. 插件命名:使用小写字母,单词间用短横线分隔(例如:my-custom-plugin)。
  2. 插件结构:每个插件应包含 install 方法,用于在 Vite 中注册插件。
  3. 文档说明:每个插件应附带使用示例和配置说明,以便其他开发者理解和使用。

scripts 目录#

scripts 目录包含项目构建脚本和其他任务脚本,主要用于自动化构建、测试和部署等任务。具体脚本可以根据需要添加。

types 目录#

types 目录用于存放 TypeScript 类型声明文件 .d.ts。可以在此目录中添加全局类型模块声明,以供整个项目使用。

config 目录#

config 目录存放项目的全局配置文件,包含 Vite 配置、环境变量和其他相关设置。可根据不同的环境(开发、测试、生产)进行相应的配置。

此文由 Mix Space 同步更新至 xLog
原始链接为 http://www.sroxck.top/posts/note/wide


加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。