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

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.

gist:

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)

2 Likes

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

3 Likes

image

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: [
    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__)}
  ]

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
14 Likes

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!

4 Likes

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",
  "phx.digest"
]

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:

2 Likes

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

2 Likes

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:
http://write.w5hnews.com/u/cwSNkeLNXf#fly-deploy-elixir-pheonix-app-with-npm

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

1 Like