-
For those that don't know, my side project Raveberry is a multi user music server that allows democratic selection of songs. People can download it from PyPi and setup their own instance.
-
SaaSHub
SaaSHub - Software Alternatives and Reviews. SaaSHub helps you find the best software and product alternatives
-
In this post I want to share with you the journey of how I significantly reduced the size of the frontend code used in Raveberry. For a long time, I tried to avoid the frontend ecosystem as much as possible. Stories like a transitive dependencies breaking thousands of projects or npm rendering your system unusable by changing a bunch of permissions don't really help. That's why, for a long time, Raveberry's frontend was structured pretty straightforward.
-
The external dependencies were downloaded into the static/ folder containing all frontend assets using yarn and a package.json. Other than that, yarn was not used. Next I ran a bash script that removed all files I did not need, keeping the javascript, css and font files that should be served. In html, these files where directly included. I knew that loading many files is bad, so I used django-compressor to combine them into one big file. Conveniently, this tool also provided me with a way to compile scss.
-
Analyzing these dependencies, I found that some of them could be reduced or replaced. For example, jquery-ui is used for autocompletion and reordering. All additional widgets provided by jquery-ui (e.g. sliders, datepickers) are dead weight and can be excluded from the final bundle. Another example is marked, which was used to render the changelog. However, the changelog has a very simple structure and does not require a ~300KB library to be parsed. So instead, I use snarkdown, a lightweight alternative which is fully sufficient for this application.
-
The external dependencies were downloaded into the static/ folder containing all frontend assets using yarn and a package.json. Other than that, yarn was not used. Next I ran a bash script that removed all files I did not need, keeping the javascript, css and font files that should be served. In html, these files where directly included. I knew that loading many files is bad, so I used django-compressor to combine them into one big file. Conveniently, this tool also provided me with a way to compile scss.
-
Similar to the approach used for the css code, the fonts were also modified to only contain used symbols. A script parses html and javascript files to find used identifiers. Then, fonttools is used to create a subtyped font file with only these symbols. Since Raveberry only uses a small set of icons and Font Awesome provides a lot of them, this approach eliminates the vast majority. The resulting font files are 6.7KB and 2.3KB, much smaller than the original ones.
-
webpack
A bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through "loaders", modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.
To bring everything together, I use webpack to create the final bundle. It takes care of including the necessary libraries and minifies the output. I tried to use rollup but there were issues when importing only parts of jquery-ui. The final bundle.js has a size of 272KB. This is still not ideal, but since the functionality is basically identical, I consider it quite an achievement. The next step would probably be to replace jquery and jquery-ui with more lightweight alternatives.
-
Bootstrap provides css rules for a lot of html elements. Instead of serving all of it, purgecss is used to only include the necessary rules. The tool sifts through every html template and all javascript files to detect used identifiers. Everything else is removed from the resulting file, drastically reducing its size. I only had to manually prevent a few dynamically created identifiers from being removed.
-
Afterwards, a postcss pass minifies the css code, resulting in 21,8KB per light/dark style. In comparison to the naive approach, this amounts to almost 90% reduction.
-
Analyzing these dependencies, I found that some of them could be reduced or replaced. For example, jquery-ui is used for autocompletion and reordering. All additional widgets provided by jquery-ui (e.g. sliders, datepickers) are dead weight and can be excluded from the final bundle. Another example is marked, which was used to render the changelog. However, the changelog has a very simple structure and does not require a ~300KB library to be parsed. So instead, I use snarkdown, a lightweight alternative which is fully sufficient for this application.