项目:html5-examples | 版本:v1.1 | 生成日期:2026-10-06 | 依据:源码分析
《06-部署运行》回答"怎么跑起来",本篇回答"每个配置项为什么是这个值、改它会牵动什么"。全篇分五节:前端构建配置逐段解读(vite.config.ts 与 vitest.config.ts、tsconfig、eslint 的关键段落)、后端配置(NestJS 三处配置载体)、环境变量全清单(前端 + 后端逐项)、脚本全量(两个 package.json 的每条 script)、姊妹项目构建差异对照。阅读原则与全文档集一致:本项目配置注释密度极高,vite.config.ts 的每条非常规配置背后都是一次真实事故——改配置前先读注释,是比读本篇更优先的动作;本篇把这些注释系统化,并补充它们与行为面的因果。
vue() + vueJsx()(JSX 支持供个别演示组件)+ tailwindcss()(Tailwind v4 的 Vite 插件形态——v4 无 tailwind.config.js,主题在 src/assets/main.css 的 @theme 中定义,配置入口在 CSS 而非 JS)。@ → src,与 tsconfig paths、vitest 别名三处一致(改别名要三处同改)。gsap/MotionPathPlugin 等子路径打成独立 chunk、各自携带一份 gsap core,导致插件 init 串入普通 tween 抛 "Indexed property setter on CSSStyleDeclaration"。配套约束是 optimizeDeps.include 必须列全 gsap 插件入口(缺任一子路径都会触发同类污染)——改 gsap 相关配置时这两处是一个原子操作。port: 5555(与后端 CORS 白名单、package.json dev script 的 --port 5555 双重固定)、host: '127.0.0.1'(仅本机访问;需要局域网联调时改 host 并同步后端 CORS_ORIGIN)、proxy['/api'] → http://localhost:3000(开发期唯一跨域消除手段;生产环境该职责转移给网关反代或 VITE_API_BASE_URL)。
| 配置 | 值 | 因果说明 |
|---|---|---|
target | 'esnext' | 不做语法降级——产物体积与构建速度优先,代价是浏览器范围受限(《06-部署运行》§1 的红线) |
minify | 'esbuild' | 速度优先选型(非 terser),与 esbuild 块的 legalComments: 'none'(剥离许可证注释)配套 |
cssCodeSplit | true | CSS 随 chunk 拆分,配合按需路由才完整 |
chunkSizeWarningLimit | 600 | 警告阈值收紧,提示新依赖是否该进 manualChunks |
reportCompressedSize | false | 跳过每 chunk gzip 计算,纯构建提速 |
hoistTransitiveImports: false:禁止 Rollup 把跨 chunk 的传递依赖提升——提升会制造 chunk 间循环初始化(TDZ 错误)。此开关是"小 chunk 策略"能安全成立的前提。chunkFileNames:名字含 vendor/runtime 的进 assets/vendor-<name>-[hash].js,其余 assets/<name>-[hash].js——为 CDN 缓存策略分组命名。experimentalMinChunkSize:注释明示"本地化后动态导入组件达 1182 个(chunk 5000+),该合并算法接近 O(n²),会使打包阶段耗时 1 小时以上"。这条注释是全文件最重要的禁令,任何"优化构建"的冲动先读它(《10-性能设计》§3.1)。manualChunks(id) 19 组规则(按判断顺序,命中即归组):plugin-vue:export-helper → index(强制进入口,防跨 chunk 循环依赖);sfcRuntime/sfc- 前缀 → sfc-runtime;node_modules 之外返回 undefined(业务代码随路由自然拆);@vue/compiler-sfc + esbuild → sfc-compiler;@antv → antv-vendor;d3/chart.js → chart-misc-vendor、apexcharts → apex-vendor、echarts-gl/echarts-stat/echarts → 三级 echarts vendor;vue/vue-router/pinia/@vue → vendor(首屏核心);@vueuse → vueuse-vendor;three → three-vendor、gsap → gsap-vendor、cannon → physics-vendor、animejs → animation-vendor;fabric/pixi/konva/leafer 各自 vendor;roughjs → roughjs-vendor、signature_pad + p5 → canvas-misc-vendor;@guolao/vue-codemirror/@codemirror → editor-vendor;monaco-editor → monaco-vendor。设计哲学一句话:每个示例只下载自己的库。exclude: ['xiaoye-ui'](自有组件库保持源码形态走 Vite 管线,避免预构建版本漂移);include 列出 24 项——dayjs 全家桶插件、Monaco 封装、three 及四个 examples/jsm 入口、gsap 与全部插件入口(见 1.1)、@vue/compiler-sfc、echarts、animejs、fabric、pixi.js、leafer-ui 及插件、shiki 三入口、roughjs、signature_pad、p5、konva。include 的作用是预构建稳定与单实例强制——新增重型依赖时问两个问题:要不要进 manualChunks?要不要进 include?
vitest.config.ts:独立于 vite.config(不继承其插件与 manualChunks),仅 vue 插件 + 别名 + test 段(happy-dom/globals/include 模式/coverage v8 限定 utils+composables)。tsconfig.json:target ES2020、strict + noUnusedLocals + noUnusedParameters + noFallthroughCasesInSwitch、moduleResolution bundler、allowImportingTsExtensions、resolveJsonModule(JSON 示例导入的类型前提)、paths 含一个历史遗留的 @ioftv/*(指向已拆分的大屏目录,《13-技术债务》§8 同源残留)。eslint.config.js 关键段落见《09-测试与质量保障》§2.2。
后端配置分散在三处,职责不同:
server/src/main.ts(启动安检):全局 ValidationPipe 三开关;CORS(CORS_ORIGIN 逗号分隔 + credentials);JWT_SECRET 弱值四项字典(your-jwt-secret-key-change-in-production/default-secret/changeme/secret)+ < 开头模板占位符检测——生产抛错拒启、开发告警;生产缺 DB_PASSWORD 拒启;createDefaultAdmin()(默认密码 ADMIN_DEFAULT_PASSWORD,未设置时兜底 admin123 并告警)。server/src/app.module.ts(运行时装配):ConfigModule.forRoot({ isGlobal: true, envFilePath: '.env' })(注意相对路径——必须在 server/ 目录下启动);TypeOrmModule.forRoot 五个 DB_* 变量 + synchronize: DB_SYNC === 'true' + logging: NODE_ENV === 'development';27 实体登记;ServeStatic 托管 server/admin/ 到 /admin(exclude /api/(.*));APP_GUARD 全局 JwtAuthGuard。server/data-source.ts(迁移连接):独立 DataSource,migrations 指向 src/migrations/*.ts、synchronize: false(迁移通道永不自动同步);读同一组 DB_* 变量但密码兜底 'postgres'(与 app.module 的无兜底不同——迁移环境更宽容)。JWT 时效语义要特别澄清(这是最易误配的一项):.env.example 中 JWT_EXPIRES_IN=7d 是历史遗留键(passport-jwt 层 sign 默认,auth.service 的显式签发并不使用它);真正生效的是 JWT_ACCESS_EXPIRES_IN(access token 秒数,未配置时代码兜底 604800 = 7 天而非 2 小时——若期望 2 小时必须显式设置 7200)与 JWT_REFRESH_EXPIRES_IN(refresh 秒数,兜底同为 604800)。前端 REFRESH_AHEAD_SECONDS = 300 的提前刷新量与 access TTL 无耦合,改 TTL 不需要改前端。
| 变量 | 声明/读取处 | 缺省行为 |
|---|---|---|
VITE_API_BASE_URL | client.ts defaultConfig | 未设置回退 /api(依赖同源反代) |
VITE_LOG_LEVEL | logger.ts | 未设置按 MODE:开发 debug、生产 error |
VITE_APP_TITLE | env.d.ts ImportMetaEnv 声明 | ⚠️ 待确认 全量 grep 未见读取处,疑似预留声明 |
注意 env.d.ts 只声明了 VITE_APP_TITLE——其余两个变量的类型声明缺失(TS 层靠 import.meta.env 的宽松索引兜底),补声明属于低成本改进。
| 变量 | 用途 | 校验/兜底行为 |
|---|---|---|
DB_HOST / DB_PORT / DB_USERNAME / DB_PASSWORD / DB_NAME | PostgreSQL 连接 | 兜底 localhost/5432/postgres/—/html5_examples;生产缺密码拒启 |
DB_SYNC | TypeORM synchronize | 仅 'true' 时开启(危险开关,生产禁用) |
JWT_SECRET | JWT 签名密钥 | 弱值/占位符检测(main.ts);未设置时 JwtStrategy 构造即抛错 |
JWT_ACCESS_EXPIRES_IN / JWT_REFRESH_EXPIRES_IN | 令牌秒数 | 兜底均 604800(见 §2 的语义澄清) |
JWT_EXPIRES_IN | 历史遗留 | 实际签发不使用 |
ADMIN_DEFAULT_PASSWORD | 默认管理员密码 | 未设置兜底 admin123 + 告警 |
PORT | 服务端口 | 兜底 3000 |
NODE_ENV | 环境 | production 激活安检硬失败与 cookie Secure;development 开 SQL 日志 |
CORS_ORIGIN | 逗号分隔白名单 | 兜底 http://localhost:5555,http://localhost:5560 |
OSS_REGION / OSS_BUCKET / OSS_ACCESS_KEY_ID / OSS_ACCESS_KEY_SECRET / OSS_ROLE_ARN | 阿里云 OSS(knowledge 网盘) | 不配置优雅降级(功能不可用、启动正常);OSS_ROLE_ARN 为 STS 分片直传用 |
RUN_ADMIN_TOKEN | run 模块守卫共享秘密 | 未配置即禁用整个 run 通道(fail-closed,非 .env.example 模板项——需手工追加) |
| script | 实际命令 | 说明 |
|---|---|---|
dev | vite --port 5555 | 端口与 vite.config 双重固定 |
build | vue-tsc --noEmit && NODE_OPTIONS='--max-old-space-size=8192' vite build | 类型检查 + 8GB 堆构建(CI 不直接用它,CI 分步跑) |
build:fast | vite build | 跳过类型检查的迭代通道 |
preview | vite preview | 本地预览 dist/ |
extract | tsx scripts/extract-examples.ts | Markdown → CodeExample JSON 的内容生产入口 |
lint / lint:fix | eslint .(+ --fix) | flat config,CI 门禁 |
format | prettier --write "src/**/*.{ts,vue,js,css,json}" | 无分号/单引号/行宽 100/LF |
typecheck | vue-tsc --noEmit | CI 门禁 |
test / test:watch / test:coverage | vitest run / watch / --coverage | CI 门禁与覆盖率 |
提交钩子:lint-staged 配置内嵌 package.json(*.{ts,vue,js} → eslint --fix + prettier;*.{css,json,md} → prettier)。
| script | 实际命令 | 说明 |
|---|---|---|
dev | nest start --watch | watch 模式 |
build / start | nest build / node dist/main | 生产形态 B 的两步 |
lint | eslint "{src,apps,libs,test}/**/*.ts" --fix | ⚠️ 自带 --fix,无纯 check 形态(《13-技术债务》§9) |
typeorm | TS_NODE_PROJECT=./tsconfig.json ts-node -r reflect-metadata node_modules/typeorm/cli.js -d data-source.ts | 三个迁移命令的公共底座 |
migration:generate / migration:run / migration:revert | typeorm 三子命令 | 结构变更三件套 |
import-data | tsx scripts/import-data.ts | 历史数据导入入口 |
| (无 test) | — | 结构性缺口(《09-测试与质量保障》§3 第 1 条) |
另注:后端依赖里有 mysql2(run 模块的 MySQL 查询通道)与 nanoid/dotenv;前端 devDependencies 里的 pg、@types/d3-geo、@types/uuid 等属于历史脚本的遗留依赖(前端运行时并不直连 PG)。
三个姊妹项目(同为 Vue 3 + Vite + pnpm,2026 年从本项目拆出)的构建配置差异如下(实测各自 package.json):
| 维度 | html5-examples(本项目) | html5-dataviz | html5-games | devtools |
|---|---|---|---|---|
| dev 端口 | 5555 | 5566 | 5556 | 5560 |
| build | vue-tsc --noEmit + 8GB 堆 vite build | 8GB 堆 vite build(无类型检查前置) | 裸 vite build | 裸 vite build(typecheck 独立 script,CI 分步) |
| 测试 | vitest run + coverage(底座口径) | ⚠️ 待确认(scripts 未见 test) | vitest run | ⚠️ 待确认 |
| 拆包规模 | 19 组 manualChunks + 大型 optimizeDeps | 图表库向拆包 | 游戏引擎向拆包 | 工具库向拆包(含代码运行器依赖) |
| 部署耦合 | 可纯静态 + 可选 NestJS 后端 | 纯静态 | 纯静态 | 纯静态(但经后端 run 通道与 CORS 5560 关联) |
三点差异背后的含义:其一,端口的分配(5555/5556/5560/5566)是刻意错开的——后端 CORS 白名单默认含 5555 与 5560 两项,正对应本项目与 devtools 两个会调后端的前端,这印证了"devtools 是后端接口的姊妹消费方"的设计意图(run 模块注释即为此而写,尽管现源码未见调用,《13-技术债务》第 2 条)。其二,构建命令的差异反映各项目对"类型安全 vs 构建速度"的不同取舍:本项目因 1182 个动态组件 + 约 8.3MB JSON 的规模必须 8GB 堆,且把 vue-tsc 放进 build 兜底;dataviz 的 8GB 堆同样源于图表库体量但省了类型检查步;games/devtools 体量小走裸构建。其三,四项目共享"esnext target、pnpm、prettier 同参数、flat eslint"的底座约定,这是同代拆分的痕迹——迁移某项构建改进(如缓存头策略)时可以四项目平移,迁移某项事故教训(如 gsap dedupe)时先确认对方是否同样依赖 gsap。
收尾给一张"改 X 动 Y"速查表,覆盖本篇涉及的高频变更:改 dev 端口 → vite.config + package.json dev script + 后端 CORS_ORIGIN;改后端端口 → PORT + vite proxy target + CORS_ORIGIN;新增重依赖 → manualChunks 归组 + optimizeDeps(gsap 类还需 dedupe + 插件入口全列)+(可选)chunkSizeWarningLimit 复评;改 access token TTL → 后端两个 JWT_* 键(注意 604800 兜底语义),前端无需动;改 /api 前缀或跨域部署 → VITE_API_BASE_URL(构建期注入,改后重构建)+ 网关反代 + CORS_ORIGIN;改 alias → vite.config + tsconfig paths + vitest.config 三处同改。凡是速查表覆盖不到的配置变更,回到 §1.4 的三条事故注释(hoistTransitiveImports / gsap dedupe / experimentalMinChunkSize 禁令)做一次对照检查——它们是这份配置文件里所有"看起来可以简化"的地方的答案。
本篇完。下一篇:15-接口全量参考.md