【问题标题】:Environment Variables in an isomorphic JS app: Webpack find & replace?同构 JS 应用程序中的环境变量:Webpack 查找和替换?
【发布时间】:2025-12-09 18:45:02
【问题描述】:

我正在使用 webpack 捆绑同构 JS 应用程序 (based on this example),以便浏览器运行与服务器相同的代码。一切都运行顺利,除了我有一个config.js,其中一些设置是从服务器上的环境变量中提取的:

module.exports = {
  servers:
    auth: process.env.AUTH_SERVER_URL,
    content: process.env.CONTENT_SERVER_URL
  }
}

在服务器上这很好,但是当 webpack 为客户端渲染时 process 是空的,这不起作用。

我希望有一种“查找和替换”的 webpack 插件,可以单独用文件中的内容替换它们?

"…config.js content…".replace(/process\.env\.([a-z0-9_]+)/, function(match, varName) {
  return process.env[varName];
})

【问题讨论】:

  • 我找到了envify,但我很难配置它。
  • 有一个插件,允许将应内联的环境变量列入白名单:new webpack.EnvironmentPlugin(["AUTH_SERVER_URL", "CONTENT_SERVER_URL"])
  • 问题在于构建环境的机器并不总是运行代码的机器(在我们的例子中确实如此)。一种方法是将它们放在 HTML 中的 globalwindow 中,但这不是我最喜欢的解决方案。

标签: javascript webpack


【解决方案1】:

我需要一种方法来使用在运行代码的机器上设置的环境变量,而不是使用构建应用程序的机器的环境变量。

我还没有看到解决方案。这就是我所做的。

publicEnv.js:

// List of the env variables you want to use on the client. Careful on what you put here!
const publicEnv = [
  'API_URL',
  'FACEBOOK_APP_ID',
  'GA_ID'
];

const isBrowser = typeof window !== 'undefined';
const base = (isBrowser ? window.__ENV__ : process.env) || {};

const env = {};
for (const v of publicEnv) {
  env[v] = base[v];
}
export default env;

在我拥有的页面的 HTML 模板文件中:

import publicEnv from 'publicEnv.js';

...

<script>
  window.__ENV__ = ${stringify(publicEnv)};

  // Other things you need here...
  window.__INITIAL_STATE__ = ${stringify(initialState)};
</script>

所以现在我可以通过以下方式在前端和后端获取 env 变量的值:

import publicEnv from 'publicEnv.js';

...

console.log("Google Analytic code is", publicEnv.GA_ID);

希望对你有帮助。

【讨论】:

    【解决方案2】:

    请注意,按照接受的答案中的建议使用DefinePlugin 可能是一个危险的操作,因为它完全暴露了process.env。正如 Tobias 上面评论的那样,实际上有一个插件 EnvironmentPlugin 可以通过添加白名单功能完成此操作,在内部使用 DefinePlugin

    在你的webpack.config.js

    {
      plugins: [
        new webpack.EnvironmentPlugin([
          'NODE_ENV',
          'WHITELISTED_ENVIRONMENT_VARIABLE'
        ])
      ]
    }
    

    【讨论】:

    • 我不明白 webpack 怎么知道用 "production" 替换 NODE_ENV,例如。使用 envify 你需要告诉它用什么替换NODE_ENV——这是怎么工作的?
    • Webpack 并没有真正替换这里的任何值,它会将您从 process.env 列入白名单的任何内容注入到您的代码中,并使用已经设置的任何值。您需要在编译开始之前自己设置环境变量。从命令行NODE_ENV=production webpack,或者在你的Webpack配置文件process.env.NODE_ENV = 'production'
    【解决方案3】:

    在您的webpack.config.js, 使用以下preLoaders(或postLoaders),

      module: {
        preLoaders: [
          { test: /\.js$/, loader: "transform?envify" },
        ]
      }
    

    使用webpack.DefinePlugin的另一种方式:

    plugins: [
        new DefinePlugin({
          'process.env': Object.keys(process.env).reduce(function(o, k) {
            o[k] = JSON.stringify(process.env[k]);
            return o;
          }, {})
        })
    ]
    

    注意:使用envify-loader 的旧方法已被弃用:

    已弃用:改用transform-loader + envify

    【讨论】:

    • 出于兴趣,基于什么理由不推荐使用另一种方法?
    • envify-loader 中所做的一切都只是一个包装。讨论here.
    【解决方案4】:

    是的;看起来envify-loader 是一个简单的解决方案。

    我刚刚在我的 webpack 加载器中添加了以下内容:

    {
      test: /config\.js$/, loader: "envify-loader"
    }
    

    并且config.js(并且只有那个文件)被修改为静态包含任何引用的环境变量:)

    【讨论】:

    • 此方法已弃用!