dbern

dbern

Adding `--tailwind` flag to phx.new

I heard on a podcast episode on Thinking |> Elixir that there could be some TailwindCSS support when generating new Phoenix projects.

https://twitter.com/j_tormey/status/1334168111675809792

I’d love to work on this feature, but before I start slinging code, I’d like some buy-in from the Phoenix team. Are there any thoughts on how Tailwind could be included in a new Phoenix project?


Should this be the default for new Phoenix projects, instead of the included Milligram CSS? I like how Milligram is super easy as a drop-in without really any work to pull it out if you wanted to use a different CSS framework. Literally delete the phoenix.css file and you’re done.


Should this be opt-in via a --tailwind flag on the phx.new generator? I’m inclined to go this way, since including Tailwind also has some workflow changes, and several files. Adam Wathan seems to suggest avoiding using Sass when also using PostCSS to avoid some glitches; so I’m also thinking that this --tailwind flag would also not include sass by default and instead setup Sass-like features through PostCSS

  • postcss-import
  • postcss-nested

other thoughts? Also heads up, there’s an in-progress guide for integrating TailwindCSS into Phoenix from the tailwindcss.com site

Most Liked

josevalim

josevalim

Creator of Elixir

As the person who literally implemented the Rails Application Templates in the incarnation still used today, they have many pitfalls that may not be obvious unless you maintain them and/or write anything mildly complex with them. For example:

  1. Brittle. Whenever you change the generated code, which is often common, there is a chance template code will break or it will generate the wrong application

  2. They don’t compose. As application templates get more and more complex, it is unlikely you can run multiple of them

  3. Untested. Back then I don’t remember seeing a single application generator which comes with a comprehensive test suite (which would help addressing previous points)

  4. Hard to maintain. It is really hard to maintain an application template as you extend it because they lack structure

But most importantly, I think application templates most often miss the point: what are the odds that you need to execute something exactly when the application is being generated? For example, take mix phx.gen.auth, it could be designed as an --auth flag to phx.new but it is just so much better as its own standalone project.

So what about Tailwind support on Phoenix if it is not part of Phoenix? How would someone approach that? Easy:

$ mix archive.install hex phx_new
$ mix archive.install hex phx_new_tailwind
$ mix phx.new foo
$ cd foo
$ mix phx.new.tailwind # change everything required for tailwind support

While this approach doesn’t necessarily address point 1, because this type of code will always be brittle, it pretty much does better in all other points mentioned above. The beauty of phx_new_tailwind is:

  1. Is its own project, with proper structure, and hopefully tests

  2. Has its own command, which means it has a proper place to document all of its options and behaviour (something you don’t get with application templates iirc)

I am sure this process is nowhere as fleshed out as Rails Application Templates, but I would rather use this approach as a starting point and improve it based on feedback than pick a solution that has many known pitfalls. In any case, it is 100% possible today.

This is not even specific to Phoenix… as the same can be achieved with Rails generators and it is pretty much the approach I preferred back then: devise and simple_form used rails devise:install and rails simple_form:install commands instead of templates. I remember maintaining some front-end based installers way back then too.

sasajuric

sasajuric

Author of Elixir In Action

I used to think that too until I started consulting an agency, and what I saw made me change my minds. My clients start new projects fairly frequently. They want to keep the different projects technically as similar as possible to each other (language, frameworks, libraries, CI/CD). When I started working with them they have already built their own custom generator which expanded on phx.new generating some custom stuff (like e.g. deploy pipeline).

One of my main tasks has been introducing common Elixir style & practices to their projects, with the purpose of assisting with project switches. A company-wide custom generator has been indispensable in making this happen, so I’ve spent significant amount of time expanding it. Examples of simpler things we’re doing include generating our own custom credo configuration, or setting up default CI checks (formatter, credo, dialyzer, migrations reversibility, OTP release).

In addition, the generator also performs some more complicated changes on top of phx.new, such as moving db/endpoint configuration to init callbacks, renaming some files, most notably everything under the web folder, together with renaming corresponding modules. Changing some configurations in config scripts, etc. Such changes are made using a hacky combination of regex search & replaces, file operations (e.g. rename), or in some cases by completely overwriting the generated files.

It all feels fragile, and I sometimes wonder if we should completely part ways with phx.new and generate everything ourselves. However, the main challenge is that it’s unclear what exactly should be done to add different layers of Phoenix to the existing non-Phoenix project. Last time I was doing that, I invoked mix phx.new my_existing_project in /tmp, then copied that over the existing project, and carefully analyzed git differences, which was far from perfect. Moreover, once such generator is built, I fear that upgrading it to the next Phoenix is going to be much harder.

A comprehensive step-by-step guide explaining how to add Phoenix to existing project to existing project might be of great help here. I’d expect such guide to cover various scenarios, starting with the basic API, and then expanding with HTML, LiveView, and webpack, and of course including recipes for std configuration (e.g. dev-only live reload, debug errors, etc.). Understanding the changes between two Phoenix version could then amount to diffing the guides, which should be easier to comprehend than diff of the generator project.

Other than that, I’m not really sure what kind of support could be offered by the core generators to simplify the kind of changes we’re doing.

tcoopman

tcoopman

I actually love tailwind and I appreciate your opinion on tailwind, but I don’t see how your comment adds any value to the question above.

To the question, I don’t think tailwind should be the default. I would like it, but I think it’s too opinionated to be a default.
As an extra option, I’m not sure either, it’s an extra option to support.

Would it be possible to extend the mix task as a separate package so that the support burden doesn’t fall on the Phoenix team?

11
Post #3

Where Next?

Popular in Discussions Top

matthias_toepp
I’d love to hear what people think about Wisp, the new Gleam web framework started by Gleam’s primary creator Louis Pilfold. Gleam, alon...
New
mikl
I wanted to capitalize a string, and tried using String.capitalize(). That generally works well, until you try to capitalize a word like...
New
cvkmohan
The upcoming Phoenix 1.6 release looks very interesting. Became a habit to watch the commits - and - what they are bringing in. phx.gen...
New
laiboonh
Hi all, I am trying to convince my team to use liveview over the current react. What are some of the points where one should consider us...
New
AstonJ
Are there any Elixir or Erlang libraries that help with this? I’ve been thinking how streaming services like twitch have exploded recentl...
New
Crowdhailer
I’ve been hearing much about the new formatter and it’s something I have been keen to try. I find examples buy far the most illuminating...
248 19204 150
New
AstonJ
I’ve just started the Phoenix part of the utterly brilliant online course by @pragdave. On generating the Phoenix app he uses the --no-ec...
New
shishini
I think this twitter post and youtube video didn’t get as much attention as I hoped I am still new to Elixir, so can’t really judge ...
New
PragTob
Hey everyone, this has been on my mind for some time and I’d love your input on it! TLDR: I feel like maps are superioer for storing and...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

Other popular topics Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

We're in Beta

About us Mission Statement