Time in milliseconds; lower is better. SSR = Server-side rendered, CSR = Client-side rendered. Render time measured in CSR mode, rehydration time measured in SSR mode.
Both flavors performed very well. The SSR variants in particular showed dramatic improvement in First Meaningful Paint, reducing the time before a member sees useful content by over one second compared to the CSR variants.
Based on our test, Glimmer.js seemed to slightly outperform Preact at achieving First Meaningful Paint and Rehydrating/Rendering the page, in both the server-side rendered and client-side rendered variants. Preact seemed to slightly outperform Glimmer.js in Time to Interactive (TTI), which measures how quickly the CPU becomes idle after page load. Performing a root cause analysis of this difference has proven difficult because it is much more variable than the other metrics, and is sensitive to confounding factors such as ads and members beginning to interact with the page.
Either way, overall load time performance is very close—within hundreds of milliseconds—between the two flavors.
So what does it mean?
Ultimately, both Preact and Glimmer.js are fantastic tools for building fast, modern web applications. Both technologies allowed us to build an app that beat the initial load time of the control version. The difference in performance between the two flavors was so small as to be effectively imperceptible.
Both libraries offer their own unique benefits. Our team noted that Preact’s use of JSX offered productivity benefits, particularly thanks to integration with TypeScript. On the other hand, Glimmer’s unique architecture will allow it to take advantage of WebAssembly. This opens up a tantalizing avenue of exploration for improving load time even more in the future.
One takeaway from our experiment is that file size, while important, is not the whole story. Many people use library size as a proxy for how fast their application will load. Based on our findings, apps built with a larger library can load as fast or faster than those built with a smaller library, by amortizing the file size difference via savings in other areas.
It’s important to reiterate that we focused only on initial load times. There are other important performance metrics, such as responsiveness to interaction, that were out of scope for this experiment.
We are grateful for the rare opportunity to conduct this test, where we were given the time and resources to build two versions of the same app with the same team. We are also grateful to be in the unique position of having had maintainers from both Preact and Glimmer.js on the team, helping guide each implementation.
For us, the outcome of this experiment is particularly exciting because Glimmer.js shares a rendering engine with Ember.js, which is used to build LinkedIn today. We are in the process of taking the learnings from our prototype and contributing them back to Ember.js, so that we can improve the performance of our existing app and bring our learnings to the rest of the community.
It took a multi-disciplinary team of motivated engineers and managers from across LinkedIn to execute on this experiment. I’d like to thank the following people for their invaluable contributions to the project: Sarah Clatterbuck, James Baker, Kris Baxter, Diego Buthay, Chris Eppstein, Jeba Emmanuel, Chad Hietala, Jeremy Kao, Anand Kishore, Casey Klimkowski, Kacey Mack, Adam Miller, Asa Kusuma, Caitlin O’Connor, Mark Pascual, Karthik Ramgopal, Felipe Salum, Marius Seritan, Mahir Shah, and Sara Todd.