Maybe Tailwind is the best thing since sliced bread, maybe it's just the newest hype. But one thing I can say for sure is that even a design-illiterate like me can create things that look (kind of) good. So naturally I'm interested to integrate it into my workflow with Structr.
The basics are explained quite well in the basic installation guide but it took me quite a while to get it production-ready which is why I'm writing this short tutorial.
Setup & Development Build
For our development system with stock TailwindCSS everything is done in a few simple steps. The build customized for production takes a bit more effort but is also quite easy. Let's start with the dev build.
Step 1: Create a directory structure for our project
mkdir tailwind-structr
cd tailwind-structr
mkdir src
mkdir dist
Step 2: Initialize an npm project with the default configuration file
npm init -y
Step 3: Install TailwindCSS with its dependencies
npm install -D tailwindcss@latest postcss@latest postcss-cli@latest autoprefixer@latest
Step 4: Init TailwindCSS with PurgeCSS and create default configuration files tailwind.config.js
and postcss.config.js
npx tailwindcss init -p
Step 5: Create default main.css
. This is where we could add custom classes to our build later.
@tailwind base;
@tailwind components;
@tailwind utilities;
Step 6: Add the development build script to package.json
...
"scripts": {
"build:dev": "postcss main.css -o ./dist/tailwind.css"
},
...
Now we have everything set up to get started. Without any customizations we build our development version of TailwindCSS using the default configuration.
npm run build:dev
This yields the complete TailwindCSS file with all classes.
kai@Kais-iMac ~/Documents/tailwind-structr $ ll dist/
total 7672
-rw-r--r-- 1 kai staff 3924381 23 Feb 20:13 tailwind.css
We can add this to our Structr development system and start developing with the full feature set of TailwindCSS.
Optional: Forms & Typography
To make things a bit more interesting, we want to use TailwindCSS to style forms and render user-generated content in our project. TailwindCSS offers a forms plugin that provides a basic reset for form styles and also offers a tyography plugin which adds typographic defaults to any vanilla HTML. We also want to be able to style some properties and the mouse cursor on disabled elements.
npm install -D @tailwindcss/forms @tailwindcss/typography
We add the plugins to our tailwind.config.js
, add our extensions to the variants …
module.exports = {
purge: [],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {
cursor: ['disabled'],
opacity: ['disabled'],
backgroundColor: ['disabled'],
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography')
]
}
… and build again.
npm run build:dev
kai@Kais-iMac ~/Documents/tailwind-structr $ ll dist/
total 7944
-rw-r--r-- 1 kai staff 4064568 23 Feb 20:18 tailwind.css
Production Build
After our first development cycle we want to deploy our application to a production environment but the default TailwindCSS file size of almost 4 MB is a bit heavy, so we want to purge the unused classes. To do this we need to export our Structr app to the tailwind-structr/src/webapp
folder. (For example's sake the REST call is used - it is a lot easier using the Dashboard section in Structr itself)
let config = {
"mode": "export",
"target": "/Users/kai/Documents/tailwind-structr/src/webapp"
};
fetch("http://localhost:8082/structr/rest/maintenance/deploy", {
"headers": {
"x-user": "admin",
"x-password": "admin"
},
"body": JSON.stringify(config),
"method": "POST"
});
Then we add the purge
configuration to tailwind.config.js
to purge all unused classes (see the documentation about purgeable HTML).
module.exports = {
purge: {
enabled: (process.env.NODE_ENV === 'production'),
content: ['./src/webapp/**/*.html']
},
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {
cursor: ['disabled'],
opacity: ['disabled'],
backgroundColor: ['disabled'],
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography')
]
}
This tells PurgeCSS to scan all HTML files in all subdirectories of ./src/webapp
and look for used classes. All unused classes will be removed from the CSS file. We only want this to run in production
builds, which is why we add a build:prod
script to our package.json
...
"scripts": {
"build:dev": "postcss main.css -o ./dist/tailwind.css",
"build:prod": "postcss main.css -o ./dist/tailwind.min.css --env production"
},
...
Then we run our production build script …
npm run build:prod
… which leaves us with a significantly smaller file size (around 40 KB with this project).
kai@Kais-iMac ~/Documents/tailwind-structr $ ll dist/
total 8016
-rw-r--r-- 1 kai staff 4064568 23 Feb 20:18 tailwind.css
-rw-r--r-- 1 kai staff 36461 23 Feb 20:27 tailwind.min.css
But we still want more - we want the file to be minified! For this we install cssnano
…
npm install -D cssnano
… and customize postcss.config.js
to only enable minification in production builds.
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
cssnano: ((process.env.NODE_ENV === 'production') ? { preset: "default" } : false)
},
}
We run our build script one last time…
npm run build:prod
… and get a purged and minified CSS file which is ready for production. The file size in this project went from close to 4 MB down to around 23 KB.
kai@Kais-iMac ~/Documents/tailwind-structr $ ll dist/
total 7992
-rw-r--r-- 1 kai staff 4064568 23 Feb 20:18 tailwind.css
-rw-r--r-- 1 kai staff 23332 23 Feb 20:29 tailwind.min.css
The final version of this setup can be found in this GitHub repository. It contains everything except the Structr project. Simply run npm install
to install the dependencies and try it out with your own project!