为什么 "Mix.env()" 在布局中调用时在生产中变为零?

Why does "Mix.env()" become nil on production when being called in a layout?

我将其添加到我的基本布局文件中:

<%= if Mix.env() in [:prod] do %>
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?........................
    </script>
<% end %>

它在生产中崩溃了,因为它被认为是 "Mix.env()" 零。

但是同样的代码在开发环境的本地机器上运行。

如何解决?

更新1

但是,为什么这对开发和生产都有效?

  # /lib/my_module1.ex
  defmodule MyAppWeb.MyModule1 do
    use Plug.Builder

    unless Mix.env() in [:prod] do
      # some stuff here
      # all works, no exception thrown

Mix 不必存在于运行时中。它是一个构建工具,用于编译阶段。您可以将 Mix.env() 替换为以下函数:

@env Mix.env()
def env, do: @env

所以会在编译的时候判断是哪个环境

默认情况下,

Mix 不包含在 OTP 版本中。 Elixir 确实通过 mix 在 运行 时隐式加载了多个应用程序,包括但不限于 :mix:runtime_tools:observer

我现在正在努力寻找参考来证明这一点,如果有人知道参考,请在评论中分享我会更新答案。

虽然可以通过将 :mix 添加到 MyApp.Mixfile 中的 :included_applications 列表来明确地将其包含在发布中 [ 但不要那样做!这完全是错误的],正确的解决方案是依赖由项目所有者控制的环境变量。也就是说,在您的生产主机上设置一个环境变量,在一些 .rc 文件中:

export MYAPP_PROD=true

或在您的 systemctl/upstart 脚本中,或在 运行 发布期间明确:

MYAPP_PROD=true bin/my_app foreground

并用System.get_env/1检查:

<%= if System.get_env("MYAPP_PROD") do %>
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?...
    </script>
<% end %>