There are many articles online on integrating Tailwind into Next.js/Nuxt.js, but there are only a few ones for Sapper.
Most of them are:
- outdated,
- very complicated,
- doesn't allow to use of all features of TailwindCSS, like
@apply
.
Some of them are making the development flow a real nightmareβfor example, 30 secs of hot module reloading time. π΅
I spent hours figuring out the best way to integrate it into Sapper, so you don't need to.
This tutorial assumes you are familiar with the terms and commands I will use. I'm not going into deep details about them to keep this article short and simple (and concise).
Initial Sapper setup
Create an initial clone of the official sapper template - rollup version.
npx degit "sveltejs/sapper-template#rollup" sapper-tailwind && cd sapper-tailwind
It will create a directory named sapper-tailwind
with a basic Sapper configuration.
Typescript (optional)
If you would like to use Typescript, execute the following command before you do anything. Otherwise, your changes could be lost.
node scripts/setupTypeScript.js
This is totally optional if you are not sure that you need Typescript or not, you probably not! (Don't follow the hype!)
Add the required packages
yarn add -D cssnano npm-run-all postcss postcss-cli \
postcss-import postcss-load-config postcss-preset-env \
svelte-preprocess tailwindcss
cssnano
to make the production CSS as small as possible.
npm-run-all
to run package.json scripts in parallel or sequential - you will see why.
postcss*
packages, obviously for PostCSS.
svelte-preprocess
to preprocess other languages like Typescript or SCSS. It also helps svelte-vscode extension to understand your code before preprocessing in VSCode.
tailwindcss
- no idea why it's needed π.
Configure tailwind
This will create a tailwind.config.js
in your root directory:
npx tailwind init
We need to tweak the default configuration to look like this:
module.exports = {
future: {},
purge: {
mode: 'all',
content: ['./src/**/*.svelte', './src/**/*.html'],
},
theme: {
extend: {},
},
variants: {},
plugins: [],
}
Allowing purge helps us to remove all the unnecessary CSS classes from the production bundle. That is what you definitely needed because Tailwind with all the classes and stuffs is heavy (~1.4MB).
Create Svelte configuration
Drop the following content to svelte.config.js
in the root directory:
import autoProcess from 'svelte-preprocess';
export const preprocess = autoProcess({ postcss: true });
This will allow you to use many syntax sugar languages in Svelte and tell VSCode how to process that much sugar.
Modify Rollup configuration
We need to add the preprocess method to our rollup configuration. Otherwise, rollup won't know what to do.
Rollup.config.js` has a default export, which consists of 3 sections:
- Client
- Server
- Service worker
Each has its own plugin configuration. We need to add preprocess to our client
& server
section, exactly to the svelte
plugin part:
import { preprocess } from './svelte.config';
// client
svelte({
dev,
hydratable: true,
emitCss: true,
_preprocess_
})
// server
svelte({
generate: 'ssr',
hydratable: true,
dev,
_preprocess_
}),
Create PostCSS config
Add a postcss.config.js
file to the root directory:
const tailwind = require('tailwindcss');
const cssnano = require('cssnano');
const postcssImport = require('postcss-import');
const presetEnv = require('postcss-preset-env')({
features: {
'nesting-rules': true, // Optional, not necessary. Read details about it [here](https://tabatkins.github.io/specs/css-nesting/#motivation)
},
});
const plugins =
process.env.NODE_ENV === 'production'
? [postcssImport, tailwind, presetEnv, cssnano]
: [postcssImport, tailwind, presetEnv];
module.exports = { plugins };
Modify package.json
Add the following scripts to package.json
file:
"scripts": {
"watch:css": "postcss src/assets/global.pcss -o static/global.css -w",
"watch:dev": "sapper dev",
"dev": "run-p watch:*",
"build": "run-s build:css build:sapper",
"build:css": "NODE_ENV=production postcss src/assets/global.pcss -o static/global.css",
"build:sapper": "sapper build",
"build:export": "sapper export",
"export": "run-s build:css build:export",
"start": "node __sapper__/build",
"serve": "serve ___sapper__/export"
},
Don't worry. You do not need to use all of them.
- To develop, use
yarn dev
to preprocess TailwindCSS in watch mode (watch:css
script) and start sapper development (watch:dev
). - To build,
yarn build
, which also preprocess tailwind, but inproduction
mode, it eliminates unused classes + minify the final CSS files. Also builds application related files. - To start production SSR,
yarn start
- simple.
Note: I removed the
--legacy
flags from the build commands because I have no good argument to support old browsers.
Import Tailwind into your application
Create the following directory src/assets/
and place a PostCSS file (global.pcss
for example) which imports Tailwind configurations:
// src/assets/global.pcss
@tailwind base;
@tailwind components;
@tailwind utilities;
We are done! π
Conclusion
It was a wacky ride. You persisted to the end. I'm proud of you. π
You deserve the full code in a repository.
If you are interested in my journey, be sure to follow me on Twitter or here.
Cover photo by Aron Visuals on Unsplash