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
@@ -45,3 +45,24 @@ export function contract<T extends z.ZodType>(
|
||||
// 「能渲染的东西」而不是一个异常,分歧已经通过上面那条日志暴露出来了。
|
||||
return value as z.infer<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* 同 `contract`,但校验挪到后台:先原样交出数据,schema 按需加载之后再核、只记日志。
|
||||
*
|
||||
* 给**首屏路径**用(启动就要拉的 /me)。同步校验得在入口包里带上 schema,也就带上
|
||||
* 整个 zod 运行时(~100KB);而这道闸本来就只记日志、不改数据 —— schema 里没有
|
||||
* default / transform 时,放行原文和放行解析结果只差 zod 剥掉的多余字段,前端用不上。
|
||||
* 给 schema 加 default / transform 之前,得先把调用方从这里挪回 `contract`。
|
||||
*/
|
||||
export function contractDeferred<T extends z.ZodType>(
|
||||
endpoint: string,
|
||||
loadSchema: () => Promise<T>,
|
||||
value: unknown,
|
||||
): z.infer<T> {
|
||||
loadSchema()
|
||||
.then((schema) => contract(endpoint, schema, value))
|
||||
.catch(() => {
|
||||
// schema 那个 chunk 加载失败(部署换了哈希之类)不影响页面,闸门本来就只记日志
|
||||
})
|
||||
return value as z.infer<T>
|
||||
}
|
||||
Reference in new issue
Block a user