perf(前端): zod 移出首屏包,首屏 JS 721KB → 594KB(gzip 237 → 199KB)
首屏包里带着整个 zod 运行时(~100KB),来路有三条,缺一条都挪不出去(逐条撤回实测过): - 契约包没有 sideEffects: false,入口从桶里取任何一个值都会把所有 schema 模块带上。 契约包里没有顶层副作用(核过),加上之后 rolldown 才能按导出摇树 - roles.ts 里的 USER_TYPE / toAdminType 是入口要的,同文件却定义了两个 z.enum。 schema 挪到 admin.ts(唯一用处),roles.ts 文件头写明不许 import zod - 启动就要调的 getWebsiteConfig / getAILoginSummary 在 oj/api.ts 里,而那个文件同步 import 了题目详情、提交详情两个 schema。这两个函数挪到 shared/api.ts;那两道 闸门保持同步 —— submissionDetailSchema 有 .catch(),放行原文和解析结果不等价 - /me 的契约闸门改成 contractDeferred:先放行原文,schema 按需加载后在后台核、只记 日志。userProfileSchema 没有 default / transform,两者等价。动态 import 的目标是 单独的 shared/profileSchema.ts —— 直接 import 契约桶会让 rolldown 重排共享 chunk, 实测首屏反而涨到 1811KB 浏览器实跑核过:登录后 profile 正常加载、profileSchema 按需拉取、无控制台报错; 故意喂一份不符的数据,后台闸门照常打出 [契约] 分歧日志。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6b2da41882
commit
83b9d23c68
9 files changed
+60
-22
No files matched your search
@@ -5,8 +5,11 @@
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"exports": { ".": "./src/index.ts" },
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "^4.4.3"
|
||||
}
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { adminTypeSchema, problemPermissionSchema } from "./roles"
|
||||
import { ADMIN_TYPES, PROBLEM_PERMISSIONS } from "./roles"
|
||||
|
||||
import { achievementRaritySchema } from "./achievement"
|
||||
import { rankProfileSchema } from "./account"
|
||||
@@ -14,6 +14,10 @@ import {
|
||||
sqlDisplaySchema,
|
||||
} from "./problem"
|
||||
|
||||
// 放这里而不是 roles.ts:roles.ts 要保持不 import zod,理由见那边的文件头
|
||||
export const adminTypeSchema = z.enum(ADMIN_TYPES)
|
||||
export const problemPermissionSchema = z.enum(PROBLEM_PERMISSIONS)
|
||||
|
||||
/**
|
||||
* 后台侧的契约。与 oj 侧分开放:同一张表在两侧下发的字段集通常不同
|
||||
* (后台要 `visible` 这类管理字段,oj 侧连键都不该出现),
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { z } from "zod"
|
||||
|
||||
/**
|
||||
* 角色与题目权限的字面量。**全仓唯一的定义处。**
|
||||
*
|
||||
@@ -10,6 +8,9 @@ import { z } from "zod"
|
||||
* ADMIN_ROLES / TEACHER_ROLES,`["Regular User", "Student Admin"]` 这个学生口径
|
||||
* 在四个文件里各写一遍,另有二十多处散落的 `=== "Super Admin"`。拼错一个字母
|
||||
* TypeScript 一个字都不会说,只会在运行时静默放行或静默拒绝。
|
||||
*
|
||||
* **这个文件不能 import zod。** 前端入口要用这里的 USER_TYPE / toAdminType,
|
||||
* 一 import 就把整个 zod 运行时(~100KB)拖进首屏包。对应的 zod schema 在 admin.ts。
|
||||
*/
|
||||
export const ADMIN_TYPES = [
|
||||
"Regular User",
|
||||
@@ -18,11 +19,9 @@ export const ADMIN_TYPES = [
|
||||
"Super Admin",
|
||||
] as const
|
||||
export type AdminType = (typeof ADMIN_TYPES)[number]
|
||||
export const adminTypeSchema = z.enum(ADMIN_TYPES)
|
||||
|
||||
export const PROBLEM_PERMISSIONS = ["None", "Own", "All"] as const
|
||||
export type ProblemPermission = (typeof PROBLEM_PERMISSIONS)[number]
|
||||
export const problemPermissionSchema = z.enum(PROBLEM_PERMISSIONS)
|
||||
|
||||
/**
|
||||
* 三个分组一律是**白名单**,对齐旧后端 `account/models.py:65-73` 的显式列举写法。
|
||||
|
||||
Reference in new issue
Block a user