Starting Phoenix with conditional watchers?

I was wondering if there was a way in development to invoke something like mix phx.server --no-watch which I could somehow in dev.exs remove (or set to an empty list) my watchers. Many times I just want to boot my endpoint (so I can test my Absinthe GraphiQL API or run introspection queries) without firing off needless or (temporarily) erroring asset/webpack compilation.

I thought about this for quite a while and I’m not sure it’s possible… I think Mix.Tasks.Run --config can be passed a custom configuration file but not sure how to merge that config with my existing dev.exs.

You might create a new environment without watcher…

  • copy config/dev.exs to config/nowatch.exs

  • remove watcher in nowatch.exs

  • update mix.exs, to include live reload for nowatch

      {:phoenix_live_reload, "~> 1.0", only: [:dev, :nowatch]},

And run your server in nowatch env.

$ MIX_ENV=nowatch iex -S mix phx.server
Erlang/OTP 21 [erts-10.0.6] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

[info] Running PhLabWeb.Endpoint with cowboy 1.1.2 at http://localhost:4000
Interactive Elixir (1.7.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

This way. webpack will not run.

1 Like

I wonder if using conditional branching in the dev.exs would work

# somewhere in dev.exs
unless System.get_env("NO_WATCH") do
  config :app, App.Endpoint, watchers: [
    yarn: ["watch", cd: Path.expand("../assets", __DIR__)]
  ]
end
NO_WATCH=true iex -S mix phx.server

It might lead to unnecessary re-compilation.

2 Likes

I tried this and it’s working too.

if System.get_env("NO_WATCH") do
  config :ph_lab, PhLabWeb.Endpoint,
    http: [port: 4000],
    debug_errors: true,
    code_reloader: true,
    check_origin: false,
    watchers: []
else
  config :ph_lab, PhLabWeb.Endpoint,
    http: [port: 4000],
    debug_errors: true,
    code_reloader: true,
    check_origin: false,
    watchers: [node: ["node_modules/webpack/bin/webpack.js", "--mode", "development", "--watch-stdin",
                      cd: Path.expand("../assets", __DIR__)]]  
end

:+1:

You don’t need to duplicate common configuration since it’s always being merged for the same keys. So this would return the same final configuration as yours:

config :ph_lab, PhLabWeb.Endpoint,
    http: [port: 4000],
    debug_errors: true,
    code_reloader: true,
    check_origin: false

if System.get_env("NO_WATCH") do
  config :ph_lab, PhLabWeb.Endpoint, watchers: []
else
  config :ph_lab, PhLabWeb.Endpoint,
    watchers: [node: ["node_modules/webpack/bin/webpack.js", "--mode", "development", "--watch-stdin",
                      cd: Path.expand("../assets", __DIR__)]]  
end

or

config :ph_lab, PhLabWeb.Endpoint,
    http: [port: 4000],
    debug_errors: true,
    code_reloader: true,
    check_origin: false

unless System.get_env("NO_WATCH") do
  config :ph_lab, PhLabWeb.Endpoint,
    watchers: [node: ["node_modules/webpack/bin/webpack.js", "--mode", "development", "--watch-stdin",
                      cd: Path.expand("../assets", __DIR__)]]  
end
3 Likes

Thanks @idi527 and @kokolegorille… It works!

I spent a lot of time trying to call functions from a config kwlist and trying to figure out how to bring custom command line switches into scope in dev.exs when all I had to do was read from the global env var then merge the watcher into the endpoint config!

I’m sure your method defining a new environment would have worked @kokolegorille but I didn’t test as the other way is simpler.