Why you should avoid using document.write, specifically for scripts injection

Web performance testing tools like Google Page Speed or Dareboost already pointed it: injecting a script by using document.write instruction causes severe issues about websites loading time. Let’s talk about this topic one more time, as the next Chrome update to come won’t allow such scripts injections any longer. What kind of issues may you experience? Which alternatives to find?

Chrome won’t execute Scripts injected via document.write any longer

Paul Kinlan announced it on early September on developers.google.com website: Chrome will soon intervene against document.write instruction and, as a consequence, disallow scripts injection via this instruction. Indeed, this change is about to occur from mid-october, with the release of Chrome 54. Some warnings can be noticed yet within the Chrome 53 Developer Console for concerned websites.

What kind of blocking exactly?
Fortunately, for most of websites, blocking cases will be quite limited, only when all the following conditions are met:

  • The user is experiencing a very poor network connectivity,
  • The script is parser-blocking (neither async nor defer attributes) and is not already in the browser cache,
  • The instruction is added in the top level document (e.g. iframes won’t be concerned),

If all of those conditions are met, the script will simply not be loaded. So beware if your web pages integrates third-party services. Even if you don’t use that instruction by yourself, your website may present such a dependency, that soon will not work any more with part of your visitors.

Even if this evolution may cause failures on some websites, Chrome’s strategy is interesting though, aiming to push out (very) bad practices. As detailed below, document.write indeed comes with significant performance issues.

Issues caused by document.write

When you use the following Javascript command to inject a script:

document.write('<script src="https://example.com/script.js"></script>');

the browser is not able to continue parsing the HTML. The web browser is forced to wait for the resource to load AND to be executed. The situation could even be more harmful, as the browser will also be stopped if the first script injects other ones! Not such a rare situation considering all the third-party services you are probably using on your webpages. As a proof, in his update announce, Chrome published the results of their own tests: 7.6% of the web pages would be concerned!

By the way, we can also learn how bad the document.write instruction can be a perf killer… Let’s have a look at the Chrome’s tests results with their 1% users with a 2G connection: 38% reduction to the mean time it takes to parse a page, representing a benefit of nearly six seconds!

Another issue to be considered about using document.write command (and not only in a script injection case): if the DOM tree has already been built, the use of document.write will force the browser to build it again… A pity for the performance! (document.write writes to the document stream, calling document.write on a closed – loaded – document will reset the current document.)

How to avoid the use of document.write

Generally, you should avoid the use of blocking JavaScript. “Defer” and “async” attributes will let you invoke external scripts asynchronously. However, be careful regarding the execution order of your scripts, as this order is not guaranteed in an asynchronous loading case!

If the use of document.write concerns a third-party service, you have to check if your provider propose an asynchronous loading version. If it doesn’t, then think about an alternative.

Finally, in order to insert contents in your web pages, prefer DOM manipulation rather than using document.write. Here is an example of script:

var sNew = document.createElement("script");
sNew.async = true;
sNew.src = "https://example.com/script.min.js";
var s0 = document.getElementsByTagName('script')[0];
s0.parentNode.insertBefore(sNew, s0);

As a conclusion, please note that, according to this evolution, our website testing tool will soon stronger penalize the use of document.write, especially for analyses launched in a mobile context.