如何在Webpack+Angular中替换bundle变量I18N_MAP?含NX构建问题
解决方案
方案一:基于HtmlWebpackPlugin钩子实现全局变量注入(适配Nx构建)
Nx默认通过HtmlWebpackPlugin生成index.html,直接操作compilation.assets["index.html"]会因为构建流程差异失效,改用HtmlWebpackPlugin的官方钩子即可兼容开发/生产环境,且支持内存文件处理。
步骤1:编写自定义插件
import { Compiler } from 'webpack'; import { HtmlWebpackPlugin } from 'html-webpack-plugin'; class HtmlI18nReplacementPlugin { apply(compiler: Compiler): void { compiler.hooks.compilation.tap('HtmlI18nReplacementPlugin', (compilation) => { // 监听HTML模板渲染完成后的钩子 HtmlWebpackPlugin.getHooks(compilation).afterTemplateExecution.tapAsync( 'HtmlI18nReplacementPlugin', (data, callback) => { // 从compilation中读取manifest.json const manifestAsset = compilation.assets['manifest.json']; if (!manifestAsset) { return callback(null, data); } // 解析manifest内容并转换为JS对象字符串 const manifestContent = JSON.parse(manifestAsset.source().toString()); const i18nMapStr = JSON.stringify(manifestContent); // 替换HTML中的占位符(需提前在模板中定义) data.html = data.html.replace('{{I18N_MAP_PLACEHOLDER}}', i18nMapStr); callback(null, data); } ); }); } } export default HtmlI18nReplacementPlugin;
步骤2:配置Webpack
在Nx项目的webpack配置文件中注册插件:
const WebpackManifestPlugin = require('webpack-manifest-plugin'); const HtmlI18nReplacementPlugin = require('./path-to-your-plugin'); module.exports = { plugins: [ new WebpackManifestPlugin({ filter: (item) => item.name.startsWith('assets/i18n/'), }), new HtmlI18nReplacementPlugin(), ], };
步骤3:修改HTML模板
在项目的index.html模板中添加占位符:
<script>const I18N_MAP = {{I18N_MAP_PLACEHOLDER}}</script>
方案二:用webpack.DefinePlugin直接替换代码变量(无需修改HTML)
如果不需要将I18N_MAP暴露到全局,仅在代码中使用,可直接通过DefinePlugin在编译阶段替换变量,更简洁高效。
编写自定义插件
import { Compiler, DefinePlugin } from 'webpack'; import WebpackManifestPlugin from 'webpack-manifest-plugin'; class I18nMapDefinePlugin { apply(compiler: Compiler): void { compiler.hooks.emit.tap('I18nMapDefinePlugin', (compilation) => { const manifestAsset = compilation.assets['manifest.json']; if (!manifestAsset) return; const manifestContent = JSON.parse(manifestAsset.source().toString()); // 动态注入DefinePlugin,替换代码中的I18N_MAP常量 new DefinePlugin({ I18N_MAP: JSON.stringify(manifestContent), }).apply(compiler); }); } } export default I18nMapDefinePlugin;
配置Webpack
module.exports = { plugins: [ new WebpackManifestPlugin({ filter: (item) => item.name.startsWith('assets/i18n/'), }), new I18nMapDefinePlugin(), ], };
原方案失效原因
Nx生产构建时,HtmlWebpackPlugin生成的index.html不会直接存入compilation.assets,而是通过内部流程处理,导致直接读取compilation.assets["index.html"]无法找到目标文件。使用HtmlWebpackPlugin的官方钩子可绕过该限制,兼容所有构建模式。
内容的提问来源于stack exchange,提问作者Yackbz
相关产品推荐
相关产品推荐

