前端 ssr + csr 组合渲染国际化i18n方案

483 阅读3分钟

前端国际化i18n方案

前端在国际化方案的时候就会使用 i18n 那么在 i18n 中就会遇到一些问题

  • 假设 temu (碰瓷) 的其中一个页面来思考

image.png

- 考虑蓝色选中区域为国际化非后端下发,在切换各个国家/语言的情况

问题 1

正常在使用 i18n 时,需要配置每个语言 文件 信息,如:en.json, de.json等, 如果直接按语言引入文件则会导致当前项目随着代码量和业务推进会导致当前的体积会越来愈大(C 端 i18n 需要响应速度)

那么按需加载是我们必须考虑的行为

以我们项目为例

  • 文件数据剔除(剔除项目中未存在的内容)
    • 按需加载(en.json, de.json 等可能会存在一些我们并不需要翻译内容进行剔除)
  • 文件抽离(i18n 进行分包,分为首屏 i18n 和 全量)
    • 项目为(nestJS) ssr + csr + react 组合渲染
      • 考虑 i18n 的体积问题
      • 考虑在 ssr 首屏 和 csr 渲染的时候 i18n 的优化方向
  • 按需加载(自动分配)

1. 文件数据剔除

如何进行文件剔除?

webpack 构建时进行 Plugin,在 initialize 初始化的生命周期里进行获取,相关 json 然后通过约定使用 i18n 的正常使用方式来进行匹配发现被使用则认为当前 key 是使用中的状态,add 到我们的 使用中 i18n list 中,随后进行输出即可.

到这,其实已经解决了 我们 60% 以上的性能问题了

2. 文件抽离

如何进行文件抽离?

项目中通过 loadable 以及 创建 loadable-stats.json 来进行分配当前 chunk 到哪个模块上,并不存在 router 的维度,所以我们添加一个 babel plugin 来给 router 行为的添加标识,然后在通过 router 去查到 chunk ,chunk 再去获取到当前 chunk 下的 key,至此我们可以拿到当前 router 到 key 的所有数据

我们的代码维度

babel 对 router 进行添加标识
webpack initialize 解析 标识,获取 router 和 chunk 的对应关系
webpack initialize 中解析到 chunk 和 key 的关系
webpack 输出 translate.json 我们自己的路由和i18n 的关系图

loadable-stats.json loadable 的依赖关系数据

image.png

至此我们拿到了最重要的关系数据

image.png

省略了代码,大家脑补

ssr 通过客户端提供的 path 过滤 然后注水 i18n 到 state 数据中 (前置会提供各个path 的 redis 缓存,及前置的 页面 cdn 达到毫秒级打卡)

问题 3 衍生问题

虽然我们通过上述获取了重要的关系 json ,但是知识限制在 ssr 中存在,只是优化了首屏,那么 csr 之后的数据如何处理,及用户跳转后的页面可能不存在当前 i18n 数据该如何处理?

多层级引入

我们解决了首屏加载 i18n 的问题,那么衍射问题 csr 拿不到数据如何解决呢?

预加载当前页面以外的其他页面的 i18n, 使用 IntersectionObserver 去识别 路径上 path 这样我们可以预加载当前的数据,且先拦截这些跳转行为

加载之前的全量数据源,一旦加载完成则表示 i18n 加载完毕,这样多层加载就实现了

省略了代码,大家脑补(后续会出个 demo 留言)

至此,首屏的语言包几乎忽略,csr 的基本也没有其他特别大的问题

后续优化

感觉这样的思路可能还有更好的方法,哪个大哥可以带带弟弟(留言)

其他优化

google 插件查看当前页面那个地方使用了哪个 key,方便运营,产品同学自己去后台修改翻译内容