Is it possible to have page-specific javascript with LiveView?

This is one of the two best threads that come up from search on the topic, so reviving it with an up-to-date solution for the benefit of all.

Just like the OP, I wanted to use a heavy JS library in a single page without compromising the bundle size for the rest of the app.

Nowadays Phoenix projects use esbuild by default, and modern browsers support ESM modules and dynamic import.

To my surprise, asking Gemini 3 produced a reasonable output, hinting at the right things. In a nutshell:

  • Update the esbuild config in config/config.exs to output the bundle as an ESM module and enable code-splitting:
      --format=esm
      --splitting
  • Update the root template to load the app.js as a module:
- <script defer phx-track-static type="text/javascript" src={~p"/assets/js/app.js"}>
+ <script phx-track-static type="module" src={~p"/assets/js/app.js"}>
  • Within a JS hook, import the dependency in the mount() callback.
Hooks.MyHook = {
  async mounted() {
    await import("...")
  }
}
  • Alternatively, import the dependency within an event handler.
window.addEventListener("myapp:action-with-heavy-dependency", event => {
  import("...").then(...)
})

With that setup, esbuild should produce a small bundle for app.js, loaded on all pages, and additional files that are only imported/downloaded/executed when needed.

Resources

15 Likes