9

Is there any difference in declaring my async javascript statically vs dynamically?

static

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript" src="https://foo.bar/myscript.js" async>
  </script>
  ...
</body>
</html>

dynamic

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript">
      var myScript = document.createElement("script");
      myScript.src = 'https://foo.bar/myscript.js';
      myScript.async = !0;
      myScript.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(myScript);
  </script>
  ...
</body>
</html>

I noticed that declaring a script statically let a browser detect it earlier and preload (chrome + firefox).

My goal is to load a javascript in async way in order not to block HTML rendering and other scripts execution. Sametime, I want it to be executed as soon as it's downloaded, having in mind that it requires one element to be in the DOM already. Once downloaded the script is executed and it accesses the my-script-needs-me div. One limitation, I cannot change the script itself.

9
  • you can put this in a callback for window.DOMContentLoaded Commented Mar 17, 2017 at 21:02
  • put what? I wouldn't like to way for the DOMContentLoaded coz there are plenty of another script loading before and after my script. I want to start loading the script as soon as possible and execute it once my div is in DOM without waiting for the rest of DOM to be completed. Commented Mar 17, 2017 at 21:04
  • 2
    dynamic script declaration is non-blocking, whereas static script declaration without async tag blocks until it is evaluated completely Commented Mar 17, 2017 at 21:10
  • 1
    yes, there is no difference. appendChild is asynchronous. Commented Mar 17, 2017 at 23:05
  • 1
    very interesting. it makes sense because async will have the browser immediately begin fetching the script in a separate thread, whereas dynamic declaration will push the method onto the execution queue Commented Mar 31, 2017 at 17:43

4 Answers 4

2

supports async parameters allowing to make this call asynchronous.

The second way you described allows you to have the url as a parameter and bind it. It allows too the use of a callback to do some stuff when your script is loaded.

let scriptElement = document.createElement('script');
let url = `https://maps.googleapis.com/maps/api/js?key=${apiKey}`;//&libraries=geometry
  scriptElement.src = url;
  //Chargement de l'API Google
  scriptElement.onload = () => {
    //API chargée, on peut lancer l'initialisation du composant
    this._initializeMap();
  };

I used this to load Google Maps API, it's not directly in the HTML, so i can modify the URL when my page loads. And when the API is loaded, I an launch treatments that need this API.

Sign up to request clarification or add additional context in comments.

2 Comments

I can you load callback with static script declaration as well. The only this is about dynamic url, that's true, you can have it only with the dynamic script tag creation. My question is more about performance, but your point is totally valid and clear.
I believe that static declaration is faster. With dynamic, you create a static link, but you have to count the time required for creating the script tag. So, static is faster.
1

you can use defer for that instead of async.

your script will execute right after html be parsed.

5 Comments

I want to execute the script once it's loaded and don't want to wait until the whole page is parsed.
You can place your script tag at the top of head tag. And you can use IIFE to execute your code immediately.
I cannot place my script tag at the top of the head because it requires the my-script-needs-me element to present at the page.
Could you please clarify how IIFE makes the difference?
IIFE will be the same as function call. you can check the speed here jsperf.com/iife-vs-iife-call-vs-named-vs-declare/1
1

Static

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript" src="https://foo.bar/myscript.js" async>
  </script>
  ...
</body>
</html>

As you know, HTML is parsed top-bottom. So, if it placed within body tag, then as soon as parsed, if it is an IIFE or the file myscript.js contains a function call, it will execute immediately.

So, inside, body, put it the script at the bottom will help you to execute it after the div has loaded.

But we can't ensure because of caching.

If the browser cache the script and if it is an IIFE or contains a function call, we can't predict the behaviour.

Dynamic

In dynamic also, it depends on the order.

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript">
      var myScript = document.createElement("script");
      myScript.src = 'https://foo.bar/myscript.js';
      myScript.async = !0;
      myScript.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(myScript);
  </script>
  ...
</body>
</html>

In both cases, it will render after HTML contents.

The best way to ensure it loads only after all contents are loaded is

Giving an eventListener on Window.

Check the code below

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript">
     function load(){
        var myScript = document.createElement("script");
        myScript.src = 'https://foo.bar/myscript.js';
        myScript.async = !0;
        myScript.type = 'text/javascript';
        document.getElementsByTagName('head')[0].appendChild(myScript);
     }
     window.addEventListener("DOMContentLoaded",load);
  </script>
  ...
</body>
</html>

Check this line window.addEventListener("DOMContentLoaded",load);.

The DOMContentLoaded is similar to jQuery's $(document).ready(). It will trigger the callback function when the HTML is properly loaded. So, you don't have to check for the existence of the HTML Element.

2 Comments

from my tests, even if the script is cached (static approach) it won't be executed earlier than declared. And another thing, the DOMContentLoaded, as well as the bottom of the page, would work if there is no other code after my script but there are plenty of it and I would like to make it's not preventing my async script from executing once my div is rendered.
@AlexeyStrakh then, in the head, add an eventlistener to the window for 100 mS and in the callback, check if the div is undefined or not. if not, clear the eventListener and start the execution.
1

From what I've learned it's better to go with static way to declare an async script (in my particular scenario) than dynamic. Here some of why(s):

  1. static async script declaration is detected by a browser and kicked off right away (at the very top of the page processing);
  2. (deferred from #1) a browser puts the script request earlier in requests queue and if you have enough (30-40 requests per page load) it could be crucial to be in first 10 requests, not at the position 30-40;
  3. adding a script dynamically to the head from the body doesn't introduce any performance advantage against the static declaration as long as whole head is already processed and it won't delay execution of the statically declared script;
  4. at the moment when we reach the script declaration, static will work instantly because it's already pre-loaded and ready to be executed (in most cases, async is crucial here) while the dynamic script declaration will just kick off the request to download the script and only after then execute it;

I hope my thoughts will help someone as well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.