多语言项目可通过自定义打包插件剔除未使用的语言包以减小体积。插件在构建阶段静态分析 locale 路径,仅保留白名单语言,支持 vite(resolveid 钩子)和 webpack(normalmodulereplacementplugin),并可进阶结合 ast 扫描自动推断语言标识。

在多语言项目中,构建产物常因引入完整语言包(如 moment、ant-design、element-plus 的 locale 文件)而体积膨胀。自定义打包插件可在构建阶段静态分析并剔除未使用的语言包代码,无需手动维护,效果直接且可复用。
识别冗余语言包的关键路径
多数 UI 库或工具库将语言包组织为独立模块,路径有明显规律,例如:
-
antd/es/locale/zh_CN.js、antd/es/locale/en_US.js -
element-plus/lib/locale/lang/zh-cn.js、en.js -
dayjs/locale/zh-cn.js、ja.js
插件需监听这些路径的导入语句,在依赖图生成阶段捕获实际被引用的语言包,其余视为冗余。
在 Vite 中编写简易剔除插件
Vite 插件可通过 transform 或 resolveId 钩子介入模块解析。推荐使用 resolveId 拦截 locale 路径,仅保留白名单语言:
export default function localePrunePlugin(options = {}) {
const { include = ['zh-CN', 'zh-cn', 'en-US', 'en-us'] } = options;
const validLocales = new Set(include.map(s => s.toLowerCase()));
return {
name: 'locale-prune',
resolveId(id) {
// 匹配常见 locale 路径模式
const localeMatch = id.match(/\/locale\/(?:lang\/)?([a-z_-]+)\.js$/i);
if (localeMatch) {
const lang = localeMatch[1].toLowerCase();
if (!validLocales.has(lang)) {
return { id: '\0virtual:empty-locale', external: true };
}
}
},
load(id) {
if (id === '\0virtual:empty-locale') return 'export default {};';
}
};
}
在 vite.config.ts 中启用:
import localePrune from './plugins/locale-prune';
export default defineConfig({
plugins: [localePrune({ include: ['zh-cn', 'en-us'] })],
});
Webpack 场景下使用 NormalModuleReplacementPlugin
Webpack 更适合用 NormalModuleReplacementPlugin 在模块解析时重定向:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.NormalModuleReplacementPlugin(
/\/locale\/(?:lang\/)?([a-z_-]+)\.js$/i,
(resource) => {
const lang = resource.request.match(/\/locale\/(?:lang\/)?([a-z_-]+)\.js$/i)?.[1]?.toLowerCase();
if (lang && !['zh-cn', 'en-us'].includes(lang)) {
resource.request = path.resolve(__dirname, 'src/stubs/empty-locale.js');
}
}
)
]
};
确保 src/stubs/empty-locale.js 存在且导出空对象或兼容接口,避免运行时报错。
进阶:结合编译期语言检测自动推断
若项目通过 import locale from 'xxx/locale/zh-CN' 显式引入,可进一步在 transform 阶段扫描 AST,提取所有字面量语言标识,动态构建白名单。例如用 @babel/parser 解析源码,查找 CallExpression 或 ImportDeclaration 中匹配 /locale\/[a-z_-]+/i 的字符串,汇总后用于后续剔除逻辑。这种方式无需硬编码 include,更适合大型多语言切换项目。










