How does app.js resolve the phoenix imports?

When a new Phoenix project is created, these imports are in app.js

import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
import topbar from "../vendor/topbar"

I’m not a js export, but normally these imports are either relative, such as “topbar” (makes sense that the code is vendored right there in the directory), or they are listed in package.json and the code comes from node_modules folder.

But since a new Phoenix app has neither package.json or a node_modules folder, I’m confused how it knows where to import “phoenix_html”, “phoenix” and “phoenix_live_view” from?

It’s esbuild doing that. It uses NODE_PATH for module resolution which is configured in config/config.exs:

config :esbuild,
  version: "0.17.11",
  default: [
    args:
      ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

You can read a bit more here.

1 Like