Phoenix 1.6.0 LiveView + esbuild + Tailwind JIT + AlpineJS - A brief tutorial

If anyone has trouble getting this to work on Windows this did the trick for me.

watchers: [
    # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
    node: [
      cd: Path.expand("../assets", __DIR__)

You can also do cmd: ["/c", "npx", ... ] to run npx and other things that are .cmd files, which Erlang doesn’t seem to be able to open a port to.


Never considered that. Very helpful.

Are there any tricks/methods for the additional css files you could use as an addition to tailwindcss. Like for example adding @import "./custom-base-styles.css"; to the assets/css/app.css file. Would this still work and where do I need to drop these additional files. When trying via the assets/css/ location doesn’t work.

Has anyone successfully made a Dockerfile integrating his deploy script? I tried generating a mix release.init but for some reason the start command does not seem to get called.


Put the file anywhere in the config directory and when add the path to the esbuild key in config.exs

~w(js/app.js css/custom.css --bundle --loader:.woff2=file --loader:.woff=file --target=es2016 --outdir=../priv/static/assets)

Sharing this here…tailwind with esbuild and phx1.6 WITHOUT the tailwind cli. Uses a build file for esbuild (and the esbuild api). I find this approach much cleaner than having a lot of npm commands everywhere. Also gives you more flexibility with bundling your static assets (the esbuild cli can get long and unwieldy if you are trying to load font files, etc)


I checked out the repo for a sec. Do you see what more there might be to do beyond adding “html-heex” and/or “HTML (HEEx)” into the list of languages?

I didn’t tried anything on that front due to my work busy,

Hello @sergio !
Silly question. In this deployment, where does phoenix logs are stored? I deployed the application on an EC2 instance - and - simply could not locate the logs. I am getting an error message - and - unable to locate the logs to trace the error.

fyi to other readers, it has been added: tailwindcss-intellisense/languages.ts at 0f4d93b96e8d82d42de07477e9be9f0655ccdb5c · tailwindlabs/tailwindcss-intellisense · GitHub



Thanks, that works really well and dramatically lowers the learning curve for Tailwind! :star_struck:

Thaaaaaaanks, just this worked for me

1 Like

For people following this guide if you get errors with AlpineJS you need to change the target from es2016 to a minimum of es2017.

# Configure esbuild (the version is required)
config :esbuild,
  version: "0.13.10",
  default: [
      ~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__)}

For google the errors you’ll see are:

module.esm.js:1635 Alpine Expression Error: func(...).catch is not a function

module.esm.js:1701 Uncaught TypeError: func(...).catch is not a function
    at module.esm.js:1701
    at tryCatch (module.esm.js:1628)
    at evaluate (module.esm.js:1646)
    at module.esm.js:2998
    at Function.<anonymous> (module.esm.js:2390)
    at flushHandlers (module.esm.js:1757)
    at stopDeferring (module.esm.js:1762)
    at deferHandlingDirectives (module.esm.js:1765)
    at initTree (module.esm.js:1953)
    at module.esm.js:1921

I couldn’t trigger that error on Alpine 3.5.1 (latest at time of writing) but the change to fix is straightforward. Thanks for pointing it out!


This was a really great guide thank you! I also had to cross-reference the asset management guide:

That I found after this forum post on external flags for esbuild. You’ll notice that the asset_management guide is updated to reflect external: rather than external=. I also cross-referenced with PragProg’s free guide on Tailwind with esbuild, particularly they add slightly to the deploy script in the assets/package.json:

"scripts": {
  "deploy": "NODE_ENV=production tailwindcss --postcss --minify --input=css/app.css --output=../priv/static/assets/app.css"

Finally, I had to make slight adjustments because Metamorphic has an umbrella app structure. So, my base project mix.exs has this:

"assets.deploy": [
  "cmd --cd ../metamorphic_web/assets npm run deploy",
  "esbuild default --minify",

And my esbuild config expands the path as such:

cd: Path.expand("../apps/metamorphic_web/assets", __DIR__)

That did the trick for me along with making sure my asset handling with priv/static was updated for deployment following the upgrade from a 1.5 app to 1.6.

So, if anyone else is working in an umbrella app, then hopefully this helps you out too. And, again, thank you for the wonderful guide. :heart:


Thank you so much! Your plan to let Google know worked out pretty well.


When esbuild tries to compile app.js, it fails on

> js/app.js:20:16: error: Expected ";" but found "from"
    20 │ import "Alpine" from "alpinejs";

if using just import "Alpine; then

 > js/app.js:20:7: error: Could not resolve "Alpine" (mark it as external to exclude it from the bundle)
    20│ import "Alpine";

I just deleted my folder and recloned the project as is; mix setup and mix phx.server has the project running fine. Check what you’re doing differently and make sure you npm install in your assets folder @Seb

For this one specific error. I wanted to comment, that this error means that you did not install it. And what it usually means is that you don’t have npm as one of the dependencies to do npm install --prefix /assets.

More on a solution here:

It took some time to realize what the error actually meant.
Hope this helps future searchers that find this page on google.

1 Like