Skip to content

Tailwind.config.js with asset pipeline #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jasonlor opened this issue Feb 26, 2021 · 13 comments
Closed

Tailwind.config.js with asset pipeline #50

jasonlor opened this issue Feb 26, 2021 · 13 comments

Comments

@jasonlor
Copy link

jasonlor commented Feb 26, 2021

Thanks for providing this gem.

I can't seem to find documentation on how to customize Tailwind when using the asset pipeline.
I have a tailwind.config.js file in my rails root directory. Do I need to move the file to assets/javascripts/?

What's the proper way to do this?

@DaveSanders
Copy link

Searching the closed issues, I think the answer right now is: "you can't". #6

I'm thinking about setting up a separate project where I just run postcss to customize and output a production ready Tailwind that I can then just vendor into my project. In my experience so far, once it's "set" I don't usually mess with the tailwind config much - my palette and fonts are generally not being changed frequently. So to keep webpack complexity out of my rails project it might be better to just compile it separately.

Downside of this approach would mean that I wouldn't get the purging of the CSS for what I don't need to use - unless I create some sort of link between the project that compiles Tailwind and the rails project. Ugh.

For my case I might just use this gem and then just have to override certain tailwind tags to customize them.

I get why Tailwind built their framework this way, but it's a lot tougher to use than, say, Bootstrap.

@jonathanhefner
Copy link
Member

It is true that the asset pipeline does not support customizing via tailwind.config.js, but there are proposals for alternative ways to customize Tailwind: #14 and #49.

What kind of customizations would you like to see?

@jasonlor
Copy link
Author

jasonlor commented Mar 3, 2021

I'm looking to customize spacing, colors and plugins. I'm implementing a design with a different grid increments.

With webpacker I used the forms and typography plugins. So support for that would also be great.

@DaveSanders
Copy link

@jonathanhefner I think for me its mostly custom color palette and fonts right now. But I'm not a tailwindcss power user and tend to just roll my own stuff when I have something I need done in a pinch.

My concern in general about the approach of this gem, and those ideas in #14 and #49 is that it feels like it could become a big ball of duct tape, and might make future compatibilities harder and harder to maintain. I'd rather see a methodology that uses what the Tailwind team produces in the way they intended.

Really, I'd like to see Tailwind have ways to build their library without being so tied to the node / js world, but that's not fair to ask either. IMO, its an incredibly useful approach to design but wrapped in unrelated and complicated tech. And I worry about doing hacky things to get it to work in a webpack free rails environment. I think I'd rather have a "Tailwind compatible" framework that is built using ruby tech from the ground up...

I think I'm settled now on not using this gem and setting up an outside of rails build process for my CSS, so I can do it the "tailwind way". But I hope it comes together!

@jasonlor
Copy link
Author

jasonlor commented Mar 4, 2021

For my use case, the draw of this gem is to avoid all of the additional JS packages for babel transpiling/loading SCSS.
I am still using webpacker for javascript since I'm using Hotwire.

It would be great to see an approach that leverages these instructions:
https://tailwindcss.com/docs/installation#using-tailwind-without-post-css

Maybe something that:

  • Add tailwindcss-cli as a devDependency
  • Leverage the existing tailwind.config.js
  • taiwindcss-cli dumps out to the stylesheets directory
  • Maintains the existing purger compressor that was built in this gem.

This might simplify custom work and just leverage what already works.

@viktorshamal
Copy link

viktorshamal commented Mar 24, 2021

I followed your formula here @jasonlor and it ended up being quite easy to get a fully configurable tailwind.config.js to work.
I just had to register my own version of the compressor that looks for a custom tailwind.css instead.

This seems to function identically to using the built in stylesheet, and I have it running on Heroku currently. You still end up using node, but you can avoid adding webpacker just to be able to change the config. You have to run the build script everytime you change it though.

Steps:

  • Add the following line to assets.rb:
    Sprockets.register_compressor "text/css", :custom_purger, Tailwindcss::Compressor.new({ only_purge: %w[tailwind_custom] })

  • Create a package.json with tailwindcss-cli, plugins and build script:

