I have been working for over a year on lego, a static site generator written in JavaScript. When I decided to rewrite my site, I had a wide variety of SSGs to choose from. I eventually narrowed down my choices to the following:
- Gatsby - I really liked how optimised the output was with Gatsby. The only issue I had with Gatsby was the slow build timings.
- Hugo - I loved Hugo for its speed. However, the templating language was frankly too disappointing.
- Jekyll - This was fast enough for my site's size and the templating language, Liquid, was pretty similar to Jinja2. However, doing Gatsby like optimisations was challenging.
I had way too much free time on my hands so I did what every bored developer does. Write my own framework. In this case, I decided to write my own static site generator that emulates the good parts of these three frameworks.
I had a few requirements out of this and decided to try building it for a week or so and see how feasible this was.
- Support Liquid(recently added Nunjucks support).
- Support Markdown posts, data in YAML(later extended to JS and JSON).
- Transpile and uglify JS with terser, use PostCSS for CSS(both use
browserslist
to determine targets). - Revision assets like JS, CSS and images.
- Optimise images.
- Extract and inline critical styles with critical for all pages.
- Minify HTML of all pages.
- Generate a tag-wise listing of posts. For example,
site/tags/javascript
should list all pages taggedJavaScript
. - Live Reload during development.
Surprisingly it turned out pretty well. There were still a few rough edges but I quickly ported over my site in the hopes that I could fix them.
This is when the fun began.
lego was taking about 5-6 seconds to start up. While this was not that bad compared to Gatsby, I wanted to squeeze out as much performance out of it as I could. The whole purpose of this project was to learn something and have fun in the process so I decided to profile lego. A few interesting things stood out.
- Just requiring PostCSS plugins was taking a second or two.
- Some code paths were running more often than necessary.
After fixing these, it came down to about 2-4 seconds.
This is when I started looking into caching. While coming up with a technique for this was challenging, the actual implementation was rather trivial. After implementing caching, I felt satisfied with this whole endeavour of writing my own SSG. I now had a fast, performant SSG that generated an optimised site.
Right now, lego starts up a development server for my own site in under 600ms. Rebuilds take under a couple hundred milliseconds. Production builds take about 20 seconds!
I wrote a benchmark to test all this. When Liquid templates are used, lego is about 1.5x faster than Jekyll and when Nunjuck templates are used, lego is a cool 8.7x faster than Jekyll.
I then added a few more things like RSS Feed generation and sitemap generation based on my own needs. While lego supports auto-generating responsive images, I think it's a little less robust and I will start paying attention to it in the coming days.
If you are feeling adventurous and want to try this out,
Run
npm i -g @astronomersiva/lego
.Generate a site using
lego g my-awesome-site
. This will generate a dummy site.Run
lego s
to start the server.
You can also checkout the code on GitHub.
Have a great weekend folks!
Top comments (6)
That's interesting. I think lego and eleventy have certain differences in the end goal. Lego tries to be like Gatsby while 11ty leaves all those decisions to the user.
Having said that, I put together a dummy project with a similar structure containing 100 markdown posts. Running lego with all the optimisations and caching disabled results in the following:
Really cool job! I like that you kept RSS and other good dev options
Thanks @Setiz!
Yes, most of the work that lego does is to make it easy for developers to work on their sites. There's also build time code highlighting so you don't have to run highlight.js or Prism.js on page load. Just a small CSS file will be sufficient and the code will be highlighted even if the users browse with JS disabled on their browsers.
The bulk of lego's production build timing is spent in three tasks:
If I disable image optimisation and inlining critical styles, I am able to hit sub 10 second production builds as well but the output files are still minified with htmlminifier.
I am curious if 11ty does these as well.
Nice, why not another SSG.
Now I'm using 11ty (for simple LP and sites) and Gatsby (for blogs), but I will take a look at your tool.
Happy SSG-ion!
I think using the name "lego" might be a problem for legal reasons?