Why to use mix.install when deps are already declared on mix.exs?

I already defined plug and cowboy as deps on mix.exs and installed it using mix deps.get, but my code (that is the simple hello world from plug documentation) only works if I load the deps on the top of the file using

Mix.install([:plug, :plug_cowboy])
when I try to run without it, I get the error
module Plug.Conn is not loaded and could not be found

There should indeed no need to use Mix.install in an actual mix project, can you share a reproducer?

sure I’ll try it, my project was generated with Mix so it follows the basic structure
i’m following this guide from Plug with cowboy
I dont know how to markdown correctly on this forum but here is my mix.exs file

defmodule Api.MixProject do
  use Mix.Project

  def project do
    [
      app: :api,
      version: "0.1.0",
      elixir: "~> 1.16",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  def application do
    [
      extra_applications: [:logger]
    ]
  end

  defp deps do
    [
      {:plug, "~> 1.11"},
      {:plug_cowboy, "~> 2.0"}
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end
end

and here is my plug.exs file

defmodule Plug do
  import Plug.Conn

  def init(options) do
    options
  end

  def call(conn, _opts) do
    conn
    |> put_resp_content_type("text/plain")
    |> send_resp(200, "hello world")
  end

end

require Logger
webserver = {Plug.Cowboy, plug: Plug, scheme: :http, options: [port: 4000]}
{:ok, _} = Supervisor.start_link([webserver], strategy: :one_for_one)
Logger.info("Plug now running on localhost:4000")
Process.sleep(:infinity)

mix.exs its located at root folder, and plug.exs inside lib, there is no additional files, and to run the application i’m running elixir plug.exs inside the lib folder

hey @henriquesati at least one issue here is that defmodule Plug is creating a module named Plug, but that name is already taken by Plug itself. It’s best to always scope your modules under the namespace of your project.

Secondly, how are you running your exs file? To run scripts inside your mix project you want to mix run path/to/script.exs. More normally you’d separate out the module you’re building into a .ex file and then put your other stuff there in a supervision tree. To build a project with a supervision tree, you want to mix new --sup. Most Plug tutorials should cover this.

Finally as a minor note, please use code format blocks, it makes things a lot more readable.

3 Likes

there is something additional that I need to do? I’m following Plug final step that says:

Save that snippet to a file and execute it as elixir hello_world.exs . Access http://localhost:4000/ and you should be greeted!

I changed the module and file name to myplug, but still cant run it without mix.install
also how do I do format blocks here? I usually use OF and they just have a button for this

Ok now I got it, I must use Mix to run it instead of elixir, not working yet but a different error at least, thanks!

That is a script (notice the .exs extension). You can basically run that script standalone without creating a mix project by using elixir command as it is documented.

If you want a full-fledged mix project, then the setup is different, you have to add dependencies to mix.exs, the plug to your application supervision tree and the module in a separate .ex file. Then you can run the project by calling mix run or iex -S mix.

4 Likes