{
  "scripts": {
    "tailwindcss:build": "tailwindcss-cli build ./app/assets/tailwind/tailwind_custom_base.css -o ./app/assets/stylesheets/tailwind_custom.css"
  },
  "devDependencies": {
    "@tailwindcss/forms": "^0.2.1",
    "tailwindcss-cli": "^0.1.2"
  }
}
  • npm i / yarn add
  • Create a tailwind.config.js file:
module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {
    },
  },
  variants: {
    extend: {},
  },
  plugins: [require('@tailwindcss/forms')],
}
  • Create the file /app/assets/tailwind/tailwind_custom_base.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind forms;

/* You can use apply here!*/
.btn {
  @apply px-4 py-2 bg-blue-600 hover:bg-blue-400 text-white rounded cursor-pointer;
}
  • Run npm run tailwindcss:build. The configured tailwind.css will output to /app/assets/stylesheets/tailwind_custom.css
  • Change your stylesheet tag to <%= stylesheet_link_tag "tailwind_custom" %>
  • Change your compressor in config/environments/production.rb
    config.assets.css_compressor = :custom_purger
  • Voila!

@jeromecornet
Copy link

With the new JIT mode, it's fast enough to use with the assets pipeline, so I was inspired by the comments above, and wrote a hacky Sprockets compressor which runs tailwindcss-cli with an ERB-able config (so you can purge in production but not in dev)

https://gist.github.com/jeromecornet/93f04cc8358dcf3a96750615062bfc70

This requires node (to run tailwindcss-cli) but it's much lighter weight than webpacker, yet allows you to use all the tailwind directives in your CSS (like @apply) throughout the app.

And you don't have to think about running the command manually.

@tleish
Copy link

tleish commented Apr 15, 2021

so you can purge in production but not in dev

@jeromecornet - Can you explain a bit more about this comment?

@jeromecornet
Copy link

When in development, I like to keep all the styles from tailwind in the CSS so that I can manually add styles in the DOM to evaluate their effect. But in production, I want to be able to purge the styles that are not used to keep the CSS as small as possible.

rails/tailwindcss-rails comes with a purger that is independent of tailwindcss https://github.com/rails/tailwindcss-rails/blob/1777975578b66c49ade77c088e0641dc6a5528d8/lib/tailwindcss/purger.rb, but the regular tailwindcss allows you to configure a purger (in tailwind.config.js).

By running the config file through ERB, I can turn on or off the purger configuration based on the environment (https://gist.github.com/jeromecornet/93f04cc8358dcf3a96750615062bfc70#file-tailwind-config-js-erb-L5 ), so in production the generated css has been purged of all the unused styles but in dev all the styles are still there.

I hope this makes sense

@viktorshamal
Copy link

This is great! I didn't know about the Tailwind JIT mode, but it really simplifies the process a lot.

@travisp
Copy link

travisp commented Apr 25, 2021

I spent some time looking at the approach suggested by jeromecornet, and was able to initially seemingly get it to work, as long as the css_compressor was set in assets.rb and not in a separate initializer (something about this seemed to mess with the list of precompiled files).

However, I'm not sure I fully understand the solution unless I'm missing something. JIT mode is enabled, but as far as I can tell, JIT mode isn't truly being used -- the cli build is just being called every time a stylesheet changes. As a result, there's no general "watcher" and the tailwind css is not updated if a previously unseen class is added to one of the view files. It's not true JIT mode as far as I can tell, it just calls a one-off build (with JIT settings) every time a stylesheet (but not HTML) changes.

If tailwindcss is going to be used with jit, then somehow the build needs to be updated when the views change as well. I'm not sure using JIT is possible currently without using webpacker

@inopinatus
Copy link

Ultimately, it's always been a PostCSS plugin, and the introduction of the JIT compiler drives that home. Not only because there's little/nothing to purge, but also because stackable variants and parametric utilities can't be statically distributed.

However, we don't need Webpack to run Tailwind; we can invoke it with postcss-cli too. Note that autoprefixer-rails is already a sprockets wrapper for invoking PostCSS; perhaps that may be adaptable.

@dhh
Copy link
Member

dhh commented Aug 18, 2021

No plans at this time to rely on a node setup. This gem is aimed at working in a node-less environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants