Ever since the very first commits, a primary focus of NodeBB has been speed. We set out to provide a feature-rich forum without the typical reduction in speed commonly associated with long-running projects. While we didn’t know at the outset whether this was possible, there are a few reasons we prioritised speed:
- Technical debt accumulates over time, and we try to be active in reducing it
- Quite selfishly, every second longer it takes for NodeBB to build, affects us ten-fold simply because we build and re-build NodeBB hundreds of times per day.
- A fast forum is a forum that is a joy to use. The worst thing we can show to a user is nothing at all.
We’ve made some significant headway up until now, with a couple stand-outs1:
- The fact that we have a plugin system drastically reduces the core size of NodeBB to a common (and minimal) set of features. Every single forum has different priorities and needs, and it makes little sense to bundle these features into the core product itself, even if it is easier to do so2
- Our build system, while not a novel idea, drastically reduced the start time of NodeBB, and allowed assets to be built and re-built even if NodeBB was running. Reducing downtime when NodeBB restarts happened was the key driver here.
- Utilising your reverse proxy to serve static assets and compress files instead of NodeBB. Splitting up the work and minimizing the actual content sent over-the-wire makes a big difference.
- Our decision to utilise a hybrid templating engine (templates.js, and later on, Benchpress) meant we could serve the fully-formed HTML to the end-user without requiring post-processing commonly associated with client-side templating strategies. At the same time, we were able to handle intra-site navigation quickly again because of the hybridized approach3. In essence, we got the best of both worlds in terms of our view engine.
- Thanks to the awesome work of Peter Jaszkowiak, NodeBB is actually powered by a view engine that self-reports to being in the top three view engines available, while maintaining full feature compatibility with the templates.js syntax. Way to go!
In most cases, when we decide whether we want to pursue some sort of optimization, we do a quick thought experiment to see whether it ends up saving us time:
Figure 1. Of course there’s a relevant XKCD — https://xkcd.com/1205/
… nine times out of ten, the effort is worth it.
Can we do better?
We have a couple of changes in the pipeline that are worth sharing already. Thanks to automated tools like Google PageSpeed and Lighthouse, we were able to make measurable changes to NodeBB in order to improve page load speeds further.
We used to brush off complaints about our PageSpeed score by saying that automated tools don’t tell the whole story, and sometimes, they don’t4. In the end, we felt like we were avoiding the problem and set out to ace PageSpeed/Lighthouse, because benchmarks are still benchmarks.
- We started by removing any
@importstatements found in our codebase. We moved those out to
<link>tags with the
prefetchattribute, because a split-second of a fallback font was an acceptable tradeoff for faster initial page loads5.
- Any script that is loaded now uses the
deferattribute so as to not block the critical path, including the main
nodebb.min.jsfile, to prioritise loading the page content and style first.
- All link tags use the
prefetchattribute. In many cases, we were loading stylesheets and scripts for functionality needed later on, and so this made it quite easy to determine what was needed right away6
All of the above changes are tracked in our
develop branch at the moment, since they contain some breaking changes for themes. They’re slated to land in v1.7.0, which is not scheduled quite yet.
… but wait, there’s more!
Those changes were just the easy ones. We’re just about reaching the point of diminishing returns, where we’d likely be spending a fair bit of time just to squeeze out a few measly milliseconds of load time7. However I personally don’t see any reason not to continue to ensure that NodeBB is faster than any other forum software out there.
Among the many paths we could choose to go down…
- Should we create a successor to the Persona theme, we would likely opt to utilise common fonts found on the majority of systems, instead of relying on an imported font from a CDN like Google Fonts. Our users in China will love this one.
- Our css stylesheet can also be split up into separate files to allow browsers to intelligently choose which stylesheet to load based on device size, orientation, etc.
- On the server-side, our translator still takes a disproportionate amount of time relative to other tasks. Could this be our next optimisation project?
I guess sometimes I just feel the need… the need for… what was it again?
1 One quite controversial improvement we added was to place a progress bar at the very top of the page, much like YouTube has. When you clicked a link, right away the progress bar started animating from zero up to the ~60% region, before we started making the request to the server, and as it turns out it didn’t really matter because 95% of the time, by the time the animation finishes, the page finished being requested. We learned then that perceived speed mattered a whole lot in addition to real speed.
2 However, this tradeoff only benefits you in the short-term, and introduces technical debt if and when you need to excise the same feature out in the future.
3 Intra-site navigation only sends the raw data in JSON format, and the template is parsed on the client-side.
4 Performance tests tend to judge sites based on a strict set of benchmarks that don’t often correlate to user experience. Sometimes we were dinged for things that didn’t really harm user experience. Nonetheless…
5 Designers are screaming here.
6 The answer is: None. Nothing is needed right away.
7 Some say we’re there already.