简体   繁体   中英

How can I make an inserted javascript load before DOMContentLoaded?

I have a remote script that is referenced in the HEAD of my page HTML. This first script loads and inserts another script by appending it to the DOM. Both scripts exist on a different domain than the page they're embedded on.

The contents 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 out in Chrome (Version 43.0.2357.81, 64-bit), I see that the first script is loaded very early in the timeline. But, the second script is never loaded until right after the DOMContentLoaded event occurs.

The following screenshot shows the load/execution timeline for the two scripts. The first script is the top item and the second script is the bottom item. Ignore the item in the middle, which is a different artifact that I couldn't filter out of the timeline for the screenshot. The vertical blue line is the DOMContentLoaded event.

在此输入图像描述

I've tried with and without async and deferred, but that seems to have no effect. Is there any way to force the loading of the second script to be instantaneous, rather than having it wait until the DOMContentLoaded event occurs?

Update:

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

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

Open the Chrome developer tools and look at the network tab as the page loads. You can use the sliders on the timeline to narrow in on a certain time period and see which scripts were loaded when. You may have to refresh a few times to make sure the shim.js was loaded well before the DOMContentLoaded event, but you'll notice that second.js is never loaded before DOMContentLoaded no matter when shim.js is loaded and finishes execution.

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

Update 2:

For some background: We're building a 3rd party product that's 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're transitioning everybody over to use the second script directly, but until all of our customers are transitioned over to using the second script directly, we need the shim to effectively route them automatically. Both the first and second script are dynamically generated (ie server-side rendered) scripts that sit behind a CDN.

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 a jsp) that gets served as js file. You can have .js extension mapped to say a jsp.

In your server code you can fetch the second script passing in the appropriate parameters. <script src="/webapp/jsp_file.js"> Then in the jsp file use some tag libraries to import the second js.

This has an ugly downside of your server becoming the real client for the second js - might result in performance issues & may also break the second js file if it relies on request headers/ip filtering.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM