informatom

informatom

Using the Tailwindcss/jit Compiler with Phoenix

I have set up Tailwindcss for a Phoenix (v 1.5.8, so using Webpack, Liveview and Surface) project successfully and tried to switch to the new tailwindcss/jit-Compiler. That does not fully work, as changes in a view or template file won’t get picked up. If I touch the tailwind config file manually, the compiler recompiles successfully. So my issue is the range of files, that are monitored by webpack.

Currently by watcher config looks like this (from dev.exs):

config :pan, PanWeb.Endpoint,
  http: [port: System.get_env("PORT") || 4000],
  debug_errors: true,
  code_reloader: true,
  check_origin: false,
  watchers: [
    node: [
      "node_modules/webpack/bin/webpack.js",
      "--mode",
      "development",
      "--watch-stdin",
      cd: Path.expand("../assets", __DIR__)
    ]
  ]

The tailwindcss/jit documentation stresses, that you set NODE_ENV=development, which should be done with --mode development, I hope.
Anybody knowing, what should be changed? I tried to remove the cd ../assets part, but then the webpack config is broken.

Marked As Solved

_toni

_toni

Using webpack v4 + tailwind 2.1.1, I find that with mode: 'jit', every new class that I add keeps accumulating to the CSS bundle size even though it’s not being used​:smiley:
Eg.

  1. using text-green-200 → Filesize 10kb
  2. using text-green-200 & text-blue-300 → Filesize 10.1kb
  3. using text-green-200 & text-red-400(replacing the previous blue)-> Filesize 10.2kb
  4. using text-green-200 & text-purple-300(replacing the previous red, hence only green and purple being used)-> Filesize 10.3kb
  5. Restart server + using text-green-200 & text-purple-300 —> Back to 10.1kb

Did you encounter this behavior as well? If so, does it change with webpack 5?

Also Liked

APB9785

APB9785

Creator of ECSx

When I tried switching my Phoenix project from standard tailwind to tailwind JIT using the official instructions, it stopped generating new classes. Any classes that were already used in a previous version were available, but if I used a new class, there would be no effect, even after shutting down the server and recompiling. The dev team was unwilling to help troubleshoot because they don’t know Phoenix so I just went back to standard tailwind, which works great for me.

If anyone does manage to get JIT running with Phoenix, please let us know how (and maybe let the tailwind-JIT team know too so they can update the installation instructions for Phoenix users). The added features shown in the demo look fantastic.

arathunku

arathunku

I’ve summarized my notes from switching to @tailwindcss/jit in a blog post if anyone’s curious - @arathunku - Test driving @tailwindcss/jit. SPOILER: It's great

In dev.exs, I’m using:

  yarn: ["run", "dev:watch", cd: Path.expand("../assets", __DIR__)]

I prefer to have all flags inside 1 single command in package.json

soup

soup

If you run webpack separately, maybe the issue is clearer. Webpack has no idea when you alter templates because it doesn’t look at .html.exs files (or in the lib/) folder.

AFAICT, webpack4 can only / will only watch files that it finds via an entry point (which is why our JS file includes a imports a CSS file). I don’t think there is a good way to add an elixir template as an entry point.

TailwindJIT has it’s own watcher stuff I think, but I am not sure where it gets it’s file list from. Probably by piggybacking the purge purge-css option in it’s config.

Why invalidating the root CSS file causes everything to start working, I am not sure.

Possibly:

  • Tailwind watcher runs as a child of webpack, but maybe doesn’t start automatically or doesn’t run on boot, or something.
  • webpack doesn’t see template changes in html.exs files (no entry point).
  • changing the css file causes webpack to notice a css change.
  • tailwind watcher wake up, they do know to look at exs files because we tell it what to search for when it runs it’s purge-css stuff.
  • now tailwind watcher is awake and template changes propagate back out.

Maybe…


Edit:

There are a few moving parts:

TailwindCSS-jit works additively (in NODE_ENV=development) from an in memory cache (?).

Each time you restart the server and invalidate the css file, you get a fresh tw build.

This means:

  • As you go through the “add class to html, invalidate css hash” workflow, the new class appears in the CSS, but the old class remains there.
  • If you don’t restart the server, those old classes remain, even if they are no longer in your templates.
  • When you do restart the sever but do not invalidate the hash, the old classes still hang around even if they are not in your templates.
    • so they still “seem to work”, because the css still exists.
  • Adding new classes to a template wont work until you invalidate the css, at which point the old but now unused classes disappear. Now it you try to use a “it worked before” class, it won’t work because it’s now a new class.

This is why it seems to work “some of the time” and why my main project seems immune to issues: (mostly) all the classes used in that project are already there.

On top of all this, there seems to be a race condition where you may be served the css file before tailwind has finished building it, so the hot reload may show no change but a hard reload will. This is most likely to occur if you use an expensive (?) class like a custom color.


Edit:

Basically, the TLDR is:

  • Follow the phx-tailwindcssjit repo to setup TailwindCSS-jit (Mostly as per instructions except for the extra webpack4 patch).
  • Start your server as NODE_ENV=development mix phx.server
  • Invalidate the main css entry point (Add a blank line to the end of app.css, save)
  • Edit your templates as normal, repeat the invalidation every time you restart your server.

That should be reasonably reliable. Sometimes you may have to hard refresh the page if you hit the race condition.


Edit edit edit edit:

Probably it’s all rooted in HardSourceWebpackPlugin.

A fresh clone of the repo will work flawlessly for me, no messing about with invalidating the css hash.

Stop the server, restart it and you have to start invalidating the hash.

rm -rf assets/node_modules/.cache/hard-source and start the server and you have no issues again.

I don’t actually notice any real speed differences with the cache nuked, and hard source hasn’t been updated in a few years, possibly it’s out of style/not needed with modern js systems. Could probably just drop it from your webpack config if you want.

Where Next?

Popular in Questions Top

myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New

We're in Beta

About us Mission Statement