Rails 6: How to install css-bundling with Tailwind JIT
Tags: rails, tailwindcss, tutorial, programming
Published: 2021-10-07 15:37:22

This tutorial explores how to install [cssbundling-rails](https://github.com/rails/cssbundling-rails) gem into existing rails applications with Webpacker.

- From a rails 6 app with legacy tailwindcss installed through Webpacker and a `postcss.config.js` file 
- To the new `cssbundling-rails` gem and Tailwind JIT.

1. [Install gem](#1-install-gem) 
2. [Migrate config file](#2-migrate-config-file)
3. [Migrate custom classes](#3-migrate-custom-classes)
4. [Remove stylesheet_pack_tag](#4-remove-stylesheetpacktag)
5. [Remove or keep postcss file](#5-remove-or-keep-postcss-file)
6. [Run the server with bin/dev](#6-run-the-server-with-bindev)
7. [Github Actions](#7-github-actions)
8. [Heroku](#8-heroku)


In case you haven't heard about Tailwind JIT yet...

Tailwind JIT makes the development experience magnitudes faster. Only classes that are used in the application folder remain. Tailwind classes that you do not use are purged (removed) from your `application.css` file, significantly reducing the CSS file size and speeding up re-compiling CSS.

## 1. Install gem

Depending on how you initially installed tailwind, remove the original installed gem or package (`tailwindcss`).

- Add the gem to gemfile:
```rb
gem 'cssbundling-rails'
```

- Run in the terminal:
```bash
bundle install
rails css:install:tailwind
```

The `install:tailwind` command will do most of the heavy lifting of the migration:
- a `/builds` folder with an `application.css` where all your tailwindcss will compile
- a tailwind.config.js file in the root of the project

## 2. Migrate config file

Migrate the content from the legacy __tailwind.config.js__ file inside the `app/javascript/stylesheets` folder to the newly created `tailwind.config.js` file at the app's top level. Make sure to active __jit__ by adding in `mode: 'jit'`. After migrating the file's content, delete the original file.

```js
// old
module.exports = {
  purge: [
    './app/**/*.html.erb',
    './app/helpers/**/*.rb',
    './app/javascript/**/*.js'
  ],
  variants: {
    extend: {
      opacity: ['disabled'],
    }
  },
  plugins: [
    require('@tailwindcss/forms'),
    require('@tailwindcss/typography'),
    require('@tailwindcss/aspect-ratio'),
  ]
}
```

```js
// new
module.exports = {
  mode: 'jit',
  purge: [
    './app/views/**/*.html.erb',
    './app/helpers/**/*.rb',
    './app/javascript/**/*.js'
  ],
  plugins: [
    require('@tailwindcss/forms'),
    require('@tailwindcss/typography'),
    require('@tailwindcss/aspect-ratio'),
  ]
}
```

When using Tailwind JIT, variants are redundant. Just-in-time compiling enables us to create classes on the fly. You can delete custom variants completely. Read more about this cool JIT feature [here](https://tailwindcss.com/docs/just-in-time-mode).

##  3. Migrate custom classes

- Import Tailwind in `app/assets/stylesheets/application.tailwind.css`.
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
- Migrate the remaining content (any scss. or .css file) of the `javascript/stylesheets` folder to into the asset pipeline (`app/assets/stylesheets`).

After migrating, remove the stylesheets folder in `app/javascript`

## 4. Remove stylesheet_pack_tag

Webpacker refers to the location of a stylesheet using a `stylesheet_pack_tag`. As tailwindcss moves into the asset pipeline (`app/assets/...`), the stylesheet_pack_tag is no longer needed.

In your `application.html.erb` file (or any other layouts you render), remove the `stylesheet_pack_tag`. Note that the gem's install process automatically inserts the new stylesheet_link_tag refering to the asset pipeline.

```erb
<%# old %>
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbo-track': 'reload' %>

<%# new - automatically insert by cssbundling gem %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
```

## 5. Remove or keep postcss file

You have 2 options here.
1. To use Tailwind without importing any relative files. Remove the `postcss.config.js` file at the root of your project. This is the most simple set-up.
2. To import relative files into Tailwind with the __@import__ directive an additional package `import-css` is needed. Read [Import Class in Relative File into Tailwind CSS and Rails](
https://dev.to/thomasvanholder/extract-class-in-relative-file-with-rails-and-tailwind-css-50ii) for details on how to set it up.

## 6. Run the server with bin/dev

An important point. To benefit from Tailwind JIT's auto-recompiling, you need to have an additional watch process running. You can run a `rails server` in one terminal tab and `yarn build:css --watch` in another. 

Or you can take full use of your appended `Procfile.dev`, which allows us to run both watch processes with a single command. Run `./bin/dev` instead of `./bin/rails server`.

## 7. Github Actions
If you use Github Actions as a  CI/CD make sure to add in an additional build step. The `application.tailwind.css file` needs to be bundled before running the tests in your workflow file.

```yml
- name: Build TailwindCSS
  run: yarn build:css
```

## 8. Heroku

If you use heroku to deploy your application, Heroku will [automatically](https://devcenter.heroku.com/changelog-items/1557) pick up the additional build process __build:css__ from your package.json file. 

Thanks for reading.

Questions, feedback? Let me know.