Middleman + TailwindCSS + Webpack
Tags: middlemanapp, tailwindcss, webpack, css
Published: 2019-07-02 16:27:26


I really enjoy using [Middleman](https://middlemanapp.com/) for some websites that I maintain. For one of my projects I wanted to include [TailwindCSS](https://tailwindcss.com/) and started googling how to do that. I found [this guide](https://vcavallo.github.io/css/static_site_generator/how_to/2017/12/06/setting-up-middleman-with-tailwind-css.html) but it seemed bit outdated.

This got me inspired to write an updated version.

So, in this guide I'm trying to describe how I managed setting up a middleman project and integrate TailwindCSS using Webpack.

It uses these versions:

* Middleman `4.3.4`
* Tailwind `1.0.4`
* Webpack `4.35.2`

**Disclaimer**: *I am not an expert with Webpack etc*. So the following instructions may be inaccurate, incomplete or misleading. I hope it's not too bad though, please comment if you feel something is terribly wrong.

Here we go...

## Setup a Middleman project

Firstly, install Middleman and create a project

```shell
gem install middleman
middleman init project
cd ./project
middleman serve
```

Once `middleman serve` is running you should see a default page on `http://localhost:4567`. You may abort the process again since we're going to change some configurations now...

Also, from now on this guide assumes that the working directory is the project's root directory.

(These instructions were taken from the [Middleman installation page](https://middlemanapp.com/basics/install/))

### Add Livereload (Optional)

Livereload automatically reloads the page in the browser every time we change something in the code, which can be useful later.

1. Add `gem 'middleman-livereload'` to `./Gemfile`
2. Add `activate :livereload` to `./config.rb`
3. Run `bundle install`

(These instructions were taken from the [Middleman Basics page](https://middlemanapp.com/basics/development-cycle/#livereload))

## Add npm packages

Now we get to the first part where I don't have much knowledge about. After some experimenting I concluded this list of packages

```shell
yarn init
yarn add autoprefixer css-loader mini-css-extract-plugin postcss postcss-import postcss-loader style-loader tailwindcss webpack webpack-cli
```

(You may substitute `yarn` with `npm`. Use `npm install` instead of `yarn add`)

## Prepare CSS file

Middleman comes with SCSS, but I decided to not use SCSS together with Tailwind. That's why I renamed the stylesheet's filename:

```shell
mv ./source/stylesheets/site.css.scss ./source/stylesheets/site.css
```

Then I changed the content of `./source/stylesheets/site.css` to this:

```css
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

body {
  @apply bg-red-500;
}
```

This imports the Tailwind definitions and applies a rule to the `body` tag using Tailwind's `@apply` directive. At the end of this guide we expect the background color of the page to be red(-ish).

(This instruction was taken from the [Tailwind's installation page](https://tailwindcss.com/docs/installation#2-add-tailwind-to-your-css))

## Create `postcss.config.js`

Next we're going to create a file `./postcss.config.js` with this content:

```js
module.exports = {
  plugins: [
    require('postcss-import'),
    require('tailwindcss'),
    require('autoprefixer'),
  ]
}
```

(This instruction was taken from the [Tailwind's installation page](https://tailwindcss.com/docs/installation#using-tailwind-with-postcss))

## Configure webpack

To me, configuring webpack was the most difficult part. There are a lot of examples for this on the interwebs and as a JS-noob I couldn't make clear which way is the best. But here's what I came up with.

Create a file `./webpack.config.js` with this content:

```js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new MiniCssExtractPlugin()
  ],
  entry: {
    application: './source/javascripts/site.js',
    styles: './source/stylesheets/site.css',
  },
  output: {
    path: __dirname + '/.tmp/dist',
    filename: '[name].js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              hmr: process.env.NODE_ENV === 'development',
            },
          },
          'css-loader',
          'postcss-loader',
        ]
      }
    ]
  }
}
```

While I created this file I made several observations that I'd like to share:

* The keys in `entry: { ... }` (`application` and `styles`) will be used as filenames. So there will be a file named `application.js` and one named `styles.js` (yes... the styles file's extension is going to be `.js`, I guess it won't be used though, may be I can get rid of it somehow?)
* `output.path` apparently has to be `/.tmp/dist` (!), otherwise Middleman won't use it in development?
* Lastly, the rule for `.css` files is more or less copy/pasted from `MiniCssExtractPlugin` [project page](https://github.com/webpack-contrib/mini-css-extract-plugin#minimal-example). I assume this plugin is responsible for processing/creating a `styles.css` file in the output path? Note that this plugin replaces a plugin named `extract-text-webpack-plugin`.

You see, in this area I have multiple question marks. So if you have corrections, I invite you to post them in the comments.

## Activate Webpack as `:external_pipeline`

Now let's hook up webpack to the Middleman pipeline.

Add these lines to `./config.rb`

```ruby
activate :external_pipeline,
  name: :webpack,
  command: build? ? './node_modules/webpack/bin/webpack.js --bail' : './node_modules/webpack/bin/webpack.js --watch -d --color',
  source: ".tmp/dist",
  latency: 1
```

This ensures that webpack runs as soon as anything changes in the project during development or when we build the project.

(This instruction was taken from the [Middleman Documentation](https://middlemanapp.com/advanced/external-pipeline/#webpack-example))

## Change stylesheet and javascript paths in `./source/layouts/layout.erb`

Remember that we configured webpack so we get a file named `application.js` and one named `styles.css` as outputs? We need to change these filenames in the `head` section of the page.

In `./source/layouts/layout.rb` change

```erb
<%= stylesheet_link_tag "site" %>
<%= javascript_include_tag "site" %>
```

to

```erb
<%= stylesheet_link_tag "styles" %>
<%= javascript_include_tag "application" %>
```


## Moment of truth...

Run

```shell
middleman serve
```

Check whether the background of the page at `http://localhost:4567` is red(-ish). If so, this guide is trustworthy and you can happily start using Tailwind in your project. If not, put the blame on me and share your experience.

![](https://thepracticaldev.s3.amazonaws.com/i/o5age2s4t98nm5ljic6c.png)

## Credits

[Cover image](https://www.flickr.com/photos/30478819@N08/46074804494) by Marco Verch