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

I’m using Webpack 4.43.0. I didn’t notice the docs are for v5, but the dynamic imports are certainly working for me.

I’m going to open-source YouMeet when it launches, so I don’t have the full repo open to browse yet, but here are some snippets that I think covers it.

Here’s an example hook to load a fancy WYSIWYG editor that’s using Vue:

hooks.Editor = {
  mounted() {
    const phoenix = this;
    const target = this.el.getAttribute('phx-target');
    const Editor = () => import(/* webpackChunkName: "editor" */ "./components/Editor.vue");
    () => import(/* webpackChunkName: "highlight" */ "./syntax-highlighter");

    new Vue({
      el: this.el,
      provide: function() {
        return {
          publish: this.publish
        };
      },
      methods: {
        publish: payload => phoenix.pushEventTo(target, "editor-update", payload)
      },
      render: createElement =>
        createElement(Editor, {
          props: {
            initialValue: phoenix.el.dataset.initialValue,
            placeholder: phoenix.el.dataset.placeholder,
          }
        })
    });
  }
};

On the LiveView EEX to load it (actually a LiveComponent but should be about the same)

<div phx-update="ignore" id="Editor-<%= @id %>">
  <div data-placeholder="<%= html_escape(@description_placeholder) %>" 
       data-initial-value="<%= html_escape(input_value(f, :description)) %>" 
       phx-target="<%= @myself %>" 
       phx-hook="Editor" 
       class="container flex h-screen m-4">
  </div>
</div>

and in my Webpack config:

// all the configs plus this:
  output: {
    filename: "[name].js",
    chunkFilename: "[name].bundle.js",  // <-- this line
    path: path.resolve(__dirname, "../priv/static/js"),
    publicPath: "/js/"
  },
// ... no optimizations key
// this may imply that you need to split code yourself.

EDIT: There should be a GIF right here, but it doesn’t seem to load? Sorry, it’s just illustrating how navigating from one LiveView without the script, and then clicking a link to another liveview does trigger the JS fetch and import.
dynamic-import-via-hook

Hopefully I didn’t miss anything!

7 Likes