Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fetch Elixir dependencies per environment?

Tags:

hex

elixir

There are multiple ways to install Elixir dependencies. I wonder what happens in the following cases:

1.

mix deps.get --only prod

What exactly dependencies are being fetched then?

2.

defp deps do
  [
    {:credo, "~> 0.8", only: ~w(dev)a, runtime: false},
  ]
end

How only option impact on a particular dependency?

3.

def project do
  [
    # ...
    deps: deps(Mix.env()),
  ]
end

What is the difference if we specify dependencies like that?


I'm confused a little bit when to use what regarding defining dependencies.

like image 713
Kamil Lelonek Avatar asked Jun 16 '17 14:06

Kamil Lelonek


2 Answers

When you write this :

mix deps.get --only prod

It will fetch all dependencies for the prod environment, namely the dependencies where there is no only option, and dependencies where the only option is specified and containing :prod (e.g {:some_dep, "~> 0.8", only: [:prod]})

When you write this :

defp deps do
  [
    {:some_dep, "~> 0.8"}
  ]
end

That tells mix to install some_dep in any environment it is run into.

When you write this :

defp deps do
  [
    {:another_dep, "~> 0.8", only: [:dev]}
  ]
end

It tells mix to install another_dep only when your environment is dev (MIX_ENV=dev). If you are in any other environment (e.g. prod), mix deps.get will simply ignore another_dep and won't install it.

writing this :

def project do
  [
    # ...
    deps: deps(Mix.env()),
  ]
end

will result in ** (CompileError) mix.exs:13: undefined function deps/1 because in your mix.exs, only deps/0 is defined. Now you might tell me why not implement deps(:dev), deps(:prod) and so on... Well, if you read what I explained before, you'll see that it is pointless, since the deps separation for each environment is already taken care of :)

like image 121
BachirC Avatar answered Nov 15 '22 07:11

BachirC


I'm going to address these in reverse order.

using deps(Mix.env) would force you to specify each of your dependencies multiple times if they are used across multiple environments. Something along the lines of

def deps(:dev) do
  [
    {:ecto, "~> 2.1"}
    {:credo, "~> 0.8", runtime: false}
  ]
end
def deps(:test) do
  [
    {:ecto, "~> 2.1"}
  ]
end

I will admit that I do not even know if this would work, but this is adding too much code for something that is already handled for you if you just specify the :only option.

Using :only allows you to specify which environments a dependency should be used in. In your example, {:credo, "~> 0.8", only: [:dev], runtime: false} you are telling mix that the credo package should only be used in the dev environment. If you do not include the :only option, the package will be used in all environments.

$ mix deps.get --only prod will only retrieve the packages relevant to the production environment. From the previous example, the credo package will not be retrieved because you told mix that credo should only be used in the dev environment.

like image 23
Justin Wood Avatar answered Nov 15 '22 09:11

Justin Wood