A proof-of-concept integration of Vite.js (modern JS/assets bundler) with Phoenix + Liveview

Hi @50kudos! I tried Vite today for the first time with Phoenix 1.6 and your response was really helpful. In the end, I had to do a little bit more work, but It seems everything is working as expected. Here’s my setup…

package.json

{
  "repository": {},
  "description": " ",
  "scripts": {
    "build": "vite build",
    "watch": "vite build --watch --minify false --emptyOutDir false --clearScreen false --mode development"
  },
  "dependencies": {
    "@popperjs/core": "^2.10.1",
    "bootstrap": "^5.1.1",
    "phoenix": "file:../deps/phoenix",
    "phoenix_html": "file:../deps/phoenix_html",
    "phoenix_live_view": "file:../deps/phoenix_live_view"
  },
  "devDependencies": {
    "sass": "^1.42.1",
    "vite": "^2.5.10"
  }
}

Fixes problems with import resolution for “phoenix”, “phoenix_html” and “phoenix_live_view” and includes support for Sass.

vite.config.js

export default {
  publicDir: "./static",
  build: {
    target: "es2018",
    minify: true,
    outDir: "../priv/static",
    emptyOutDir: true,
    assetsInlineLimit: 0,
    rollupOptions: {
      input: ["js/app.js", "css/app.scss"],
      output: {
        entryFileNames: "js/[name].js",
        chunkFileNames: "js/[name].js",
        assetFileNames: "[ext]/[name][extname]"
      }
    },
  }
}

dev.exs

config :my_app, MyAppWeb.Endpoint,
  http: [ip: {127, 0, 0, 1}, port: 4000],
  debug_errors: true,
  code_reloader: true,
  check_origin: false,
  watchers: [
    npm: ["run", "watch", cd: Path.expand("../assets", __DIR__)]
  ]

mix.exs

"assets.deploy": ["cmd --cd assets npm run build", "phx.digest"]

endpoint.ex

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

Differs from the default esbuild config which outputs directly to priv/static/assets.

root.html.heex

<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/css/app.css")}/>
<script defer phx-track-static type="module" src={Routes.static_path(@conn, "/js/app.js")}></script>

Updates public path and adds type="module" to properly load the exposed javascript module.


PS.: It seems that Vite supports older browsers with a plugin but I didn’t seem to work for me.

Bonus: If you are using VS Code with ElixirLS and your *.heex files are not properly highlighted you can add the following setting to your user config: "files.associations": {"*.heex": "html-eex" }

8 Likes