使用Webpack模块联邦在运行时注入环境变量

5

已经有人提出并回答了有关在使用Webpack打包之后注入环境变量的问题。

答案通常基于在index.html文件中加载更新的环境变量。

但是,在使用Webpack模块联邦时,我们只公开了一个component.js文件,因此在构建docker镜像阶段打包源代码,但在服务阶段(例如在k8s内部以pod形式运行我们的打包文件时)读取环境变量应该如何实现呢?

3个回答

2

目前,我们正在将 webpack.EnvironmentPluginDocker 结合使用。

webpack.config.js 中,我们将环境变量替换为特殊字符串:

plugins: [
    new EnvironmentPlugin({
        MY_CUSTOM_ENV_VAR: '{{MY_CUSTOM_ENV_VAR}}',
        ANOTHER_ENV_VAR: '{{ANOTHER_ENV_VAR}}',
    }),
],

这意味着,在构建时,如果没有这些环境变量,bundle将包括字符串'{{MY_CUSTOM_ENV_VAR}}'和'{{MY_CUSTOM_ENV_VAR}}'。
现在,为了替换这些变量,在容器启动时,我们将向RUN命令添加一个替代。
CMD sed -i "s@{{MY_CUSTOM_ENV_VAR}}@${MY_CUSTOM_ENV_VAR}@g" /usr/share/nginx/html/*.bundle*.js \
    && sed -i "s@{{ANOTHER_ENV_VAR}}@${ANOTHER_ENV_VAR}@g" /usr/share/nginx/html/*.bundle*.js \
    && nginx -g "daemon off;"

它将在捆绑文件中使用/usr/share/nginx/html/*.bundle*.js(nginx)将字符串{{MY_CUSTOM_ENV_VAR}}替换为${MY_CUSTOM_ENV_VAR}的值。


0

我正为同样的问题苦苦挣扎... 我只能想到在容器中使用一个约定来处理这个问题。

所有的微前端都可以潜在地在 ./assets/env.template.js(最终为 ./assets/env.js)中暴露它们的环境变量,使用 ${MY_ENVIRONMENT_VARIABLE} 作为占位符。

这个 env.template.js 文件将是一个自动执行的 JavaScript 函数,它会将环境变量值作为全局属性引入 window(请参见下面的示例)。

env.template.js

(function (window) {
  window.env = window.env || {};
  window['env']['clientId'] = '${CLIENT_ID}';
  window['env']['baseUrl'] = '${BASE_URL}'
})(this);

创建docker镜像时,会生成最终的资产env.js,以替代环境变量。例如,使用以下命令创建docker nginx镜像:
CMD ["/bin/sh", "-c", "envsubst < /usr/share/nginx/html/assets/env.template.js > /usr/share/nginx/html/assets/env.js && exec nginx -g 'daemon off;'"]
容器在加载远程组件时,会尝试动态加载其公开在assets中的env.js文件。
普通的Angular注入环境将从window.env获取值。

最终,我使用了类似的解决方案,但更加优雅,因为我们使用了动态模块联邦。我们的容器根据描述其远程入口和可用模块的配置加载微前端。在解决这个问题之前,我们只有“路由”模块类型(由根路由模块用于构建路由)和“其他”模块类型(用于其他类型的插件模块,如仪表板小部件等)。 为了解决这个问题,我们添加了一个新的启动模块类型,它将在启动时加载,并且这个模块将负责加载env.js。 - Jon

-2
在 webpack.config 文件中
const webpack = require('webpack');       
require('dotenv').config({ path: './.env' }); 

然后在插件模块部分添加这个

new webpack.DefinePlugin({
  "process.env": JSON.stringify(process.env);
}),

这将从计算机中获取所有环境变量的代码。

另一个改进是通过这种方式实现的,这样您就可以创建像.env.development.env.production这样的文件。

module.exports = (env, args) => {
    require("dotenv").config({ path: `./.env.${args.mode}` });

如果您想仅传递在 .env 文件中定义的环境变量,请将 require 更改为以下内容:
const dotenv = require("dotenv").config({ path: ./.env.${args.mode}` }); 

将definePlugin更改为以下内容:

new webpack.DefinePlugin({ "process.env": JSON.stringify(dotenv.parsed), }),

但请注意,所有这些解决方案都在“webpack”命令期间可用-“构建”时间。现在假设我已经捆绑了我的代码,并创建了一个带有它的Docker镜像。如何启动容器并使用一些环境变量来在包中使用? - baruchiro
你可以在 Dockerfile 中构建应用程序,只需使用入口点命令即可。 - Vitor de oliveira
但是此时负载需要时间。 - baruchiro
1
我认为这并没有真正回答问题。在构建时将环境变量传递到Docker容器中已经是一个解决的问题。问题在于运行时,这方面并没有广泛理解的解决方案。 - Daven Quinn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接