`mix phx.server` does not serve CSS with MIX_ENV=prod

Background

I have a Phoenix LiveView app that works well with MIX_ENV=dev. However, when I run it with MIX_ENV=prod, it really looks to me that something is missing.

MIX_ENV=dev:

MIX_ENV=prod:

Code

config/dev

import Config

# The watchers configuration can be used to run external
# watchers to your application. For example, we use it
# with webpack to recompile .js and .css sources.
config :demo, DemoWeb.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__)
    ]
  ]

# Watch static and templates for browser reloading.
config :demo, DemoWeb.Endpoint,
  live_reload: [
    patterns: [
      ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
      ~r"priv/gettext/.*(po)$",
      ~r"lib/demo_web/(live|views)/.*(ex)$",
      ~r"lib/demo_web/templates/.*(eex)$"
    ]
  ]

# Do not include metadata nor timestamps in development logs
config :logger, :console, format: "[$level] $message\n"

# Set a higher stacktrace during development. Avoid configuring such
# in production as building large stacktraces may be expensive.
config :phoenix, :stacktrace_depth, 20

# Initialize plugs at runtime for faster development compilation
config :phoenix, :plug_init_mode, :runtime

config/prod

import Config

config :demo, DemoWeb.Endpoint,
  url: [host: "localhost", port: 80],
  cache_static_manifest: "priv/static/cache_manifest.json"

# Do not print debug messages in production
config :logger, level: :info

config/config

import Config

# Configures the endpoint
config :demo, DemoWeb.Endpoint,
  url: [host: "localhost"],
  secret_key_base: "fNLUlX9B2V22b4mc74qrvWcod6auRthTAz2+E5M/DUL7B+S/WsxQzQBhIXnElayt",
  render_errors: [view: DemoWeb.ErrorView, accepts: ~w(html json), layout: false],
  pubsub_server: Demo.PubSub,
  live_view: [signing_salt: "yRZCwQIF"],
  server: true

# Configures Elixir's Logger
config :logger, :console,
  format: "$time $metadata[$level] $message\n",
  metadata: [:request_id]

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"

Issue

The issue is rather evident. At first I thought the problem was a missing keyword in my config/prod. But after comparing that file with config/dev and reading the comments on the second one, I have that most of the stuff in config/dev is there for the live reload and file watchers. I don’t want any of that for prod (I don’t need to watch files) I just want for the CSS files to be used.

Question

How can I fix this?

Did you run https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Digest.html

1 Like

Prior to this You might also run…

npm run deploy --prefix assets

…then

MIX_ENV=prod mix phx.digest
1 Like

Oh wonderful!
There is only one thing missing. The “LiveDashboard” link is not showing.
This is the code from the template:

<%= if function_exported?(Routes, :live_dashboard_path, 2) do %>
  <%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %>
<% end %>

How can I fix this?

This is normal because it’s not meant to run in production :slight_smile:

Unless You modify your router.

  if Mix.env() in [:dev, :test] do
    import Phoenix.LiveDashboard.Router

    scope "/" do
      pipe_through :browser
      live_dashboard "/dashboard", metrics: KokoWeb.Telemetry
    end
  end
2 Likes