Using Tailwind with Begin.com and Architect(arc.codes) is mostly straightforward with just a few hurdles. The instructions below cover how to use them together for a server rendered scenario. This is not a full introduction to either Tailwind or Begin/Architect so it will be helpful to be familiar with both before reading this post.
TL&DR
The biggest challenge with the integration is building the production vs development CSS and connecting that to the Begin.com or Architect deployment process. Skip to that section if you are already familiar with Tailwind and Begin/Architect separately.
Install Tailwind
Refer to the tailwindcss.com docs for details on this, but once you have a Begin or Architect project setup install tailwind at the root with the following:
# Using npm
npm install tailwindcss
# Using Yarn
yarn add tailwindcss
Inject Tailwind styles
Add the tailwind directives to your CSS stylesheet if you have one. If you are styling the entire app with tailwind create a tailwind.css with the three directives below. Put these styles in the src/styles
directory. They could also live at the root of the project to avoid adding more files to the src folder.
/* /src/styles/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Other global CSS styles here*/
Tailwind Config File
When you install tailwind you create a config file with the following command:
npx tailwindcss init
The important step for Architect and Begin is to point to any src files that contain any tailwind classes so that the production build will not purge any of the classes needed. The example below looks at any javascript, html, and njk(nunjucks template) files for tailwind utility classes.
// tailwind.config.js
module.exports = {
future: {},
purge: ['./src/**/*.js', './src/**/*.njk', './src/**/*.html'],
theme: { extend: {} },
variants: {},
purge: [],
plugins: [],
};
Build CSS for Development vs Production
Tailwind has a development build that is huge (i.e. 3-5mb). It includes everything so that you can add and remove utility classes while developing without rebuilding CSS. When you build the CSS for production it purges everything that it doesn't need to reduce the CSS to a more reasonable kb size. The production build should be regenerated every time you deploy in case any new utility classes need to be included.
Below is the package.json
file that will work for both Begin.com and Architect.
{
"name": "begin-app",
"version": "0.1.0",
"description": "Tailwind example",
"scripts": {
"start": "npm run check-css; npx sandbox",
"build": "npm run build:prod-css",
"staging": "npm run build:prod-css; arc deploy",
"production": "npm run build:prod-css; arc deploy production",
"check-css": "if !(tail -n 1 ./public/css/styles.css | grep 'DEVELOPMENT BUILD'); then npm run build:dev-css; fi;",
"build:dev-css": "NODE_ENV=testing npx tailwindcss build ./src/styles/tailwind.css -o ./public/css/styles.css -c ./tailwind.config.js &&echo '/*DEVELOPMENT BUILD*/' >> ./public/css/styles.css",
"build:prod-css": "NODE_ENV=production npx tailwindcss build ./src/styles/tailwind.css -o ./public/css/styles.css -c ./tailwind.config.js"
},
"devDependencies": {
"@architect/sandbox": "^3.0.5"
},
"dependencies": {
"tailwindcss": "^1.7.5"
}
}
When npm run build:prod-css
is run Tailwind will purge the CSS if NODE_ENV=production
. When the build:dev-css
is run all styles are included. Both these scripts output to the same file ./public/css/styles.css
. There is currently not an easy way to deploy a different asset (i.e. styles.css) depending on what stage you are running which is why both build to the same file. The development script tags the bottom of the output file with a comment /*DEVELOPMENT BUILD*/
. This is used to detect if it needs to be run again to avoid rebuilding the development file every time you launch the local sandbox.
Begin.com CSS Build
Begin.com is a CI/CD service that runs when you commit your changes to your main branch on Github. As part of the deployment process it automatically runs a build
script defined in your package.json
. This is not configurable so you have to use build
. This is the best place to include your production CSS build step. The build
script in the above package.json
calls the build:prod-css
script.
With Begin you don't need to generate your production CSS locally because it is handled on Begin.com. This eliminates overwriting development CSS locally every time you deploy.
Architect (arc.codes) CSS Build
With an Architect project you can deploy to Staging or Production with the commands arc deploy
or arc deploy production
directly from a local environment. It will then use the static assets in your ./public
folder which include your CSS. For this reason you need to generate the production build just prior to running those deploy scripts. That is handled by the staging
and production
script above.
If you are deploying directly from a local environment you will then need to rerun your development build the next time you try to launch the sandbox locally. This can take 10 seconds in my experience so you don't want to do it unless you have to. The check-css
script looks at the last line of the CSS file to see if it is tagged as DEVELOPMENT
before rebuilding.
Fingerprinting of CSS assets
Architect can handle fingerprinting of static assets to help browsers and CDN's properly cache your CSS. Below is the Architect config file for this project. The @static
pragma is what configures the static assets. The folder public
tells Architect which folder you put the assets in. Setting fingerprint true
means that the styles.css file generated will be appended with a hash that is unique for the file contents similar to styles-8ax5rs.css. Architect will also add aggressive caching headers to make sure that if the CSS doesn't change it will be cached as long as possible.
app.arc
@app
link-pages
@static
fingerprint true
folder public
Pointing to CSS from HTML
Especially with fingerprinting, but even without it you need a way to point to the correct place for your static assets. Architect provides a helper function to make this easier. Below is a sample lambda file that serves HTML. This includes the CSS in the header using the arc.static('css/styles.css')
helper to point to the correct path and the fingerprinted filename for the CSS.
const arc = require("@architect/functions");
async function page(req) {
return {
status:200,
body: `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet"
href="${arc.static('css/styles.css')}">
</head>
<body>
<div class="bg-white text-bold">
A Page of Links</div>
</body>
</html>`
}
exports.handler = arc.http.async(page);
Gatsby or other Front end build systems
The above process works best when sending server rendered html from Architect or Begin.com. When using Gatsby or some other frontend framework to build an app it often works best to follow the installation instruction for adding tailwind to Gatsby for instance. It is then built by Gatsby and included in the public folder along with everything else.
Top comments (0)