Create a Pelican plugin to minify HTML, CSS, and JS

TL;DR - Minify you Pelican Website

Minification of wesite resources is an essential step for good PageSpeed / Lighthouse scores, and as I've bragged in past, CloudBytes/dev> scores a perfect 100.

CloudBytes.dev PageSpeed Score

This is partly because Website generated by SSGs are generally faster than the ones generated using CMS solutions like WordPress, etc. But the main reason is non-redundant JS & CSS code.

To make websites faster still, you minify the contents of all the HTML, CSS & JS files which typically results in smaller file sizes that consequently means faster load times for users.

Minify Reduction

Minify your Pelican Website

There are a lot of options in Python to minify your webassets, but none of them work. Either they break your website (e.g. remove embedded JS code) or are outdated and not maintained. I personally tried the below in dev environment:

  1. ❌ Unofficial Pelican Plugin: css-html-js-minify: Broke the website πŸ’”, removed embedded JS, deleted some CSS variables & class definitions.
  2. ❌Official Pelican Plugin: Extremely promising, is useless, and doesn't work. Becase it doesn't minify HTML pages, and it relies on additional 3rd party modules for minification and those modules are either unmaintained (cssmin,css_yui, etc) or simply doesn't work and breaks the site (cssutils), or requires NPM/NodeJS modules that needs to be installed manually (cleancss)
  3. ❌Non-Python packages such as html-minifier, minimize, etc. These could have been used but the hassle of integrating them into the CI/CD workflow was too much
  4. βœ… minify-html: This seemed to work without breaking the website. Minify HTML is a Rust app but with APIs available in several languages (Python, Ruby, NodeJS, Java, etc) which made it easy to write a simple plugin.

Writing the Minification Plugin

First step is to install the minify-html package. Run the following command

pip install minify_html

Then create a plugin, using the below code

import minify_html
import glob
import os
import sys
import logging

from pelican import signals

logger = logging.getLogger()


def main(pelican):
    for file in glob.iglob(pelican.output_path + "/**/*.html", recursive=True):
        print(f"Processing {file}")
        try:
            with open(file, "r", encoding="utf-8") as html:
                minified = minify_html.minify(html.read(), do_not_minify_doctype=True)
            with open(file, "w", encoding="utf-8") as html:
                html.write(minified)
        except Exception as error:
            logging.error(error)


def register():
    signals.finalized.connect(main)

Add it to the plugins list in pelicanconf.py and you're good to go with a website that is almost 20-30% faster

Need Help? Open a discussion thread on GitHub.