通过静态分析AST实现编译期语言包按需加载,识别$t、t、useI18n().t等调用的key,裁剪locales文件并动态注入import逻辑,生成精简.min.json且输出为独立chunk。
直接通过静态分析 AST 实现按需加载语言包插件,核心是识别代码中实际用到的语言 key,再自动生成对应 locale 文件并剔除未使用项。这不是运行时逻辑,而是在构建阶段完成的“编译期裁剪”。
目标是捕获所有 $t('xxx')、t('xxx')、useI18n().t('xxx')、{{ $t('xxx') }}(Vue 模板)等调用形式。关键不是字符串字面量本身,而是其作为第一个参数的静态可解析 key:
@babel/parser 解析源码为 AST,重点关注 CallExpression 和 MemberExpression 节点$t、i18n.t、useI18n().t),且第一个参数是 StringLiteral
value 字段,例如 $t('user.name') → 'user.name',归入 key 集合拿到全项目所有被引用的 key 后,需将其映射到各语言的实际文案。不建议硬编码翻译,而是基于已有结构做裁剪:
locales/zh-CN.json、locales/en-US.json 等原始文件,解析为 JS 对象'button.submit'),递归查找其在各语言文件中的路径:用 key.split('.') 逐级取值locales/zh-CN.min.json,体积通常压缩 40%–70%光裁剪不够,还要让运行时只加载当前语言的精简包。这步需修改入口或 i18n 初始化代码:
立即学习“前端免费学习笔记(深入)”;
createI18n({ locale, messages }))@babel/traverse 找到 messages 参数对象表达式import(`./locales/${locale}.min.json`),并包裹 then(...) 处理异步加载messages: { 'zh-CN': {...} }),则重写为函数式工厂:messages: () => import(...)
最终产出要能被 Webpack/Vite 正确识别为独立 chunk,避免回退到主包:
@babel/generator 输出修改后的 AST 为代码import('./locales/' + locale + '.json'))splitchunks 规则,将所有 /locales/.*.min.json$/ 匹配进 locales chunk 组build.rollupOptions.output.manualChunks 实现同样效果这个插件不依赖框架运行时,也不修改业务逻辑,只在构建期读源码、改 AST、写文件。它把“按需”从“用户切换时加载”推进到“编译时就只包含真正需要的文案”,更彻底,也更容易测试和调试。