Apologies for misleading you with a vague title, but I wouldn't call this approach the new way, because under the hood webpacker
and sass-rails
were doing all of the bundlings without us needing to tinker with the configuration. For simpler applications, this was rock solid, but for complex applications, webpacker
kind of stood in the way. But all is good now since the advent of two gems jsbundling-rails
and cssbundling-rails
.
So let's see what these gems have to offer. We'll start with a bare-bone version of rails without any JavaScript.
rails new myapp --skip-javascript
After initializing the rails app, go to the Gemfile and add these two gems that we'll be using.
gem 'jsbundling-rails'
gem 'cssbundling-rails'
Run bundle install
after that.
In this demo, we'll be using webpack
and tailwindcss
as the example.
./bin/rails javascript:install:webpack
./bin/rails css:install:tailwind
These generators should create a Procfile.dev
, webpack.config.js
, and more. Go to the app/javascript/application.js
and write some JavaScript code. Now run ./bin/dev
and with any luck, your JavaScript and CSS should be bundled and compiled into app/assets/builds
directory into two files, namely: application.css
and application.js
. This is so much better because now we can use
<%= stylesheet_link_tag "application", "data-turbo-track": "reload", media: "all" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
into our layouts/application.html.erb
file.
Having webpack.config.js
in our root directory is even better. It's all plain vanilla webpack
without any fancy wrappers around it and hence we can customize it to our hearts.
However, the above-mentioned approach to using tailwind
in our app is limited. For example, we cannot use @layer
or any other fancy tailwind
syntax because it depends on postcss
and other jazz. Again, for simpler applications it's fine, but a complex one may need those syntaxes and may need to write scss
instead of css
alone.
Although we can revert the changes that we made above easily, for ease of understanding let's spin up a new rails app instead.
rails new myapp2 --skip-javascript
This time we'll only be installing the jsbundling-rails
gem.
./bin/rails javascript:install:webpack
As usual, the generator will create the Procfile.dev
, webpack.config.js
, and more.
So in this approach to installing TailwindCSS, we'll be installing postcss
and its plugins to handle all situations.
yarn add tailwindcss autoprefixer css-loader mini-css-extract-plugin postcss postcss-import postcss-loader
That was quite a lot. But you can add or remove these libraries depending on your application's need.
Our approach will be the same. We'll output two files, namely: application.css
and application.js
in the app/assets/builds
directory so that we can use the stylesheet_link_tag
and javascript_include_tag
in our layout/application.html.erb
file.
Go to the app/assets/stylesheets/application.css
and rename this file to application.scss
, and also paste the following lines of code.
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
Let's configure our webpack.config.js
const path = require('path')
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
mode: 'production',
entry: {
application: [
'./app/javascript/application.js',
'./app/assets/stylesheets/application.scss',
],
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'app/assets/builds'),
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
],
}
As you can see, we have defined two entry points inside the application
array. If you have separate assets for your admin page or a marketing page, you can define another array of entry points and webpack
will spit out the compiled assets into separate files.
Also, take note of the plugins
array. The MiniCssExtractPlugin
is responsible for compiling the stylesheet and then spitting it out into the defined directory.
Now the final piece of the puzzle is to configure postcss
and manifest.js
. Create a file called postcss.config.js
in the root of the project directory and write down the following lines.
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
],
}
// app/assets/config/manifest.js
//= link_tree ../images
//= link_tree ../builds
Now run ./bin/dev
and check the app/assets/builds
directory for your compiled assets. It wasn't that hard, was it.
I'm excited about where rails is heading to. We started with hotwire
and now we have new asset bundling options. I wonder what's next. Now is the time to hop into the rails ecosystem if you haven't already.
Cover picture: https://unsplash.com/photos/cvBBO4PzWPg
Top comments (2)
If you like a faster development experience that doesn't require reloading the page after each change, you can try Vite Rails.
Vite uses esbuild and rollup, making it extremely fast in development, and very efficient in production.
I'd be curious to see how TailwindCSS is implemented in Rails with esbuild only.