Атрибут src: подключение внешних скриптов в JavaScript
Подключение внешних скриптов через атрибут src
Самый эффективный способ для большинства современных проектов
Для оптимальной загрузки страницы рекомендуется использовать атрибут src вместе с defer. Это позволяет браузеру загружать скрипт параллельно с разметкой, но выполнять его только после полного парсинга HTML, сохраняя порядок скриптов.
<script src="js/app.js" defer></script>Js src (атрибут src тега script)
В таком случае скрипт не блокирует рендеринг, а DOM гарантированно готов к моменту выполнения. Подходит для скриптов, которым нужен весь DOM, и порядок их выполнения важен.
Потенциальные проблемы:
- Если скрипт использует
document.write, то приdeferон не сработает (это устаревшая практика). - Браузеры, не поддерживающие defer (например, очень старые), проигнорируют атрибут и загрузят скрипт синхронно. Однако для современных сайтов это неактуально.
Как просто подключить внешний скрипт без задержек?
Базовое синхронное подключение. Скрипт загружается и выполняется немедленно, блокируя парсинг HTML до завершения.
<script src="scripts/analytics.js"></script>как подключить js (как подключить javascript к html)
Используется для критически важных скриптов (например, системы аналитики), которые должны выполниться раньше остального контента. Однако это замедляет загрузку страницы.
Ошибка: если скрипт очень большой, страница будет долго оставаться пустой. Рекомендуется размещать такие скрипты в конце <body>.
Как загрузить скрипт асинхронно, не дожидаясь HTML?
Использование атрибута async. Скрипт загружается параллельно с HTML и выполняется сразу после загрузки, не дожидаясь полного парсинга.
<script src="https://example.com/widget.js" async></script>
Подходит для независимых скриптов (счётчики, реклама), которые не зависят от DOM или других скриптов. Порядок выполнения не гарантируется.
Проблема: если один асинхронный скрипт зависит от другого, они могут выполниться в непредсказуемом порядке. Решение - не использовать async для таких зависимостей.
Как гарантировать выполнение скрипта после загрузки HTML, сохраняя порядок?
Атрибут defer (рассмотрен в основном решении). Альтернатива - разместить скрипт в конце <body> без атрибутов, но это также блокирует рендеринг.
<script src="js/libs.js" defer></script>
<script src="js/init.js" defer></script>
Порядок выполнения соответствует порядку в HTML. Все отложенные скрипты выполняются до события DOMContentLoaded.
Типичная ошибка: использование defer для скриптов, которые должны выполниться как можно раньше (например, полифилы). В таких случаях лучше async или синхронная загрузка.
Как динамически добавить скрипт на страницу после её загрузки?
Создание элемента <script> через JavaScript и добавление его в DOM. Это позволяет загружать скрипты по требованию.
let script = document.createElement('script');
script.src = 'js/chat.js';
script.onload = function() {
console.log('Чат загружен');
};
document.head.appendChild(script);
Применяется для ленивой загрузки, когда скрипт нужен только после определённого действия пользователя. Скрипты, добавленные таким образом, ведут себя как async по умолчанию (если не указать иное).
Ошибка: если динамический скрипт добавляется до того, как DOM полностью сформирован, может возникнуть конфликт. Решение - использовать DOMContentLoaded или флаги готовности.
Как подключать ES-модули с поддержкой import/export?
Современные браузеры поддерживают атрибут type="module". Скрипты с таким атрибутом автоматически откладываются (как defer) и выполняются в порядке их следования, даже без явного указания.
<script type="module" src="js/main.mjs"></script>
Модули позволяют использовать import и export, а также обеспечивают изоляцию области видимости. Подходит для современных приложений.
Проблема: старые браузеры (IE11) не поддерживают модули. Для них нужна отдельная сборка через <script nomodule> или использование defer с транспиляцией.
Дополнительные атрибуты для src
Атрибут integrity позволяет проверить целостность скрипта через хеш. Атрибут crossorigin используется для скриптов с другого домена, чтобы обрабатывать ошибки или получать доступ к содержимому.
<script src="https://cdn.example.com/lib.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>Расширенные примеры использования атрибута src
Одновременное использование async и defer
Если указать оба атрибута, то async имеет приоритет над defer для HTML-парсера: скрипт будет загружен асинхронно. Если браузер не поддерживает async (например, очень старые версии), то сработает defer. На практике комбинация не используется, так как поведение неоднозначно.
<script src="script.js" async defer></script>
В современных браузерах скрипт выполнится как async (сразу после загрузки), в IE9-10 как defer.
Динамическая загрузка с управлением порядком
Допустим, нужно загрузить библиотеку, а затем скрипт, который от неё зависит. Можно установить async=false у динамического скрипта, чтобы он вёл себя синхронно.
// Загружаем lib.js
let lib = document.createElement('script');
lib.src = 'lib.js';
lib.async = false;
document.head.appendChild(lib);
// Загружаем main.js после lib
let main = document.createElement('script');
main.src = 'main.js';
main.async = false;
document.head.appendChild(main);
Порядок выполнения гарантирован: сначала lib.js, потом main.js, несмотря на асинхронную природу динамических скриптов.
Ленивая загрузка скрипта при появлении в окне просмотра
Используется Intersection Observer для загрузки скрипта, когда элемент становится видимым.
<div id="chat-placeholder" style="height: 500px;"></div>
<script>
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
let script = document.createElement('script');
script.src = 'chat.js';
document.head.appendChild(script);
observer.disconnect();
}
});
observer.observe(document.getElementById('chat-placeholder'));
</script>
Подключение модуля с запасным вариантом для старых браузеров
Используется комбинация type="module" и <script nomodule>.
<script type="module" src="modern.js"></script>
<script nomodule src="legacy.js" defer></script>
Браузеры, поддерживающие модули, загрузят modern.js и проигнорируют nomodule. Старые - наоборот, загрузят legacy.js.
Загрузка скрипта с проверкой целостности (integrity)
Атрибут integrity содержит хеш содержимого файла. Браузер проверяет, что загруженный файл соответствует хешу, предотвращая подмену.
<script src="bootstrap.bundle.min.js"
integrity="sha384-..."
crossorigin="anonymous"></script>
Если хеш не совпадает, скрипт не выполнится, и в консоли появится ошибка. Хеш можно получить через инструменты поставщика (например, CDN) или вычислить заранее.
Использование importmap для разрешения модулей
Атрибут src в сочетании с type="importmap" позволяет переопределять URL модулей.
<script type="importmap">
{
"imports": {
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
<script type="module">
import _ from 'lodash';
console.log(_.add(1, 2));
</script>