【问题标题】:Should I include mix app in extra_applications?我应该在 extra_applications 中包含混合应用程序吗?
【发布时间】:2021-12-03 05:25:08
【问题描述】:

我正在使用 distillery 打包一个 elixir 应用程序,我想在运行时访问当前环境(是 :dev:test 还是 :prod)。

目标是在运行时检查环境,如下所示:

if Mix.env() == :prod do
  # do this only in production
end

在版本中包含mix 应用程序有什么缺点?

def application do
    [mod: {EvercamMedia, []}, extra_applications: [:runtime_tools, :os_mon, :recon, :mix]]
end

【问题讨论】:

  • 一开始你为什么要这样做?
  • @AlekseiMatiushkin 我只想在 prod 环境中执行一些功能。

标签: elixir distillery


【解决方案1】:

使用mix 检测生产环境显然是一种反模式。取而代之的是,人们可能应该将发布作为

MY_APP_PROD=true release start

并使用如下所示的系统环境检查

if System.get_env("MY_APP_PROD") == "true" do
  ...
end

【讨论】:

  • 如果不在函数内部使用,可以在编译时评估。
  • 是的,我想我们都知道什么时候评估了什么:)
  • 也许你可以,但确保每个人都能理解,即使是初学者也是一个很好的做法。
  • @AlekseiMatiushkin 为什么它是反模式对我来说并不明显,您能否详细说明这一点?
  • 这是一种反模式,因为 mix 从未被设计为在 prod 运行时中正常工作,它是编译时的野兽。
【解决方案2】:

您应该在您的版本中包含mix。您有多种选择:

  • 使用在运行时设置的环境变量,然后:
    • 使用例如在代码中检查它System.fetch_env!
    • config/runtime.exs 中检查它(不是 config/prod.exs;这也在编译时进行评估)。
  • 或者将MIX_ENV 的值编译到你的代码中。 @Daniel 提供了一种方法来做到这一点。我提供另一个:
defmodule M do
  @build_env Mix.env()

  def env(), do: @build_env
end

这里的技巧是@build_env... 语句在编译时进行评估(当 Mix is 可用时),设置属性。然后你可以从你的函数中返回它。

【讨论】:

    【解决方案3】:

    Mix 在生产中被禁用是有原因的,它是一个构建工具,你可以阅读更多关于它的信息here

    如果你只需要当前环境,那么你可以这样做:

    defmacro env() do
        quote do
          unquote(Mix.env())
        end
      end
    

    但是您需要记住,此代码是在编译时评估的,不适用于runtime 配置之类的东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 2019-03-16
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多