Loadable-components: Add the choose between defer or async

Created on 15 May 2019  ·  7Comments  ·  Source: gregberge/loadable-components

✨Enhancement

Add the ability to insert scripts using defer or async. By default, async is the best choice but it could creates some issues with CSS.

See #258 for context.

enhancement ✨ wontfix

Most helpful comment

Thanks for opening this issue!

Actually, it's not only css problems, but js too. See this stackoverflow answer for more context.

There's several options that the developer could potentially choose from for script and link elements:

  • <script>
  • <script async>
  • <script defer>
  • There's also <script type="module"> and <script type="module" async>
  • <link rel="prefetch">
  • <link rel="preload">

If you scripts are independent from each other using async is totally fine (and even recommended for speed).

If you have a script that depends on another script async doesn't guarantee that they will be executed in the right order, meaning that they might fail at runtime depending on the browser's implementation and network speed. If you want them to work in a deterministic way you'll have to either load them synchronously (no attribute) or use defer.

When the order of execution is important, we need to place them in the right order on the page. This probably complicates things a bit because it could require having these in the right order in loadable-stats.json. Maybe this thread helps to get some context. Also, this plugin was created for a similar purpose :)

All 7 comments

Thanks for opening this issue!

Actually, it's not only css problems, but js too. See this stackoverflow answer for more context.

There's several options that the developer could potentially choose from for script and link elements:

  • <script>
  • <script async>
  • <script defer>
  • There's also <script type="module"> and <script type="module" async>
  • <link rel="prefetch">
  • <link rel="preload">

If you scripts are independent from each other using async is totally fine (and even recommended for speed).

If you have a script that depends on another script async doesn't guarantee that they will be executed in the right order, meaning that they might fail at runtime depending on the browser's implementation and network speed. If you want them to work in a deterministic way you'll have to either load them synchronously (no attribute) or use defer.

When the order of execution is important, we need to place them in the right order on the page. This probably complicates things a bit because it could require having these in the right order in loadable-stats.json. Maybe this thread helps to get some context. Also, this plugin was created for a similar purpose :)

@yairkukielka thanks for the precision! We have to address that point seriously.

Thanks, @yairkukielka for the list. I have a few additions.

The way async and defer behave is different depending on whether the script is dynamically injected or present during the first html pass. For example, to get "deferred" behavior out of a dynamically injected script, it must use <script async="false"></script> instead of the deferred attribute. To preserve consistent behavior, chunks extracted for server render would have to rendered with <script defer></script> while those same chunks would need <script async="false"></script> when injected through the loadable() runtime.

Async:

Dynamically inserted scripts (using document.createElement()) load asynchronously by default, so to turn on synchronous loading (i.e. scripts load in the order they were inserted) set async="false".

Defer:

To achieve a similar effect for dynamically inserted scripts use async="false" instead. Scripts with the defer attribute will execute in the order in which they appear in the document.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#Attributes

Personally I think it's best to leave resource hints such as <link rel="prefetch"> out of this feature request since they don't control execution of scripts, just network prefetch.

https://www.w3.org/TR/resource-hints/

Async is quite interesting, as long as it uses CPU while Network is still in use, not interleaving their work.
However - the result is not quite “safe” - script could be ready far prior DOM, and you have to wrap boot with old good DOM Ready.

What would be really interesting - https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/
https://developers.google.com/web/updates/2017/12/modulepreload
https://github.com/zeit/next.js/issues/8438

Has anyone taken this yet? I just spent hours debugging and it turned out to be caused by the out-of-order script executions related to this, haha!

I would gladly work on this if no one has yet.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Friendly bump!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sinwailam193 picture sinwailam193  ·  6Comments

wellyshen picture wellyshen  ·  7Comments

mschipperheyn picture mschipperheyn  ·  5Comments

bitttttten picture bitttttten  ·  8Comments

luishdz1010 picture luishdz1010  ·  6Comments