【问题标题】:How to access environment variables in client side code during build in Meteor?在 Meteor 中构建期间如何访问客户端代码中的环境变量?
【发布时间】:2021-12-22 21:16:35
【问题描述】:

相关:

我也知道METEOR_SETTINGS

我有一个 Meteor 应用程序,它将为具有不同主题/功能的不同客户端部署。我想使用诸如process.env.CLIENT 之类的环境变量并使用if(process.env.CLIENT === 'foo') 之类的代码。在构建期间,应该替换 env 变量,并且死代码消除将删除/剥离 if 块。这已经适用于NODE_ENV

我不想发布某个客户端不需要的代码,也不想隐式公开其他客户端的列表。如果我在运行时检查Meteor.settings,这两件事都会发生。我需要在编译时发生这种情况。每个客户端都有不同的构建。

如何将环境变量传递给客户端?其他人是如何解决这个问题的?客户端上的process.env目前是:

{"NODE_ENV":"development","TEST_METADATA":"{}"}

在其他构建工具中,我可以访问客户端上的所有环境变量,也可以访问具有特殊前缀(出于安全原因)的环境变量,例如 FOO_

【问题讨论】:

  • 为什么不能使用方法来获取METEOR_SETTING?您可以在客户端调用 Meteor.startup 中的方法,使其在其他任何操作之前运行。
  • 如果您要进行不同的构建,为什么不使用 bash 脚本将“变量”替换为硬编码值。大致就是这样,例如,webpack 也是这样做的。
  • Meteor 设置正是为您为不同的部署分配不同的settings.json 而构建的。使用mup,您可以轻松管理它,因为每个部署都有一个文件夹,其中包含一个 mup 设置和一个 settings.json。这就是我们将同一应用的多个实例部署到不同客户的方式。
  • @Jankapunkt 我一定遗漏了有关 Meteor 设置的一些内容:我需要在 编译时 删除一些东西,这就是我的回答所做的(以及我已经在做的)在非 Meteor 项目中)。我知道我可以为每个构建使用 Meteor 设置来在 runtime 进行配置。您能否发布如何将 Meteor 设置集成到构建过程中的答案?
  • 它只是部署文件夹中的一个 JSON 文件,因此您可以在任何阶段随意转换它。 mup 还允许为此编写钩子,因此不需要 babel、webpack 等。由于您的部署文件夹中有不同的设置文件,因此它也不会修改您的开发设置文件。

标签: meteor


【解决方案1】:

像往常一样睡了一晚,答案是:https://babeljs.io/docs/en/babel-plugin-transform-inline-environment-variables/

meteor npm install babel-plugin-transform-inline-environment-variables --save-dev

添加.babelrc

{
  "plugins": [
    ["transform-inline-environment-variables", {
      "include": [
        "CLIENT"
      ]
    }]
  ]
}

现在这两个都按预期工作

CLIENT=foo meteor run
CLIENT=foo meteor build --directory $OUT

(在切换开发中的客户端以正确重建之前,撒上一些 m -rf .meteor/local/plugin-cache/

原码:

if (process.env.CLIENT === 'foo') {
  console.log('Client is foo');
} else if (process.env.CLIENT === 'bar') {
  console.log('Client is bar');
}

开发过程中的输出:

if ("foo" === 'foo') {
  console.log('Client is foo');
} else if ("foo" === 'bar') {
  console.log('Client is bar');
}

生产中的输出:

console.log("Client is foo")

在开发过程中,这让我可以轻松地在客户端之间切换。在同一客户端上工作时,添加/删除 process.env.CLIENT 按预期工作并使用 hmr 等。

对于部署,我使用dokku。这意味着一旦我配置了环境 (dokku config:set app CLIENT=foo),我就可以:

git push client_foo main
git push client_bar main

从同一个分支部署两个客户端,而不必担心事情会搞砸。

【讨论】:

    【解决方案2】:

    正如@ChristianFritz 的answer 中所述,Meteor 构建系统似乎不直接支持您的用例。

    正如您所发现的,当前的解决方案可能是依赖 Meteor 设置,但您仍会为捆绑包中的所有案例(客户/客户)提供代码。

    如果我要使用解决方法,我会将所有客户特定的代码收集在单独的文件夹中,并使用符号链接进行交换。这样,您的应用程序的其余部分将使用恒定路径导入这些位。显然,请确保在每次特定于客户的构建之前更新符号链接目标。

    但这样的用例也意味着客户特定的服务器捆绑包。如果您计划为每位客户配备一台服务器,这对您来说可能没问题,正如您似乎暗示的“每个客户都有不同的构建。

    【讨论】:

    • 谢谢!有趣的想法,但符号链接为人为错误提供了空间并且需要人工。我还想在同一个文件中包含 if/else,这对我正在做的事情来说要容易得多。
    • "符号链接为人为错误提供了空间并且需要人工":确实不需要手动处理它们; npm 脚本/您首选的自动化工具是要走的路。
    【解决方案3】:

    创建多个不同的构建并不是 Meteor 本身支持的。我认为这也很不寻常。

    但是,由于它是独立的进程,您可以使用类似于以下的 bash 脚本自己构建对它的支持:

    #!/bin/bash
    
    FOO_VALUE=$1
    echo "Using variable value $FOO_VALUE";
    
    for file in $(find imports/ui/); do
      echo "Replacing special variables in $file"
      sed -i "s/FOO_CLIENT/$FOO_VALUE/g" $file;
    done
    
    DIR="build_$FOO_VALUE/"
    mkdir -p $DIR
    meteor build -d $DIR
    

    【讨论】:

    • 谢谢!有趣的想法,但我认为这个答案缺少一个关键部分:在开发过程中这将如何工作?
    • 你告诉我。您目前在开发过程中如何做到这一点,您希望它如何?您正在创建单独的构建,您是否还在开发中运行单独的流星实例?或者您希望只保留一个正在开发的实例?通过正确使用魔法变量的语法,以上所有内容都是可能的。
    猜你喜欢
    • 2016-04-28
    • 1970-01-01
    • 2012-07-28
    • 2019-04-07
    • 1970-01-01
    • 2020-11-04
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多