🛸 Using PostCSS & Future CSS with Deno Fresh #
In this post on Deno Fresh PostCSS, we take a look at setting up some vanilla CSS tooling for Deno Fresh. Deno Fresh is an SSR site builder. It has instant deploys with no build step. The absence of a build step sets Deno Fresh apart from other site builders like Astro or SvelteKit. Both of those process CSS, minify and handle some transformations for you. Although Deno Fresh lacks those features, the upside is that you have more control over your CSS; you make the decisions, not the tooling. That said, you need to do a little setup work to use popular tooling like PostCSS. That is what we look at here.
PostCSS tooling transforms input CSS. You can use it to generate prefixes automatically for legacy browsers or to minify the CSS. Minification just removes white-space and comments from CSS, optimizing the CSS for delivery to a browser. With our setup, we can keep the original CSS file (with comments and white-space). Each time we save it, under the hood, PostCSS will generate the shipped version. We do not just look at minification here. We also add some PostCSS processing to handle modern or future CSS, which is not yet fully integrated into the CSS Specification.
🧱 What are we Building? #
Rather than build a project from scratch, we will just look at the setup we need to add to a Deno Fresh project to use PostCSS. We will see:
- how you can configure PostCSS itself in Deno Fresh;
- how you can automatically generate processed CSS each time you save a CSS input file; and
- a way to cache your static CSS assets with Deno Fresh.
If that sounds good, then let’s get started.
⚙️ Deno Import Map #
Let’s start by updating imports
filed in the deno.json
file in the project root directory:
We added an import path alias in line 8
which we will use later.
💅 Post CSS Config #
The config itself will not be too different to what you are already familiar with from Node-based
tooling. The main difference will be that we use an npm:
prefix on
imports. Create postcss.config.ts
in the project root directory with
the following content:
👀 Watch Script #
The last main piece is the watch script. This watches the CSS input folder for changes and runs
PostCSS each time you save a file there. We will use a styles
directory
in the project root folder as the CSS input directory. When we save a CSS file there, the watch script
will output the result to static/styles
. static
is for content which you want Deno Fresh to serve statically from your deployed project.
Create build-css.ts
in the project root directory with the content
below:
-
The
buildStyles
function (line8
) takes an updatedstyles
path and processes it with PostCSS, saving the output tostatic/styles
. -
Calling
debounceBuildStyles
instead ofbuildStyles
directly, stops the CSS building function from firing off too often. We limit it to run once at most in any 200 ms period. -
Lines
29
–36
will run once when we start up the build CSS task (more about that in a moment) and create the outputstatic/styles
directory if it does not yet exist. -
Lines
38
–44
contain the watch code for file changes in thestyles
directory. If you added new files before firing up the build CSS task, just save them again once the task is running to make sure PostCSS processes them.
💄 Build CSS Task #
Next, we can create a Deno task to run the watch script created in the last section. Update the deno.json
file in the project root directory to add a build:css
task:
We give the task just the permissions it needs here. These are read-write (file system) access and access to environment variables. You can be more restrictive if you prefer, listing the specific directories Deno will apply the read and write permissions to.
You can open a new Terminal tab and run this new task there:
Then in your previous Terminal tab, start up the Deno Fresh server (as usual) by running deno task start
. Try creating a new CSS file at styles/global.css
for example. If
you open up static/styles/global.css
you should see a minified version
of this CSS which PostCSS has generated.
🗳 Poll #
💯 Deno Fresh PostCSS: Testing #
Add a few more CSS files and try using new features like range media queries. You can include the
CSS in a rel
tag in one of your Preact markup files:
Here I wrapped the href
for the stylesheets in the asset
function. This is helpful for cache busting. Deno Fresh will hash the content of the files and append
the calculated hash to the filename. When the CSS changes, the hash and consequently file name change,
so no outdated CSS cached in-browser or in a CDN will be applied.
Take a look in static/styles
. Your file should contain minified
CSS and look something like this:
🙌🏽 Deno Fresh PostCSS: Wrapping Up #
We had an introduction to how you can set up PostCSS with Deno Fresh. In particular, you saw:
- Deno code for triggering a function when a file changes;
- how to be selective in Deno task permissions; and
- some Deno file APIs.
The complete code for this project is in the Rodney Lab GitHub repo . I do hope the post has either helped you with an existing project or provided some inspiration for a new one. As an extension, you can add all your favourite future CSS rules to the PostCSS config. Beyond PostCSS for linting your input CSS, consider trying stylelint .
Get in touch if you have some questions about this content or suggestions for improvements. You can add a comment below if you prefer. Also, reach out with ideas for fresh content on Deno or other topics!
🏁 Deno Fresh PostCSS: Summary #
Can you use vanilla CSS with Deno Fresh? #
- Yes! You will get prompted to set up the Tailwind plugin when you spin up a Fresh project with the CLI tool. That said, if you prefer vanilla CSS you can just add your CSS source to the static folder. You can then link the added file using rel tags in your Preact markup. We saw you can even use PostCSS to transform your input CSS. In this case, add your source CSS to another folder and configure PostCSS to output to `static`.
Is there a Deno PostCSS module? #
- Yes, there is a PostCSS module on deno.land/x (https://deno.land/x/postcss). You will likely want to add in your favourite PostCSS rules and plugins too. We saw you can import them right from npm. As an example, to use the CSSO plugin for minifying CSS, write an import statement like: `import csso from "npm:postcss-csso";`. I saw no issues using autoprefixer, postcss-csso, postcss-custom-media or postcss-preset-env in Deno.
How can you cache-bust static assets with Deno Fresh? #
- Let’s say you have a static global.css file in your project served at `https://example.com/styles/global.css`. For optimal performance, you will probably want browsers and CDNs to cache this file. However, when you update the file at a later date, there is a risk the browser or CDN serves up the stale, cached version instead of your new one. Cache-busting is a technique to avoid this happening. Deno Fresh provides a neat solution here. When you add a link in your markup to a CSS file or other resource (in the `static` folder) update the link. Change href=`/styles/global.css` to `href={asset("/styles/fonts.css")}`. You can import the `asset` function from `$fresh/runtime.ts`. It adds a hash to the linked path in your markup, so a stale cached version never gets served.
🙏🏽 Deno Fresh PostCSS: Feedback #
Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, then please consider supporting me through Buy me a Coffee.
Just dropped a new post on setting up PostCSS with 🍋Deno Fresh.
— Rodney (@askRodney) March 8, 2023
Handy for minifying your CSS and also using future CSS today.
Hope you find it useful!
#askRodney #learndeno #futurecss https://t.co/glVJHU7YQt
Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter, @[email protected] on Mastodon and also the #rodney Element Matrix room. Also, see further ways to get in touch with Rodney Lab. I post regularly on Astro as well as Deno. Also, subscribe to the newsletter to keep up-to-date with our latest projects.