You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:03:31