Adding Tailwind to Electron

This post was originally published in the thoughtbot blog, Giant Robots Smashing Into Other Giant Robots.

Tailwind CSS is a utility first CSS framework in which developers focus on writing inline styles compared to traditional CSS stylesheets. An Honest Look at Tailwind as an API for CSS is an excellent post that explains more about Tailwind.

How do we add Tailwind CSS to an Electron JS project? The purpose of this guide is to add Tailwind to Electron JS and optimise the same for production.

Electron React boilerplate

This article will use the Electron React boilerplate. If we are not using a React based Electron setup, then this article might not be relevant to the reader.

Ensure that Node JS is installed, and then clone the Electron React boilerplate as per the official installation guide. Let us call our project tailwind-react.

git clone --depth 1 --branch main https://github.com/electron-react-boilerplate/electron-react-boilerplate.git tailwind-react
cd tailwind-react
npm install

As per this guide, we will use npm as our package manager. Please refer to npm migration if you prefer to use yarn instead.

Run Electron

npm start

The above command will launch the Electron React app in debug mode. This should open the default "Hello Electron React!" launch screen.

The Electron React boilerplate comes pre-installed with react-router, the standard router for React-based applications. Let us edit src/renderer/App.tsx to simplify the default route.

  • Delete the default App.css stylesheet as we will be integrating Tailwind soon.
  • Remove unused App.css imports
  • Change the JSX that's returned by the Hello component to something like below:
    <div>
      <h1>Hello Tailwind</h1>
    </div>

The Electron app should now display "Hello Tailwind" without any styling.

Install Tailwind

Let us add tailwindcss and associated dependencies to our project. We will use Tailwind CSS v2.2.19 for this tutorial as v3 was recently released.

npm install tailwindcss@2.2.19 postcss-loader autoprefixer postcss --save-dev

Notice how all the installed libraries are devDependencies. This is how Tailwind works, generating required CSS at build time.

Tailwind CSS works by scanning all of your HTML files, JavaScript components, and any other templates for class names, generating the corresponding styles and then writing them to a static CSS file.

Set up Tailwind

Tailwind webpack configuration

Open the file .erb/configs/webpack.config.renderer.dev.ts where we set up rules for generating the styles using the installed plugins.

Scroll down to find the module object which contains the list of rules. Our goal is to modify all the test (2 by default) rules. Along with the existing style-loader, css-loader and sass-loader, we want to add a new postcss-loader to the use array. We will specify the Post CSS configuration after this step.

  module: {
    rules: [
      {
        test: /\.s?css$/,
          use: [
            ...
            'postcss-loader',

        ]
      }
    ]
  }

PostCSS configuration

Post CSS with an excellent plugin ecosystem is a tool for transforming CSS using JavaScript. Let's add some configuration in a file called postcss.config.js at the root of the project and make sure we include tailwindcss and autoprefixer plugins as per the code below:

/* eslint global-require: off, import/no-extraneous-dependencies: off */

module.exports = {
  plugins: [require('tailwindcss'), require('autoprefixer')],
};

Based on my ES lint configuration, the first line was required but might not be necessary for you.

Tailwind configuration

Create a tailwind.config.js file at the root of the project and add an empty configuration as shown below:

module.exports = {
  theme: {},
  variants: {},
  plugins: [],
};

This config object will be extended in the project eventually to contain our app's themes such as fonts, colors, and other styling goodness.

Add default Tailwind directives

Remember how we deleted the default App.css? Now would be a good time to bring that back to add the default Tailwind directives.

Resurrect the src/renderer/App.css and add the directives below:

@tailwind base;
@tailwind components;
@tailwind utilities;

Test tailwind

Open src/renderer/App.tsx, and start writing Tailwind classes.

...
import './App.css'
...
  <div className="h-screen flex items-center justify-center bg-gray-200">
      <h1 className="text-blue-500">Hello Tailwind</h1>
  </div>

The Electron app should reflect the Tailwind CSS classes now, and this means we successfully added Tailwind to our project.

Optimise for production

npm run build

While building the production version of our electron app, I noticed that none of the Tailwind CSS styles were applied on production, whereas it worked fine on debug builds. After digging deeper, I found that the generated style.css contained the standard tailwind directives (shown below) instead of actual CSS styles.

@tailwindbase;@tailwind components;@tailwind utilities;

Remember how we modified the webpack configuration earlier? Turns out we only modified it for dev and not production. Repeat the same process to add postcss-loader to all the test rules in .erb/configs/webpack.config.renderer.prod.ts.

The above step solved the style.css problems, which contained actual CSS instead of tailwind directives. The production builds now contain the correct CSS, and the App worked well. But, I was shocked by the size of style.css (3 MB) for a handful of CSS styles. Though this can be excused for an Electron app, surely this size cannot be correct.

module.exports = {
  purge: {
  enabled: true,
  content: ['./src/*/.tsx'],
  }
  ...
}

After adding the above to tailwind.config.js as per docs, the size came down to an acceptable 3 KB. Essentially, we asked Tailwind to go through all the React component code (*.tsx) and generate the most optimised styles based on our usage. The Tailwind docs have a whole section of optimizing for production with more such configuration options.

Conclusion

Congratulations! We added Tailwind to an Electron project and optimised it for production by following this guide. This guide works with the state of the current tooling and releases of Electron, React, and Tailwind CSS. The knowledge of the installation, configuration and customisation of Tailwind with Electron and how they integrate with React to generate the final CSS will hopefully remain the same even with newer releases.