“Delayed Script Execution” in Opera
I’ve recently been evangelizing techniques for loading external scripts without blocking the rest of the page. A co-worker at Google pointed out a little known option in Opera: Delayed Script Execution. Opera’s support web site provides this explanation:
This option is handy for developers today, and provides a guideline for how script deferral should be built in all browsers.
Loading Scripts Without Blocking and document.write
There are serveral advanced techniques for loading scripts without blocking other downloads and rendering. At recent conferences, I’ve talked about six alternatives for asynchronous script loading. (See slides 14-27 from my OSCON slide deck, for example.)
I created a test page that demonstrates how this feature would benefit all browsers. The test page contains a script followed by eight images. The script is programmed to take 4 seconds to download and 4 seconds to execute. The images are each programmed to take 1 second to download. In most browsers, the default behavior is that the browser starts downloading and executing the script first, since it occurs first in the page. The images have to wait 8 seconds for the script to finish before they are downloaded and rendered. The text in the page is also blocked from rendering for 8 seconds, even though it’s already been downloaded before the script. This is because browsers block rendering of anything (text and resources) below a script until the script is done downloading. Let’s look at how this page behaves in popular browsers.
- IE 6,7,8
- Firefox 2,3
- Loading the page in Firefox 2,3 produces results similar to IE — the script blocks the images. In Firefox 2 the overall page load time is ~12 seconds (8 seconds for the script plus 4 seconds for the images to load over two connections). In Firefox 3 it’s ~10 seconds (8 seconds for the script plus 2 seconds for the images to load over six connections).Since Firefox doesn’t support the DEFER attribute, you can click on the “Load Dynamically” button to load the script using one of the advanced non-blocking techniques (“script DOM element”). The page starts off loading great — the entire text is rendered immediately and the images start downloading and rendering quickly, all because the script is being loaded asynchronously. But when the script finally finishes and does its document.write, the entire page is overwritten, similar to what happens in IE. Scripts containing document.write can’t be loaded asynchronously in Firefox.
- Safari 526
- The script and eight images are downloaded in parallel. (Parallel script loading is a new feature in Safari 526.) But rendering is blocked for the entire 8 seconds while the script is downloaded and executed. Overall page load time is ~8 seconds, since the images and script are downloaded in parallel.To try loading the script asynchronously, click on the “Load Dynamically” button. The text is rendered immediately and the images start downloading and rendering quickly, all because the script is being loaded asynchronously. But when the script finishes and does its document.write, it’s not shown in the page. Scripts containing document.write won’t have their output shown in the page if loaded asynchronously in Safari.
- Opera 9.5
- Without enabling the “Delayed Script Execution” option, the page load experience is similar to the other browsers: The script is downloaded first, blocking the image downloads and text rendering for 8 seconds. The overall page load is a little faster, ~9 seconds, because Opera supports eight simultaneous connections, so the eight images download in 1 second.Enabling “Delayed Script Execution” provides an exciting alternate experience. The entire page’s text is rendered immediately. The eight images start downloading and rendering right away. In the background the 8-second script is downloading, so the overall page load time is ~8 seconds. The icing on the cake is that when the script is done executing its document.write appears where it should – a purple DIV in the box at the top. It doesn’t overwrite the page and it doesn’t disappear. It goes right where it was supposed to go.
What’s all the excitement?!
I’m even more excited about how this shows us what is possible for the future. To be able to have asynchronous script loading and preserve document.write output is like having your cake and eating it too. It’s difficult for users to find this feature in Opera. And it’s beyond the reach of web developers. But if Opera’s “Delayed Script Execution” behavior was the basis for implementing SCRIPT DEFER in all browsers, it would open the door for significant performance improvements by simply adding six characters (“DEFER ”).
This is most significant for the serving of ads. Often ads are served by including a script that contains document.write to load other resources: images, flash, or even another script. Ads are typically placed high in the page, which means today’s pages suffer from slow loading ads because all their content gets blocked. And really, it’s not the pages that suffer, it’s the users. Our experience suffers. Everyone’s experience suffers. If browsers supported an implementation of SCRIPT DEFER that behaved similar to Opera’s “Delayed Script Execution” feature, we’d all be better off.
Food for thought for Safari, Firefox, and IE.