This is the third post of the three piece series Using npm with Hugo.
In the second post of the series, I showed you that Hugo itself can be seen as a dependency of your project, and that a starter theme provides you with full control over your dependencies and gives you the possibility to customize build scripts.
We also extended our basic example with a local Hugo install, a Hugo project structure, and a starter theme structure.
Let's continue.
Customizing scripts
Now we’re ready to talk about how to customize build scripts. In stead of using npx
to run a script from a local npm package, we're going to add a number of custom scripts to our package.json
:
{
..
"scripts": {
"prestart": "npm run clean",
"start": "hugo server --disableFastRender",
"prebuild": "npm run clean",
"build": "hugo --minify",
"clean": "shx rm -rf public resources",
"test": "echo \"Error: no test specified\" && exit 1"
},
..
}
Note the pre scripts prestart
and prebuild
. The prestart
script e.g. executes before the start
script. Similarly, you can use post scripts. A poststart
script e.g. would execute after the start
script.
Listing scripts
The npm run
command lists the scripts available in your package.json
:
$ npm run
Lifecycle scripts included in npm-hugo:
prestart
npm run clean
start
hugo server --disableFastRender
test
echo "Error: no test specified" && exit 1
available via `npm run-script`:
prebuild
npm run clean
build
hugo --gc --minify
clean
shx rm -rf public resources
Running scripts
The npm run start
command e.g. will:
- delete the temporary build directories, and next
- start the hugo server with the
--disableFastRender
flag enabled.
Bootstrap
We can use dependencies to pull in resources for our project. Let's import the Bootstrap SCSS we added previously, into our starter theme:
shx mkdir assets && shx echo '@import \"bootstrap/scss/bootstrap\";' > ./assets/app.scss
And process the SCSS with Hugo in ./layouts/partials/head.html
:
<head>
{{ $options := (dict "targetPath" "main.css" "includePaths" (slice "node_modules")) -}} {{ $css :=
resources.Get "app.scss" | resources.ToCSS $options -}}
<link rel="stylesheet" href="{{ $css.Permalink }}" />
</head>
Let's add some Bootstrap styling to ./layouts/index.html
:
{{ define "main" }}
<div class="container-fluid">
<div class="row vh-100 align-items-center justify-content-center">
<div class="col-md-7">
<h1 class="text-center">{{ .Title }} 🎉</h1>
</div>
</div>
</div>
{{ end }}
Add the resources
and public
folders to .gitignore
, and check the result with npm run start
.
Removing unused CSS
We can also use dependencies to pull in tooling for our build process. Let's make our project production ready by stripping out unnecessary CSS:
PurgeCSS analyzes your content and your CSS files. Then it matches the selectors used in your files with the one in your content files. It removes unused selectors from your CSS, resulting in smaller CSS files.
We will also be installing Autoprefixer, a PostCSS plugin to parse CSS and add vendor prefixes to CSS rules using values from Can I Use:
npm i -D @fullhuman/postcss-purgecss postcss-cli autoprefixer
Add ./postcss.config.js
:
const autoprefixer = require('autoprefixer');
const purgecss = require('@fullhuman/postcss-purgecss');
module.exports = {
plugins: [
autoprefixer(),
purgecss({
content: ['./layouts/**/*.html']
})
]
};
Update ./layouts/partials/head.html
:
<head>
{{ $options := (dict "targetPath" "main.css" "includePaths" (slice "node_modules")) -}} {{ $css :=
resources.Get "app.scss" | resources.ToCSS $options -}} {{ if hugo.IsProduction -}} {{ $css = $css
| minify | fingerprint | resources.PostCSS | resources.PostProcess -}} {{ end -}}
<link rel="stylesheet" href="{{ $css.Permalink }}" />
</head>
Update ./config.toml
:
baseURL = "/"
..
Add to package.json
:
{
..
"browserslist": [
"defaults"
],
..
}
- http-server is a simple, zero-configuration command-line http server — handy for viewing a local production build.
- Chrome DevTools is a set of web developer tools built directly into the Google Chrome browser.
Run npm run build
and check the result. That's it. We've brought down the file size of our CSS file from 185.76 KB to — yes that's right — 2.63 KB.
Plugins
We could also use dependencies to pull in extra functionality into our starter theme. Think of e.g. SEO, performance, and security.
Wrapping up
You're now familiar with customizing build scripts. We also extended our example with Bootstrap, and optimized it for use in production. You're now also aware that you can use dependencies to pull in extra functionality.
You can find the full example in the npm-hugo repo I've set up.
In case you’re curious, the idea for this series was taken from a similar post written about WordPress.