How can a web app built in a visual web framework possibly beat one of the World's fastest sites? One that only includes a top navigation and a search field?
Jacob Kofoed
December 12, 2024
80% of a great user experience is based on speed. Your site might be optimized to show every element in the best possible place and have every toggle tweaked to perfection, but if it’s slow, your hard work might never get noticed.
According to a study by TechReport, “40% of users will exit a website if it takes more than 4 seconds to load.” Speed is crucial not only for users but also for business metrics, and it should be tracked regularly.
One of the core pillars at toddle is speed. As we’re responsible for how thousands of web applications are rendered, we are responsible for giving developers the foundation to build front-ends that load faster than 1 second.
We hit that goal, but we want to go faster. About a year ago, we started to dig into performance and identify the items we’d need to track to ensure a consistent performance of toddle over time. The challenge was simple: Make toddle the fastest programming language on the planet without harm to flexibility.
In March, we posted our first performance update. We increased the load speed by 2X and reduced our memory usage by 50%.
Our first findings led us to:
Reduced DOM Nodes: We've significantly reduced the number of DOM nodes by switching how we track references. This change also means that the final HTML output, in addition to faster renders, matches what you see in the editor.
Better Memory Usage: By studying memory snapshots, we found and removed some memory leaks and switched to weak references where possible.
Minimized DOM Manipulation: We opted to perform mutations over replacements for dynamic content. This change improved repeated items by moving elements around rather than destroying and recreating them.
We use Google Lighthouse to track our core web vitals, and it’s been an excellent guide for how we perform against their metrics. However, it did little to show what we were up against. We needed something a bit more…. Say… entertaining. We worked with a community member to build Lighthouse Wars. The basic idea was to create a tool to benchmark toddle’s performance against other sites.
That would give us a concrete set of metrics to start working towards and proactive feedback from the community.
Needless to say, we didn’t start great. But that was the whole point. We knew we weren’t the best, and that’s what we needed to fix.
The app was built exclusively in toddle and hooks up to Google’s Lighthouse API. It’s a neat way to track our score over time and gives us the elusive score that changes based on the EDGE location it just happens to tap into.
How did toddle become one of the fastest web frameworks?
Performance optimization is done through a continuous cycle of gathering metrics and optimizing one bottleneck at a time. In the past year, some of the bottlenecks we’ve dealt with include:
Font loading
For improved caching, toddle now serves fonts directly instead of relying on third party CDNs. This change also allows us to support some exciting modern font features, like dynamic loading with “unicode-range”. These changes drastically reduce the amount of font data that needs to be shipped. Font data may sound innocent enough, but it is often one of the heaviest individual assets of websites. We observed improvements in font-loading by up to 20x, depending on the specific font and transfer speeds.
Server-Side Rendering
We always had server-side rendering (SSR), but like so many features, it is an ongoing iterative process, and we’re not done yet (ever). With the release of toddle’s latest API panel update, we took SSR to another level. You can render entire applications with multiple asynchronous levels of components, each with multiple APIs. Even more important, it’s now easier to control when NOT to use SSR. If you have a slow API or data that’s only needed below the fold, you can disable SSR for individual APIs to let the rest of your page load faster from the server.
Core runtime optimization
We have continued to reduce the number of DOM mutations, so you can now efficiently update tens of thousands of elements simultaneously without toddle breaking a sweat. We would like to try a few more things, but as with all optimizations, the performance curve has a natural ceiling that we will likely approach soon. This leads us to:
Perceived performance
Perceived performance is equally important as raw performance. We implemented speculation rules for all links, which often close the gap between toddle pages that load fast and toddle pages that load instantly because we pre-load content before you even click a link.
We also improved our APIs with the new and upgraded API panel. This is a huge quality-of-life improvement but also adds more control over how and when data from APIs is shown. When you control the cache optimally, you can show stale or placeholder data as you fetch fresh content in the background. The new API panel significantly improves both raw and perceived performance.
Smarter issue rules
We now have more than 50 static analysis rules. These rules help users optimize their sites even further as they inform them about potential layout shifts, unnecessary formulas, workflows, and much more. The rules are constantly checking your apps in the background while in the editor, and live-updates with suggestions. We use this ourselves to optimize the toddle editor, as toddle is in fact built in toddle!
Here are some of the scores we post today
We still have a lot of work to do, but we have progressed a lot since we started the work to become the fastest web framework.
toddle vs. Netlify (92 - 89)
Netlify does well across the board, but toddle wins by having the best overall score.
toddle vs. Vercel (94 - 53)
This one surprised us. Vercel has long been the poster boy for performance. toddle beats them on all but one metric.
toddle vs. Google (92 - 88)
This one made us feel like we had unlocked God-mode. How does a ram-packed site compete with a search box made by one of the greatest companies in the world? On some days, we even outperform the fastest search engine on the planet. Ironically, Google happens to be the organization behind Lighthouse, so that makes us feel even better. To be fair, Google is likely downloading a lot of blocking tracking code.
The bar that constantly moves
As you’ve probably already spotted, the benchmark keeps moving. Every time we run this test, we’ll get a different score. It’s a bar constantly moving like a quantum particle under the Heisenberg uncertainty principle.
Some might find it frustrating, but for us, it’s a great reminder that performance has many variables that need to be controlled. We’ll continue to move the needle on performance and post these updates as we learn more. We’ll eventually want to be the fastest language programming language on the planet while maintaining the same flexibility you get from frameworks like React.
Next up?
Lighthouse is a convenient tool that allows us to compare ourselves with other cutting-edge technologies directly. However, it does not show the full picture. While toddle is unopinionated in how you build your app and which third parties you connect to (backends), we try to steer our users towards the most performant and scalable development decisions. Our issue panel, for example, is now showing many more issues around performance. Still, we are investigating ways to go beyond static analysis and give you runtime feedback on how to optimize your apps. We would also like to show analytics from proxied APIs, page render times, and ways to improve it.
While we are close to a clean 100 score on Lighthouse, our journey to become the most performant web framework will continue.