Using WebAssets in Pelican to serve small css files



I cared a lot about mobile bandwidth usage. One of the things I focused on was condensing my css as much as possible.

WebAssets

This is a cool Python tool to help manage assets in your web projects. Lol. Some made a simple plugin for Pelican to integrate it into the system

Using modular css files and webassets, I can serve only the css styles that are required per page, without dumping all css selectors on every page.

Bear with me on this one.

Pelican settings file
PLUGIN_PATHS = ['plugins']
PLUGINS = ['assets']

ASSET_SOURCE_PATHS = ['src', 'helpers']

I tell the plugin which paths to look into for files I will be using later.

ASSET_CSS_BASE = ['css/base.css', 'css/fragments/sidebar.css']
ASSET_CSS_CONTENT = ASSET_CSS_BASE + ['css/fragments/content.css', 'css/fragments/syntax.css']
ASSET_CSS_PAGINATED = ['css/fragments/pagination.css']
ASSET_CSS_COMMENTS = ['css/fragments/comments.css']
ASSET_CSS_GALLERY = ['fotorama/fotorama.css', 'css/fragments/gallery.css']

Here I am creating some reusable, easily referenced lists containing paths to the files I will bundle together

ASSET_BUNDLES = [
    ('css-base',
        ASSET_CSS_BASE,
        {'output': 'css/base.min.css', 'filters': 'yui_css', })

    ,('css-archives',
        ASSET_CSS_BASE + ['css/archives.css'],
        {'output': 'css/archives.min.css', 'filters': 'yui_css'})

    ,('css-article',
        ASSET_CSS_CONTENT + ASSET_CSS_PAGINATED + ASSET_CSS_COMMENTS + ['css/article.css'],
        {'output': 'css/article.min.css', 'filters': 'yui_css'})

        ,('css-fragment-gallery',
            ASSET_CSS_GALLERY,
            {'output': 'css/fragments/gallery-fragment.min.css', 'filters': 'yui_css'})

    ,('css-categories',
        ASSET_CSS_BASE + ['css/categories.css'],
        {'output': 'css/categories.min.css', 'filters': 'yui_css'})

    ,('css-category',
        ASSET_CSS_CONTENT + ASSET_CSS_PAGINATED + ['css/index.css'],
        {'output': 'css/category.min.css', 'filters': 'yui_css'})

    ,('css-index',
        ASSET_CSS_CONTENT + ASSET_CSS_PAGINATED + ['css/index.css'],
        {'output': 'css/index.min.css', 'filters': 'yui_css'})

    ,('css-page',
        ASSET_CSS_BASE + ['css/page.css'],
        {'output': 'css/page.min.css', 'filters': 'yui_css'})

        ,('css-gallery',
            ASSET_CSS_BASE + ASSET_CSS_GALLERY + ['css/pages/gallery.css'],
            {'output': 'css/pages/gallery.min.css', 'filters': 'yui_css'})

    ,('js-gallery',
        ['jquery/jquery.min.js', 'fotorama/fotorama.js'],
        {'output':'js/gallery.js'})
]

The ASSETS is the fun part. It accepts a Tuple of three values (name, files, options) I won't go into all the details of using the plugin, but you should be able to discern how I split up my css code and only included what was necessary.

I am using font awesome for some of my icons. I may convert them to images at some point, but I did only include the css class that I needed instead of the entire library.

The biggest culprits here for filesize are of course: jquery and fotorama. I want to change lightbox/gallery library but it's turning out to be a much harder problem than I hoped for.

base.html - Jinja template file
...
    <head>
      {% block assets %}
      {% endblock %}
    </head>
...

Above, not all is included, but what is important is defining a block I can use to put the assets inside the head.

Inside of any page that extends base.html I can put this:

{% block assets %}
    {% assets "css-index" %}
    <link rel="stylesheet" href="{{ SITEURL }}/{{ ASSET_URL }}">
    {% endassets %}
{% endblock %}

Thus allowing me to reference the proper WebAssets bundle within the relevant file.

Finally

I'm pretty happy with this one. With a simple abstraction of content, and a relatively low overhead addition of process, I was able to knock off about 20k+ in bloat by only serving the css that's required.

Comments are loading... I hope ;)