Using WebAssets in Pelican to serve small css files
web-dev ~ 2017-05-12I 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.