Skip to main content Accessibility Feedback

A better way to load scripts with JavaScript (or, why document.write() sucks)

You may have heard that you shouldn’t use document.write() to inject scripts into a page. But why?

From Google:

For users on slow connections, such as 2G, external scripts dynamically injected via document.write() can delay the display of main page content for tens of seconds, or cause pages to either fail to load or take so long that the user just gives up. Based on instrumentation in Chrome, we've learned that pages featuring third-party scripts inserted via document.write() are typically twice as slow to load than other pages on 2G. We collected data from a 28 day field trial on 1% of Chrome stable users, restricted to users on 2G connections. We saw that 7.6% of all page loads on 2G included at least one cross-site, parser-blocking script that was inserted via document.write() in the top level document. As a result of blocking the load of these scripts, we saw the following improvements on those loads:
  • 10% more page loads reaching first contentful paint (a visual confirmation for the user that the page is effectively loading), 25% more page loads reaching the fully parsed state, and 10% fewer reloads suggesting a decrease in user frustration.
  • 21% decrease of the mean time (over one second faster) until the first contentful paint
  • 38% reduction to the mean time it takes to parse a page, representing an improvement of nearly six seconds, dramatically reducing the time it takes to display what matters to the user.

10 seconds of extra delay on an already slow connection! That’s a huge decrease in performance.

So… if not document.write(), how should you inject scripts via JavaScript?

A Better Way

Here’s a technique you can use to asynchronously load JavaScript files:

// Get the first script element on the page
var ref = w.document.getElementsByTagName( 'script' )[ 0 ];

// Create a new script element
var script = w.document.createElement( 'script' );

// Set the script element `src`
script.src = 'path-to-your-javascript-file.js';

// Inject the script into the DOM
ref.parentNode.insertBefore( script, ref );

If you find yourself doing this a fair bit, you might want to consider including loadJS, an awesome helper method from Filament Group. They also have a CSS version, loadCSS.