i18n动态加载本身不会让页面变慢,问题在于错误实现:如全量加载多语言json、未分包的大型模块、裸fetch无缓存、同步遍历节点更新文案等,导致首屏阻塞、布局抖动和解析卡顿。

为什么 i18n 动态加载会让页面变慢
浏览器解析 HTML 时,如果语言包靠 JS 动态 fetch 或通过document.write() 注入,就会打断 DOM 构建、延迟首屏渲染。更常见的是:所有语言的文案全塞进一个 JSON 文件,哪怕只用中文,也得下载整份含 20 种语言的 500KB locales.json;或者用 import('./zh-CN.js') 按需加载,但没做 code splitting,导致模块体积过大、解析卡顿。
关键不是“要不要国际化”,而是“要不要一次性加载全部”——多数页面首屏只用到 10–20 个字符串,却拉下整个词典。
只加载当前语言的最小资源
默认语言(如zh-CN)应内联在 HTML 中,避免额外请求;其他语言用动态 import + 预加载提示,不阻塞主流程。
- 服务端根据
Accept-Languageheader 渲染对应语言的<script type="application/json" id="i18n-data"></script>,内容仅含首屏所需 key-value 对 - 非首屏文案(如弹窗、设置页)用
import(`./locales/${lang}.js`),配合 Webpack/Rollup 的 dynamic import 分包 - 对已缓存的语言包加
integrity属性,防止 CDN 被篡改后加载错乱文案 - 禁用
fetch('/locales/en-US.json')这类无缓存、无 fallback 的裸请求;必须配cache: 'immutable'和headers: { 'Accept': 'application/json' }
避免 DOM 重绘和 layout shift
翻译后替换文本节点时,若容器宽度随文字长度变化(比如中英文混排按钮),会导致布局抖动,影响 CLS 分数。实操要点:
- 所有可翻译元素必须设固定
width/min-width,或用 CSStext-overflow: ellipsis截断长文本 - 用
data-i18n-key标记而非直接 innerText 替换,方便 SSR 时预填充、客户端复用 - 切换语言时,用
requestIdleCallback批量更新,不卡主线程;别在click回调里同步遍历 200 个节点 - 图标+文字组合场景(如
<button><svg></svg>提交</button>),把文案抽到<span data-i18n-key="submit"></span>,SVG 保持静态
fallback 和降级必须显式声明
用户语言是ja-JP,但你的 locales/ja-JP.json 缺失或 404,这时候不能留空或报错,得有兜底逻辑。
常见错误是写成:
const text = dict[key] || key;
这会让日文用户看到英文 key(如 btn_submit),体验崩坏。
- fallback 应该是语义等价的简短中文或英文,例如
dict[key] ?? fallbackDict[key] ?? 'Submit' - 构建时用脚本扫描所有
data-i18n-key,比对各语言文件缺失项,CI 阶段就报警 - 本地开发时模拟网络失败:用 DevTools 的 Network → Offline + 禁用缓存,验证 fallback 是否生效
- 不要依赖
navigator.language做唯一判断——它可能返回zh,但服务端给的是zh-Hans,匹配不上就 fallback 到 English
font-family: 'Meiryo', sans-serif,切到阿拉伯语却还沿用同一套字体栈,导致部分字符显示为方块。这个不在 i18n 数据里,得靠 CSS media query 或 class 切换联动。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











