Skip to content

vue-i18n 架构瓶颈凸显,Intlayer 提出构建时预编译方案 ​

译注:本文编译自 dev.to 文章《The Problem with vue-i18n and Why Intlayer Fixes It》,作者 Ay Pineau,原文发布于 2026 年 9 月 23 日。文中数据与观点均来自原文,链接见文末。

在 Vue 3 或 Nuxt 中构建国际化应用时,vue-i18n 长期是默认选择。Kazupon 与社区共同打造了一个成熟且功能丰富的生态,多年来一直是 Vue 应用本地化的标准方案。

要理解 vue-i18n 为何如此运作,需要回到它架构设计的年代:它诞生于经典的单页应用(SPA)时代,那时动态导入(import())与路由级代码分割尚未普及。在那种范式下,启动时把单个庞大的翻译对象一次性加载进内存完全合理。

然而现代前端开发围绕激进的页面体积优化展开,无论是使用 Nuxt、静态站点生成(SSG)还是细粒度的动态页面加载。在这一背景下,中心化的全局 provider 模型已成为严重的架构瓶颈。

库本身体积也出乎意料地大:一个仅导入 vue-i18n 的空组件,在渲染任何一个字之前就要付出 24.3 KB gzip(83.2 KB minified) 的代价。为什么这么大?因为它内置了一整套运行时引擎,在浏览器中即时处理消息格式逻辑,求值 {{number}} 或 {name} 这类动态插值、复数规则与列表格式化。此外,处理本地化路由与 URL 管理还需要额外的客户端逻辑,用于 cookie 存储、语言检测与 URL 前缀。

这还没算上更大的架构缺陷:跨路由的大规模文案泄漏。

在典型的 Vue 应用中,createI18n({ messages }) 会实例化一棵全局消息树,包含所有受支持语言的每一个翻译键。用户访问一个简单的 /contact 页面时,浏览器被迫下载 /dashboard、/pricing、/settings 以及应用其余部分的字符串。在一个标准的 10 路由、10 语言的 Vite + Vue 3 应用基准测试中,某个页面上下载的翻译负载有 90% 属于完全无关的路由。由于 useI18n() 将组件绑定到这个全局实例,单独编译一个组件平均会拖入 196 KB 的 JavaScript。

更进一步,由于 t("key.path") 依赖运行时动态字符串求值,Vite 和 Rollup 等打包工具无法静态追踪实际使用了哪些键。未使用的翻译无法被 tree-shaking,键名拼写错误会在运行时静默失败,而不是在构建期被 TypeScript 捕获。

Intlayer 如何解决? ​

Intlayer 的思路是在构建时消除这些额外逻辑,通过静态转换把内容直接连接到相关组件,而不是依赖臃肿的运行时解析器与 provider。

1. 构建时预编译(无运行时解析开销)

不再把沉重的解析器发送到浏览器去求值 {{number}} 这类消息插值,或在运行时管理 cookie 存储与 URL 前缀,Intlayer 在构建期就解析并优化这些逻辑。浏览器收到的是精简的预编译代码,所有额外机制都被剥离,运行时体积降至 3.9 KB(使用兼容适配器则为 7.9 KB)。

2. 组件与内容直接绑定

不再把所有字符串倾倒进庞大的 locales/en.json,Intlayer 将字典就近放置在消费它的组件旁边(例如 Footer.content.ts 与 Footer.vue 并列)。因此,未被导入的组件永远不会加载未使用的内容。死代码与未渲染组件不携带任何翻译体积。

3. 借助 Vite 实现零瀑布式动态加载

更进一步,Intlayer 利用了 Vite 的高级模块转换能力。即使使用动态页面加载与代码分割,Intlayer 也只把该 chunk 中实际消费的本地化内容直接附加进 bundle。没有额外的网络请求或瀑布去等待远程 JSON 字典再渲染。组件与其精确的本地化字符串在同一个 chunk 中一起到达。

4. 严格的编译期安全

Intlayer 直接从内容声明生成严格的 TypeScript 定义。你可以获得键名的 IDE 自动补全,缺失翻译或拼写错误会在构建期立即报错,从而消除生产环境中的运行时回退意外。

5. 0% 泄漏与 3 倍更小的 bundle

在构建期,Intlayer 编译器静态分析调用点并拆分字典,使每个路由只下载它实际渲染的字符串。在基准测试中,页面文案泄漏从 90% 降至 0%,每页 JavaScript 从 134.9 KB 降至 47.0 KB(gzip)。作为参照,不含任何 i18n 的基线应用为 41.3 KB。

6. 通过 @intlayer/vue-i18n 直接迁移

如果你已有 Vue 代码库,无需重写组件。@intlayer/vue-i18n 兼容适配器暴露与 vue-i18n 完全相同的 API(useI18n、t()、d()、n()、$t、v-t)。只需添加 Vite 插件并去掉庞大的 messages 导入,现有的 t("key") 调用就会自动绑定到编译后、已拆分的字典,在零 .vue 文件改动的前提下将运行时缩小 3 倍、组件缩小 23 倍。

如果你在生产环境运行本地化的 Vue 或 Nuxt 应用,不妨在任意子页面查看浏览器的 Network 面板:你很可能会发现,下载的 JavaScript 中大部分是用户永远不会读到的翻译文案。

完整的分析、基准测试与迁移指南见:

原文链接 ​