From c0d638a127213a282b2d6b265833cbf7f5bd5b78 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Sat, 5 Sep 2020 16:37:04 +0300 Subject: [PATCH] minor fixes --- .../02-script-async-defer/article.md | 80 ++++++++++--------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/2-ui/5-loading/02-script-async-defer/article.md b/2-ui/5-loading/02-script-async-defer/article.md index ca82a730..1c02c1ea 100644 --- a/2-ui/5-loading/02-script-async-defer/article.md +++ b/2-ui/5-loading/02-script-async-defer/article.md @@ -37,7 +37,7 @@ Luckily, there are two ` @@ -68,40 +70,44 @@ The following example demonstrates that: ``` 1. The page content shows up immediately. -2. `DOMContentLoaded` waits for the deferred script. It only triggers when the script `(2)` is downloaded and executed. +2. `DOMContentLoaded` event handler waits for the deferred script. It only triggers when the script is downloaded and executed. -Deferred scripts keep their relative order, just like regular scripts. +**Deferred scripts keep their relative order, just like regular scripts.** -So, if we have a long script first, and then a smaller one, then the latter one waits. +Let's say, we have two deferred scripts: the `long.js` and then `small.js`: ```html ``` -```smart header="The small script downloads first, runs second" -Browsers scan the page for scripts and download them in parallel, to improve performance. So in the example above both scripts download in parallel. The `small.js` probably makes it first. +Browsers scan the page for scripts and download them in parallel, to improve performance. So in the example above both scripts download in parallel. The `small.js` probably finishes first. -But the specification requires scripts to execute in the document order, so it waits for `long.js` to execute. -``` +...But the `defer` atribute, besides telling the browser "not to block", ensures that the relative order is kept. So even though `small.js` loads first, it still waits and runs after `long.js` executes. + +That may be important for cases when we need to load a JavaScript library and then a script that depends on it. ```smart header="The `defer` attribute is only for external scripts" The `defer` attribute is ignored if the ` ``` - ## Dynamic scripts + +There's one more important way of adding a script to the page. -We can also add a script dynamically using JavaScript: +We can create a script and append it to the document dynamically using JavaScript: ```js run let script = document.createElement('script'); @@ -146,20 +153,11 @@ That is: - They don't wait for anything, nothing waits for them. - The script that loads first -- runs first ("load-first" order). +This can be changed if we explicitly set `script.async=true`. Then scripts will be executed in the document order, just like `defer`. -```js run -let script = document.createElement('script'); -script.src = "/article/script-async-defer/long.js"; - -*!* -script.async = false; -*/!* - -document.body.append(script); -``` - -For example, here we add two scripts. Without `script.async=false` they would execute in load-first order (the `small.js` probably first). But with that flag the order is "as in the document": +In this example, `loadScript(src)` function adds a script and also sets `async` to `false`. +So `long.js` always runs first (as it's added first): ```js run function loadScript(src) { @@ -174,6 +172,10 @@ loadScript("/article/script-async-defer/long.js"); loadScript("/article/script-async-defer/small.js"); ``` +Without `script.async=false`, scripts would execute in default, load-first order (the `small.js` probably first). + +Again, as with the `defer`, the order matters if we'd like to load a library and then another script that depends on it. + ## Summary @@ -186,12 +188,14 @@ But there are also essential differences between them: | `async` | *Load-first order*. Their document order doesn't matter -- which loads first | Irrelevant. May load and execute while the document has not yet been fully downloaded. That happens if scripts are small or cached, and the document is long enough. | | `defer` | *Document order* (as they go in the document). | Execute after the document is loaded and parsed (they wait if needed), right before `DOMContentLoaded`. | +In practice, `defer` is used for scripts that need the whole DOM and/or their relative execution order is important. + +And `async` is used for independent scripts, like counters or ads. And their relative execution order does not matter. + ```warn header="Page without scripts should be usable" -Please note that if you're using `defer`, then the page is visible *before* the script loads. +Please note: if you're using `defer` or `async`, then user will see the the page *before* the script loads. -So the user may read the page, but some graphical components are probably not ready yet. +In such case, some graphical components are probably not initialized yet. -There should be "loading" indications in the proper places, and disabled buttons should show as such, so the user can clearly see what's ready and what's not. +Don't forget to put "loading" indication and disable buttons that aren't functional yet. Let the user clearly see what he can do on the page, and what's still getting ready. ``` - -In practice, `defer` is used for scripts that need the whole DOM and/or their relative execution order is important. And `async` is used for independent scripts, like counters or ads. And their relative execution order does not matter.