Динамические скрипты. Атрибуты async, defer

Грузим html

Поговорим про то, как загружается html страница.


<!DOCTYPE html> // когда html документ попадает в браузер. он идентифицирует ее как html с помощью DOCTYPE и далее начинает ее загрузку
<html lang="en">  // видит, что это html с определенным языком
<head> // далее грузит head
    <meta charset="UTF-8"> // подгружает мета теги
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title> // грузит тайтл.
    // далее грузит всякие css файлы, шрифты и так далее. Смотря что у вас тут будет стоять.
</head>
<body> // далее идет к body и так далее тег за тегом
  <p> hi br/o </p>
  <p> hi ne br/o </p>
        <script src="script.js"></script> // подгружает скрпит и потом все конец.
</body>
</html>

script ставят в конце body для того, что бы сначала страница загрузилась, а уже потом пошла динамика и логика. Если мы скрипт поставим в head, то он начнет грузиться раньше элементов на странице с которыми он работает и так как элементов еще нет, ему не с чем будет работать. Так же скрипт может быть большим, дом структура будет всегда ждать пока скрипт загрузится, что может привести к лагам и долгой загрузки самой странице. Так вот если у нас будет очень много верстки получается нужно ждать пока все загрузится прежде чем мы подгрузим сам script? Людям придется ждать? Эта проблема не будет заметна если у человека быстрый интернет, но если у пользователя есть траблы с интернетом, то на больших сайтах эта проблемка может вылезти. Для решения этих проблем есть два атрибута async и defer.

defer

Что бы назначить атрибут defer просто пишем его у тега script

<script defer src="script.js"></script>

Атрибут defer подгружает скрипт после того, как html будет загружена. Теперь если мы поставим скрипт вначале body и попробуем получить элемент на странице, то все сработает.
Так выгляди тело html документа.

<body>
  
  <script defer src="script.js"></script> // скрипт грузит до элементов
  <p> hi br/o </p>
  <p> hi ne br/o </p>
        
</body>
deferYES

Если же мы уберем defer, то получим пустой псевдомассив:

deferNO

Также defer не блокирует html документ.
Если у нас будет два скрипта, то с defer они будут грузиться по очередно в не зависимости от своих объемов.

async

async позволяет сделать скрипты независимыми, они никого не будут ждать, как загрузились так и загрузились. Нужно это для подключения сторонних скриптов, которые не зависят от вашей дом структуры и скриптов.

<script async src="script.js"></script>

Подключаем скрипты динамически

Мы можем поместить скрипт на страницу динамически.

function loadScript(src) { // создаем функцию для подгрузки скриптов.

    const script = document.createElement('script'); // создаем свой тег script
    script.src = src; // пишем путь. Его передаем аргументом
    script.async = false; // динамически загружаемые скрипты ведут себя по умолчанию как async, они никого не ждут.
    // что бы это изменить просто отрубаем async.
    // обращаемся к атрибуту и ставим false.
    document.body.append(script); // Добавляем на страницу. Таким образом test.js будет запускаться лишь когда здесь добавится на страницу.
    // само собой у вас там свои файлы будут.
}

loadScript('test.js'); // мой файл test.js лежащий в корне.
loadScript('blaBla.js') // так можно добавить еще один файл. пишем другой путь и все.
// из за того, что у нас стоит async в false, эти скрипты будут работать по очереди.