为何Elixir应用在IEx运行正常,发布版本需添加:eex依赖?
:eex need to be added to extra_applications for a Distillery release but not when running in IEx? 你遇到的这个差异其实和Elixir/Erlang应用的加载机制,以及Mix开发环境和Distillery发布版本的环境差异直接相关,咱们一步步拆解清楚:
1. 为什么IEx(iex -S mix)里不用显式加:eex?
当你用iex -S mix启动应用时,Mix会自动加载所有关联的依赖应用,包括那些被间接引用的。虽然Plug.Debugger确实依赖EEx来渲染错误页面,但在Mix的开发环境中,EEx作为Elixir标准库的一部分,会被默认加载——毕竟Mix本身的很多功能(比如模板编译)也依赖它,所以哪怕你没在extra_applications里声明,Mix也会悄悄把它拉进来,保证开发时的体验顺畅。
说白了就是:Mix开发环境会默认兜底加载不少标准库应用,刚好补上了这个依赖缺口。
2. 为什么Distillery发布版本必须显式加:eex?
Distillery生成的发布版本是最小化的独立运行包,它只会严格加载你在extra_applications里明确声明的应用,以及这些应用直接声明依赖的应用。而Plug.Debugger对EEx的依赖属于间接依赖——Plug本身并没有把EEx列为它的必填依赖,所以发布构建工具不会自动把EEx包含到最终包中。
当发布版本运行时,Plug.Debugger尝试调用EEx.Engine.fetch_assign!/2,却发现这个模块根本没被加载,自然就抛出了UndefinedFunctionError。
解决办法
正如你自己推测的,只需要把:eex添加到mix.exs的extra_applications配置里,重新构建发布版本就搞定了:
extra_applications: [:cowboy, :plug, :logger, :eex]
这样发布构建工具就会把EEx应用包含到最终的发布包中,Plug.Debugger就能正常渲染错误页面了。
内容的提问来源于stack exchange,提问作者Adam Millerchip

