React Aria 多语言构建瘦身实战:@react-aria/optimize-locales-plugin 从原理到配置

发布时间:2026/9/14 19:25:34
React Aria 多语言构建瘦身实战:@react-aria/optimize-locales-plugin 从原理到配置 React Aria 多语言构建瘦身实战react-aria/optimize-locales-plugin 从原理到配置【免费下载链接】react-spectrumA collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.项目地址: https://gitcode.com/GitHub_Trending/re/react-spectrum本文围绕 React Spectrum 仓库中的国际化构建优化插件 optimize-locales-plugin 展开。React Aria / React Spectrum 默认会将 20 个左右的语言包en-US、fr-FR、zh-CN……全部打进产物而该插件通过拦截模块解析只保留你应用实际支持的 locale从而显著缩小 bundle 体积。读完后你将理解它的拦截原理、locale 匹配规则并掌握 webpack / Next.js / Vite / Rollup / esbuild 五种构建工具下的完整配置方式。插件解决的问题语言包体积膨胀React Spectrum 各包在构建产物中以内嵌intl/目录的方式携带翻译字符串。以 packages/adobe/react-spectrum/intl/inlinealert/index.js 为例该文件一次性import了 20 个 locale 的 JSON 文件并合并为按语言代码索引的对象import csCZ from ./cs-CZ.json; import daDK from ./da-DK.json; // ... import zhTW from ./zh-TW.json; export default { cs-CZ: csCZ, // ... zh-TW: zhTW };这意味着即使应用只服务中文用户产物里依然带着捷克语、丹麦语等全部语言字符串。react-aria/optimize-locales-plugin的目标就是把配置中未列出的 locale 对应的字符串模块从 bundle 中剔除。插件基于 unplugin因此一套核心逻辑即可同时覆盖 Vite、Rollup、Webpack 与 esbuild。Parcel 不在 unplugin 支持范围内官方为它提供了专门的替代方案react-aria/parcel-resolver-optimize-locales见下文 Parcel 用户。核心实现在模块解析阶段劫持语言包导入插件的全部逻辑只有 LocalesPlugin.js 一个文件其本质是向宿主构建工具注册一个resolveId钩子在构建器解析导入路径时做拦截。关键源码如下// packages/dev/optimize-locales-plugin/LocalesPlugin.js const localeSpecifierRegex /[a-z]{2}-[A-Z]{2}/; const sourcePathRegex //\\[/\\]/; module.exports createUnplugin(({locales}) { locales locales.map(l new Intl.Locale(l)); return { name: locales-plugin, vite: { enforce: pre }, resolveId: { filter: { id: localeSpecifierRegex }, handler(specifier, sourcePath, options) { if (!sourcePathRegex.test(sourcePath) || options?.ssr) { return; } let match specifier.match(localeSpecifierRegex); if (match) { let locale new Intl.Locale(match[0]); if (!locales.some(l localeMatches(locale, l))) { return path.join(__dirname, empty.js); } } return null; } } }; });从源码结构看插件的工作流程分为四步正则过滤filterresolveId注册时附带filter.id /[a-z]{2}-[A-Z]{2}/。只有导入路径中包含小写两位-大写两位形态 locale 标识如./fr-FR.json的模块才会进入 handler其他导入如./helpers完全不受影响几乎零性能开销。导入方白名单sourcePathRegex只有当发起导入的文件位于react-stately/*、react-aria/*、react-spectrum/*、adobe/react-spectrum、react-stately、react-aria或react-aria-components这些包路径下时才会执行裁剪逻辑正则同时兼容/与\支持 Windows 路径。这保证了插件只作用于 React Spectrum / React Aria 生态内部的语言包导入你项目里其他恰好形似 locale 的文件不会被误伤。locale 匹配判定handler 用正则从 specifier 中提取出 locale 标识转成Intl.Locale对象后与用户配置的 locales 逐一比较若都不匹配则把该模块重定向到包内的 empty.js——其内容仅有一行export default undefined;。这样被剔除语言包的模块仍然可被正常解析和 tree-shaking产物中对应语言字符串彻底消失。SSR 排除options?.ssr为真时直接return不做任何重定向。也就是说服务端构建保留全部语言包裁剪只发生在客户端 bundle 中——这是合理的因为 SSR 场景下语言切换/回退逻辑仍可能引用完整语言表。另外注意vite: { enforce: pre }这一配置插件被标记为预置执行确保它的resolveId跑在大多数插件之前语言包重定向不会被其他解析逻辑抢先处理掉。locale 匹配规则裸语言代码可覆盖所有地区变体配置中的 locale 字符串先被转成Intl.Locale实例locales.map(l new Intl.Locale(l))随后由文件末尾的localeMatches函数做匹配判定function localeMatches(localeToMatch, includedLocale) { return ( localeToMatch.language includedLocale.language (!includedLocale.region || localeToMatch.region includedLocale.region) ); }该函数表达了两条规则语言代码必须相等fr-FR的导入只有在配置了fr系 locale 时才会被保留。配置中的 region 是可选门槛若配置的 locale 不含 region如裸写fr则所有fr-*地区变体fr-CA、fr-BE……全部保留若配置了具体 region如fr-FR则只保留精确匹配。测试文件 对这套规则做了完整验证值得重点关注的几个用例测试用例断言结果验证的规则en-US配置下导入./fr-FR.json来自react-aria/button等 7 个生态包全部重定向到empty.js未列出的 locale 被剔除且各包均在白名单内导入方是some-other-pkg时导入./fr-FR.json返回undefined不处理白名单外模块不受影响配置[en-US, fr-FR]时导入./fr-FR.json返回null正常解析列出的 locale 原样保留配置[en-US, fr]时导入./fr-CA.json返回null正常解析裸语言代码保留所有地区变体传入{ssr: true}返回undefined不处理SSR 构建跳过裁剪Windows 风格路径C:\repo\node_modules\adobe\react-spectrum\...重定向到empty.js反斜杠路径同样可识别测试中还验证了 filter 本身的过滤行为./fr-FR.json能命中filter.id而./helpers不会——与源码中的正则过滤一致。构建工具配置locales是唯一配置项类型定义为readonly string[]见 LocalesPlugin.d.ts 中的UnpluginInstanceOptions, false。配置中未列出的 locale 字符串会从 bundle 中移除。下面是原文档给出的各构建工具配置均可直接复制使用。webpack// webpack.config.js const optimizeLocales require(react-aria/optimize-locales-plugin); module.exports { // ... plugins: [ optimizeLocales.webpack({ locales: [en-US, fr-FR] }) ] };Next.jsNext.js 底层即 webpack通过next.config.js的webpack钩子注入插件即可// next.config.js const optimizeLocales require(react-aria/optimize-locales-plugin); module.exports { webpack(config) { config.plugins.push( optimizeLocales.webpack({ locales: [en-US, fr-FR] }) ); return config; } };Vite// vite.config.js import optimizeLocales from react-aria/optimize-locales-plugin; export default { plugins: [ optimizeLocales.vite({ locales: [en-US, fr-FR] }) ] };如前所述Vite 场景下插件以enforce: pre预置模式生效可放心放在plugins数组中无需刻意调整顺序。Rollup// rollup.config.js import optimizeLocales from react-aria/optimize-locales-plugin; export default { plugins: [ optimizeLocales.rollup({ locales: [en-US, fr-FR] }) ] };esbuildimport {build} from esbuild; import optimizeLocales from react-aria/optimize-locales-plugin; build({ plugins: [ optimizeLocales.esbuild({ locales: [en-US, fr-FR] }) ] });说明原文档此处以 esbuild 原生 API 演示参数形态。由于 unplugin 的 esbuild 支持通常由 unplugin 生态中的esbuild-plugin适配层完成实际项目若报错可检查 esbuild 插件挂载方式是否正确。Parcel 用户请改用 react-aria/parcel-resolver-optimize-localesunplugin 不直接覆盖 Parcel。README 明确提示Parcel 用户应使用react-aria/parcel-resolver-optimize-locales。该 resolver 就位于本仓库 packages/dev/parcel-resolver-optimize-locales同样服务于只保留应用支持的语言包这一目标。如果你的项目基于 Parcel仓库内多个examples/示例如examples/s2-parcel-example即采用 Parcel请查阅对应包的文档获取配置方式而不是尝试在这里挂载 unplugin 实例。使用前提与注意事项结合源码与测试使用该插件时需要注意以下边界locale 书写格式匹配依赖/[a-z]{2}-[A-Z]{2}/形态的标识导入路径中的 locale 必须是标准xx-XX形态语言小写、地区大写才能被识别和裁剪配置项建议同样使用Intl.Locale可解析的标准格式。作用范围仅限 React Spectrum / React Aria 生态包sourcePathRegex白名单意味着插件只裁剪上述 7 类包路径下的导入第三方库自带语言包不在处理范围内。SSR 构建不受影响ssr选项为真时插件静默退出服务端产物保留全部语言包体积优化只体现在客户端 bundle 上。被剔除的模块以空模块兜底重定向目标 empty.js 导出undefined因此若运行时代码在语言回退链中显式访问某个被剔除 locale 的翻译取到的将是undefined而非抛错。生产环境请确保locales配置覆盖了用户可能实际使用的语言。插件不改变运行时行为只改变构建产物它不修改任何源码也不影响开发调试dev 下同样生效但 SSR 除外可以放心长期挂入构建链。小结react-aria/optimize-locales-plugin用不到 60 行代码解决了一个多语言项目的通用痛点通过 unplugin 的resolveId钩子在模块解析阶段把未列出的 locale JSON 重定向为空模块实现按应用支持的语言裁剪 bundle。其设计上有几个值得借鉴的细节——正则预过滤降低钩子执行成本、导入方白名单避免误伤、裸语言代码兼容所有地区变体、SSR 构建豁免、Windows 路径兼容。对于同时使用 React Spectrum / React Aria 且服务多语言的团队这是一个低成本、低风险、且已被仓库内单元测试充分验证的构建瘦身手段。【免费下载链接】react-spectrumA collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.项目地址: https://gitcode.com/GitHub_Trending/re/react-spectrum创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考