I’m trying to create a new theme for Hugo.
Hugo offers powerful features, for example, Hugo pipes. Pipes allow you to transform data in your Hugo templates.
I want to use PurgeCSS to remove unused CSS from my production bundle.
The official website has a guide for using PostCSS with Hugo, but it was not 100% clear to me how to use the instructions.
1. Template
You will have a html template in your themes
folder. Mine has the folllowing path: themes/<name-of-theme>/layouts/partials/head.html
:
{{- $critical := resources.Get "scss/critical.scss" | resources.ToCSS }}
{{- $fonts := resources.Get "scss/fonts.scss" | resources.ToCSS | resources.Minify | resources.Fingerprint }}
{{- if hugo.IsProduction }}
{{- $critical = resources.Get "scss/critical.scss" | resources.ToCSS | resources.PostProcess | resources.Minify | resources.Fingerprint }}
{{- end }}
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="{{ $critical.RelPermalink }}" />
<link rel="stylesheet" media="print" href="{{ $fonts.RelPermalink }}" onload="this.media='all'" />
<title>
{{ if not .IsHome }}{{ with .Title }}{{ . }} | {{ end }}{{ end }}{{
.Site.Title }}
</title>
<meta
name="description"
content="{{ with .Description }}{{ . }}{{ else }}{{ with .Summary }}{{ . }}{{ else }}{{ .Site.Params.description }}{{end }}{{ end }} "
/>
{{ template "_internal/opengraph.html" . }}
{{ template "_internal/twitter_cards.html" . }}
{{ template "_internal/schema.html" . }}
</head>
If we make a production build with the command hugo
, we will process the Sass SCSS file with several transformations.
2. Main Folder
The above code sits in the theme
folder, nested in your main Hugo project.
Example folder structure:
├── archetypes
│ └── default.md
├── config.toml
├── content
│ ├── about.md
│ └── blog
│ ├── 2021
│ │ ├── hipsum.md
│ │ └── lorem-ipsum.md
│ └── _index.md
├── data
├── layouts
├── static
└── themes
└── sample-hugo-theme
├── archetypes
│ └── default.md
├── assets
│ └── scss
│ ├── _config.scss
│ ├── critical.scss
│ └── _reset.scss
├── layouts
│ ├── 404.html
│ ├── blog
│ │ └── single.html
│ ├── _default
│ │ ├── about.html
│ │ ├── baseof.html
│ │ ├── list.html
│ │ └── single.html
│ ├── index.html
│ └── partials
│ ├── footer.html
│ ├── header.html
│ ├── head.html
│ ├── page-header.html
│ ├── pagination.html
│ └── post_pagination.html
├── LICENSE
└── theme.toml
We run the necessary commands from the main folder. For development mode, we use hugo server
, for production mode, we use hugo
.
Depending on which command you run, Hugo will recognize the mode.
That means that you’ll need to set configuration settings from guide in the main folder (not the themes folder where your HTML template resides).
Install the necessary Node.js dependencies in the main Hugo directory (same folder as config.{toml,yaml,json}
:
npm i -D @fullhuman/postcss-purgecss postcss postcss-cli
The next parts are identical to the documentation:
Adjust the configuration. If you use toml
, here’s the example config.toml
:
[build]
writeStats = true
Create a postcss.config.js
:
const purgecss = require('@fullhuman/postcss-purgecss')({
content: ['./hugo_stats.json'],
defaultExtractor: (content) => {
let els = JSON.parse(content).htmlElements
return els.tags.concat(els.classes, els.ids)
},
})
module.exports = {
plugins: [
...(process.env.HUGO_ENVIRONMENT === 'production' ? [purgecss] : []),
],
}
3. Production Build
Run the following command inside your terminal:
hugo
The command will create a public
folder which contains the static website that you built with Hugo. Your CSS assets should work.
Thoughts
If you share your theme for others to use, they will have to go through the steps of installing the Node.js dependencies in their Hugo project.
I find that less than ideal, as I prefer to manage my assets from the themes folder.