Search code examples
elixirphoenix-framework

How to read an external file from elixir script (exs)?


I'm writing an exs file that renders liveview. Is it possible to read javascript from an external javascript file using a script tag like below ? I'm getting this error.

<script type="text/javascript" src="/assets/app.js"></script>

Error:
17:30:10.499 [error] #PID<0.385.0> running Example.Endpoint (connection #PID<0.383.0>, stream id 2) terminated
Server: localhost:5001 (http)
Request: GET /assets/app.js
** (exit) an exception was raised:
    ** (ArgumentError) unknown application: :sample
        (elixir 1.15.5) lib/application.ex:1010: Application.app_dir/1
        (plug 1.15.0) lib/plug/static.ex:420: Plug.Static.path/2
        (plug 1.15.0) lib/plug/static.ex:191: Plug.Static.call/2
        live.exs:108: Example.Endpoint.plug_builder_call/2
        live.exs:108: Example.Endpoint.call/2
        (plug_cowboy 2.6.1) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2

Here are my router and endpoint settings.

Application.put_env(:sample, Example.Endpoint,
  http: [ip: {127, 0, 0, 1}, port: 5001],
  server: true,
  live_view: [signing_salt: "aaaaaaaa"],
  secret_key_base: String.duplicate("a", 64)
)
defmodule Example.Router do
  use Phoenix.Router
  import Phoenix.LiveView.Router

  pipeline :browser do
    plug(:accepts, ["html"])
  end

  scope "/", Example do
    pipe_through(:browser)

    live("/", HomeLive, :index)
  end
end

defmodule Example.Endpoint do
  use Phoenix.Endpoint, otp_app: :sample
  socket("/live", Phoenix.LiveView.Socket)


  plug Plug.Static,
  at: "/",
  from: :sample,
  gzip: false,
  only: ~w(assets js fonts images uploads favicon.ico robots.txt)

  plug(Example.Router)
end

Solution

  • The Plug.Static docs describe how to reference a static file, specifically the :from option. From the docs, this value can be either:

    • a string containing a file system path
    • an atom representing the application name (where assets will be served from priv/static)
    • a tuple containing the application name and the directory to serve assets from (besides priv/static), or an MFA tuple.

    Because you provided an atom (:sample), the resolution of the macro/function causes it to look for an app of that name in order to resolve its path to its priv/static directory.

    Instead, you should double-quote the value so it is a string representing the path : "sample/path". I'm guessing the value represents a directory, but you'll have to play around with it to know for sure.