How can I make the inserted javascript load before DOMContentLoaded?

I have a remote script that is referenced in the HEAD of my HTML page. This first script downloads and inserts another script, adding it to the DOM. Both scripts exist on a different domain than the page on which they are embedded.

The content of the first script looks like this:

(function(){
  var siteIdentifier = ...
  var scriptTag = document.createElement('script');
  scriptTag.type = 'text/javascript';
  scriptTag.src = '//blah.com/foo/' + siteIdentifier + '/second_script.js';
  scriptTag.async = true;
  document.getElementsByTagName('head')[0].appendChild(scriptTag);
})();

      

When I try this in Chrome (version 43.0.2357.81, 64 bit) I see the first script loading very early in the timeline. But the second script is never loaded until the DOMContentLoaded event occurs.

The following screenshot shows the download / run timeline for two scenarios. The first script is the top element and the second script is the bottom element. Ignore the element in the middle, which is another artifact that I couldn't filter out from the timeline for the screenshot. The vertical blue line is the DOMContentLoaded event.

enter image description here

I've tried with and without async and deferred, but that doesn't seem to have any effect. Is there a way to make the loading of the second script be instant and not wait for the DOMContentLoaded event to occur?

Update:

I created an example to show the problem using RawGit and Gist:

https://rawgit.com/javidjamae/43f81b4fb654e133cfe9/raw/87abe3a5351d120bdd316503d221f02ad6d3f699/index.html

Open Chrome developer tools and look at the network tab on page load. You can use the sliders on the timeline to narrow down for a specific period of time and see which scripts were loaded when. You may need to update several times to make sure shim.js was loaded long before the DOMContentLoaded event, but you will notice that second.js is never loaded before DOMContentLoaded regardless of whether shim.js is loaded and execution ends.

Note. I couldn't use JSFiddle because it doesn't load everything you define, including external scripts, until DOMContentLoaded.

Update 2:

For some background: we are building a third party product embedded on hundreds of different sites. The first script is actually a shim that extracts some identifying information and then calls the second script using the identifying information as part of the url. We jump to each other to use the second script directly, but until all our clients jump to using the second script directly, we need a shim to efficiently route them automatically. Both the first and second script are dynamically generated (i.e. server-side) scripts that sit behind the CDN.

+3


source to share


1 answer


As pointed out in the comments, given that your first script relies on the DOM to load the second script, I don't think you will find a pure JS solution.

I suggest writing a server-side script (like jsp) that will be used as a js file. You can have a .js extension to say jsp.



In the server code, you can get the second script passing in the appropriate parameters. <script src="/webapp/jsp_file.js">

Then in the jsp file use some library tags to import the second js.

This has an ugly flaw in your server becoming a real client for the second js - can lead to performance issues and may also break the second js file if it relies on request headers / ip filtering.

0


source







All Articles