基准测试与性能
本基准测试参考了 paraglide-js benchmark 的测试架构,模拟现代多语言 Web 应用在首屏预渲染并完成客户端水合(Hydration)时,用户端实际承载的全部国际化资源(HTML + 运行时代码 + 语言包)的真实网络传输体积。
场景说明:在纯静态页面(Zero-JS MPA)中,服务端直接输出翻译好的 HTML,客户端无需加载任何 i18n 代码;本测试针对的是具备客户端水合、动态交互(如表单校验、即时文案提示)与客户端路由能力的现代全栈应用,测量首屏达到可交互状态所下载的静态资源总开销。
对比方案包含:
ts-intl(轻量运行时):测试default(全语言全量打包)与locale-splitting(语言分块按需加载)两种配置。paraglide(编译型方案):测试default(编译函数全语言打包)与experimental-middleware-locale-splitting(路由中间件按需拆包)两种配置。i18next(传统运行时):测试default(全语言 JSON 打包)与http-backend(客户端异步 fetch)两种配置。
数据对比图表
以下数据通过 Playwright 无头 Chromium 访问页面,统计网络空闲(networkidle)前所有成功的 HTTP 静态响应体积总和(Transfer Size):
首屏网络传输体积 (KB)
Playwright Headless Chromium · Real HTTP Transfer Size
paraglide中间件拆包
-91%36.3 KB
ts-intl按需拆包
-86%57.8 KB
paraglide默认全量
-82%76.6 KB
i18nextHTTP 动态加载
-55%188.7 KB
ts-intl默认全量
-14%360.0 KB
i18next默认全量
Baseline420.4 KB
测试数据矩阵
测试基准配置:首屏渲染 100 条文本(20% 包含动态变量插值)。
场景一:多语言规模(10 语言 · 命名空间共 500 词条)
在该场景中,字典总共包含 500 条词条,页面实际引用并渲染其中 100 条:
| 库与打包模式 | 首屏传输体积 | 对比 i18next 默认 | 机制特点 |
|---|---|---|---|
| paraglide (中间件拆包) | 36.3 KB | -91.4% | 编译为独立 JS 函数,Tree-shaking 剔除未引用词条,按需分发 |
| ts-intl (按需拆包) | 57.8 KB | -86.2% | 核心运行时约 2 KB,仅加载当前语言 500 条词条 JSON |
| paraglide (默认全量) | 76.6 KB | -81.8% | Tree-shaking 剔除未引用词条,但合并打包 10 种语言编译产物 |
| i18next (HTTP 动态加载) | 188.7 KB | -55.1% | 客户端异步请求当前语言 JSON,附带完整基础运行时 |
| ts-intl (默认全量) | 360.0 KB | -14.4% | 合并打包 10 种语言全部 500 条词条 JSON |
| i18next (默认全量) | 420.4 KB | 基准线 (Baseline) | 合并打包 10 种语言全部 500 条词条 JSON 与完整运行库 |
场景二:轻量起步(5 语言 · 命名空间共 100 词条)
在该场景中,字典共包含 100 条词条,页面渲染全部 100 条:
| 库与打包模式 | 首屏传输体积 | 对比 i18next 默认 | 机制特点 |
|---|---|---|---|
| ts-intl (按需拆包) | 29.7 KB | -83.8% | 核心运行时约 2 KB,仅加载当前语言 100 条词条 JSON |
| paraglide (中间件拆包) | 36.1 KB | -80.3% | 仅分发当前语言 100 条词条编译函数 |
| paraglide (默认全量) | 47.1 KB | -74.3% | 合并打包 5 种语言 100 条词条编译函数 |
| ts-intl (默认全量) | 56.9 KB | -69.0% | 合并打包 5 种语言 100 条词条 JSON |
| i18next (HTTP 动态加载) | 167.5 KB | -8.6% | 客户端异步请求当前语言 JSON,附带完整基础运行时 |
| i18next (默认全量) | 183.3 KB | 基准线 (Baseline) | 合并打包 5 种语言 100 条词条 JSON 与完整运行库 |
技术架构与体积构成分析
1. 编译型方案的 Tree-shaking 优势与局限
- 优势:
paraglide将每条翻译消息编译为单独导出的 JavaScript 函数。在打包时,打包工具(如 Rollup / esbuild)能够识别代码中未引用的函数并予以清除(Tree-shaking)。在场景一中,500 条词条中未使用的 400 条未被打包进产物,因此体积最小(36.3 KB)。 - 取舍:需要专属的构建步骤(编译生成 TS/JS 源码),不支持动态远程热更新字典文件。
2. 轻量运行时方案的按需拆包优势
- 无需代码生成:
ts-intl是纯 TypeScript 运行时库,无需代码生成步骤,直接消费标准 TypeScript 对象或 JSON 文件。 - 语言数量线性无关:在
locale-splitting模式下,利用打包工具的动态导入(Dynamicimport())特性,不同语言的词典被自动分块。客户端仅下载当前激活语言的分块,因此当项目支持的语言数量由 5 种增加至 10+ 种时,单页首屏网络传输体积基本保持恒定(约 30 KB ~ 57 KB)。 - 零外部运行时依赖:
ts-intl核心运行时压缩后仅约 2 KB,底层直接利用浏览器标准的 WebIntlAPI 处理复数与数字日期格式,避免携带大型解析引擎。
3. 传统运行时的体积膨胀成因
i18next自身包含丰富的配置系统、事件发射器、AST 解析器及格式化器,基础运行库体积较大。- 在常规配置下,开发者常通过静态
import将各语言资源整体导入主入口,导致所有语言字典无论是否使用均被打包到客户端主 chunk 中。
本地复现基准测试
基准测试套件源码位于 apps/benchmark。可通过以下步骤在本地运行复现:
# 1. 安装测试所需的 Chromium(仅首次执行)
pnpm --filter @aaakul/ts-intl-benchmark prebench
# 2. 运行完整基准测试矩阵(自动完成 SSG 构建并通过 Playwright 采样)
pnpm --filter @aaakul/ts-intl-benchmark bench
# 3. 启动本地预览服务器(可在 http://localhost:3005 访问可视化结果)
pnpm --filter @aaakul/ts-intl-benchmark preview