Где я должен поместить теги <script> в разметку HTML?

При встраивании JavaScript в документ HTML, где правильное место для размещения <script> теги и включены JavaScript? Кажется, я помню, что вы не должны помещать их в <head> раздел, но размещая в начале <body> Секция тоже плохая, так как JavaScript должен быть проанализирован, прежде чем страница будет полностью отрисована (или что-то в этом роде). Это похоже на конец <body> раздел как логическое место для <script> теги.

Итак, где находится правильное место, чтобы положить <script> теги?

(Этот вопрос относится к этому вопросу, в котором было предложено перенести вызовы функций JavaScript из <a> теги к <script> теги. Я специально использую jQuery, но более общие ответы также уместны.)

27 ответов

Решение

Вот что происходит, когда браузер загружает сайт с <script> отметьте это:

  1. Получить страницу HTML (например, index.html)
  2. Начните разбор HTML
  3. Парсер встречает <script> тег, ссылающийся на внешний файл скрипта.
  4. Браузер запрашивает файл скрипта. Тем временем парсер блокирует и прекращает анализ другого HTML-кода на вашей странице.
  5. Через некоторое время скрипт загружается и впоследствии выполняется.
  6. Парсер продолжает анализ остальной части HTML-документа.

Шаг № 4 вызывает плохой пользовательский опыт. Ваш сайт в основном перестает загружаться, пока вы не загрузите все скрипты. Если есть одна вещь, которую пользователи ненавидят, это ждет загрузки сайта.

Почему это вообще происходит?

Любой скрипт может вставить свой собственный HTML через document.write() или другие манипуляции с DOM. Это подразумевает, что синтаксический анализатор должен ждать, пока скрипт не будет загружен и выполнен, прежде чем он сможет безопасно проанализировать остальную часть документа. В конце концов, скрипт мог вставить свой собственный HTML в документ.

Однако большинство разработчиков JavaScript больше не манипулируют DOM во время загрузки документа. Вместо этого они ждут, пока документ не будет загружен, прежде чем изменять его. Например:

<!-- index.html -->
<html>
    <head>
        <title>My Page</title>
        <script type="text/javascript" src="my-script.js"></script>
    </head>
    <body>
        <div id="user-greeting">Welcome back, user</div>
    </body>
</html>

Javascript:

// my-script.js
document.addEventListener("DOMContentLoaded", function() { 
    // this function runs when the DOM is ready, i.e. when the document has been parsed
    document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});

Поскольку ваш браузер не знает, что my-script.js не будет изменять документ, пока он не будет загружен и выполнен, синтаксический анализатор прекращает синтаксический анализ.

Устаревшая рекомендация

Старый подход к решению этой проблемы заключался в <script> теги в нижней части вашего <body>потому что это гарантирует, что парсер не заблокирован до самого конца.

У этого подхода есть своя собственная проблема: браузер не может начать загрузку скриптов, пока весь документ не будет проанализирован. Для больших веб-сайтов с большими сценариями и таблицами стилей возможность загрузки сценария как можно скорее очень важна для производительности. Если ваш сайт не загружается в течение 2 секунд, люди перейдут на другой сайт.

В оптимальном решении браузер начнет загрузку ваших сценариев как можно скорее, в то же время анализируя остальную часть вашего документа.

Современный подход

Сегодня браузеры поддерживают async а также defer атрибуты на скриптах. Эти атрибуты сообщают браузеру, что безопасно продолжать анализ во время загрузки скриптов.

асинхронной

<script type="text/javascript" src="path/to/script1.js" async></script>
<script type="text/javascript" src="path/to/script2.js" async></script>

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

Согласно http://caniuse.com/, 94,57% всех браузеров поддерживают это.

откладывать

<script type="text/javascript" src="path/to/script1.js" defer></script>
<script type="text/javascript" src="path/to/script2.js" defer></script>

Сценарии с атрибутом defer выполняются по порядку (т. Е. Сначала сценарий 1, затем сценарий 2). Это также не блокирует браузер.

В отличие от асинхронных сценариев, отложенные сценарии выполняются только после загрузки всего документа.

Согласно http://caniuse.com/, 94,59% всех браузеров поддерживают это. 94,92% поддерживают его хотя бы частично.

Важное замечание о совместимости браузера: в некоторых случаях IE <= 9 может выполнять отложенные сценарии не по порядку. Если вам нужно поддерживать эти браузеры, пожалуйста, прочтите это в первую очередь!

Заключение

Текущий уровень техники заключается в размещении сценариев в <head> пометить и использовать async или же defer атрибутов. Это позволяет загружать ваши скрипты как можно быстрее, не блокируя ваш браузер.

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

Как раз перед закрывающим тегом тела, как указано на

http://developer.yahoo.com/performance/rules.html

Поместите сценарии внизу

Проблема, вызванная сценариями, заключается в том, что они блокируют параллельные загрузки. Спецификация HTTP/1.1 предполагает, что браузеры загружают не более двух компонентов параллельно для каждого имени хоста. Если вы обслуживаете свои изображения с нескольких имен хостов, вы можете получить более двух загрузок для одновременного выполнения. Однако во время загрузки скрипта браузер не будет запускать другие загрузки, даже на разных именах хостов.

Неблокирующие теги скрипта могут быть размещены где угодно:

<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
  • async скрипт будет выполняться асинхронно, как только он станет доступен
  • defer скрипт выполняется по окончании разбора документа
  • async defer скрипт возвращается к отложенному поведению, если асинхронность не поддерживается

Такие сценарии будут выполняться асинхронно / после того, как документ будет готов, что означает, что вы не можете сделать это:

<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
  * might throw "jQuery is not defined" error
  * defer will not work either
-->

Или это:

<script src="document.write(something).js" async></script>
<!--
  * might issue "cannot write into document from an asynchronous script" warning
  * defer will not work either
-->

Или это:

<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
  * might throw "jQuery is not defined" error (no guarantee which script runs first)
  * defer will work in sane browsers
-->

Или это:

<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
  * might not locate #header (script could fire before parser looks at the next line)
  * defer will work in sane browsers
-->

Сказав это, асинхронные сценарии предлагают следующие преимущества:

  • Параллельная загрузка ресурсов:
    Браузер может загружать таблицы стилей, изображения и другие сценарии параллельно, не дожидаясь загрузки и выполнения сценария.
  • Независимость от источника заказа:
    Вы можете размещать скрипты внутри головы или тела, не беспокоясь о блокировке (полезно, если вы используете CMS). Порядок исполнения все еще имеет значение, хотя.

Можно обойти проблемы порядка выполнения с помощью внешних сценариев, поддерживающих обратные вызовы. Многие сторонние API JavaScript поддерживают неблокирующее выполнение. Вот пример загрузки API Карт Google в асинхронном режиме.

Стандартный совет, продвигаемый Yahoo! Исключительная производительность команды, это поставить <script> теги в конце тела документа, чтобы они не блокировали отображение страницы.

Но есть несколько новых подходов, которые предлагают лучшую производительность, как описано в этом ответе о времени загрузки файла Google Analytics JavaScript:

Стив Соудерс (эксперт по работе с клиентами) предлагает несколько отличных слайдов о:

  • Различные методы для загрузки внешних файлов JavaScript параллельно
  • их влияние на время загрузки и рендеринг страницы
  • какие индикаторы "в процессе" отображает браузер (например, "загрузка" в строке состояния, курсор мыши в виде песочных часов).

Современный подход в 2019 году - использование скриптов типа модуля ES6.

<script type="module" src="..."></script>

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

Различия между скриптом и модулем описаны здесь:

/questions/23755753/klassicheskie-skriptyi-vs-skriptyi-modulya-v-javascript/23755759#23755759

Выполнение модуля по сравнению со сценарием описано здесь:

https://developers.google.com/web/fundamentals/primers/modules

Поддержка показана здесь:

https://caniuse.com/

Если вы используете JQuery, поместите javascript в любое удобное для вас место и используйте $(document).ready() чтобы убедиться, что вещи загружены правильно, прежде чем выполнять какие-либо функции.

На заметку: мне нравятся все мои теги сценариев в <head> раздел, как это, кажется, самое чистое место.

<script src="myjs.js"></script>
</body>

Тег script следует использовать всегда перед закрытием тела или снизу в HTML- файле.

затем вы можете увидеть содержимое страницы перед загрузкой файла js.

проверьте это, если требуется: http://stevesouders.com/hpws/rule-js-bottom.php

Лучшее место, чтобы положить<script> тег перед закрытием </body>тег, поэтому его загрузка и выполнение не блокируют браузер для синтаксического анализа html в документе,

Также загрузка js-файлов извне имеет свои преимущества, например, они будут кэшироваться браузерами и могут ускорить время загрузки страницы, она разделяет код HTML и JavaScript и помогает лучше управлять базой кода.

но современные браузеры также поддерживают некоторые другие оптимальные способы, например async а также defer загружать внешние javascript файлы.

Асинхронный и отложенный

Обычно выполнение HTML-страницы начинается построчно. При обнаружении внешнего элемента JavaScript анализ HTML останавливается до тех пор, пока JavaScript не будет загружен и готов к выполнению. Это нормальное выполнение страницы можно изменить с помощьюdefer а также async атрибут.

Defer

Когда используется атрибут defer, JavaScript загружается параллельно с синтаксическим анализом HTML, но будет выполняться только после завершения полного анализа HTML.

<script src="/local-js-path/myScript.js" defer></script>

Async

Когда используется атрибут async, JavaScript загружается, как только встречается сценарий, и после загрузки он будет выполняться асинхронно (параллельно) вместе с анализом HTML.

<script src="/local-js-path/myScript.js" async></script>

Когда использовать какие атрибуты

  • Если ваш сценарий не зависит от других сценариев и является модульным, используйте async.
  • Если вы загружаете script1 и script2 с помощью async, оба будут выполняться
    параллельно вместе с анализом HTML, как только они будут загружены
    и доступны.
  • Если ваш сценарий зависит от другого сценария, используйте defer для обоих:
  • Когда script1 и script2 загружаются в таком порядке с defer, то script1 гарантированно выполнится первым,
  • Затем script2 будет выполняться после того, как script1 будет полностью выполнен.
  • Это необходимо сделать, если сценарий 2 зависит от сценария 1.
  • Если ваш сценарий достаточно мал и зависит от другого сценария типа async затем используйте свой сценарий без атрибутов и поместите его над всеми async скрипты.

ссылка:knowledgehills.com

XHTML не будет проверяться, если скрипт находится не в элементе head, а в другом месте. Оказывается, это может быть везде.

Вы можете отложить выполнение с помощью чего-то вроде jQuery, поэтому не имеет значения, где оно находится (за исключением небольшого снижения производительности во время синтаксического анализа).

Обычный (и общепринятый) ответ - "внизу", потому что тогда весь DOM будет загружен, прежде чем что-либо сможет начать выполняться.

Существуют несогласные по разным причинам, начиная с имеющейся практики намеренного начала исполнения с события загрузки страницы.

Зависит от того, если вы загружаете скрипт, необходимый для стилизации вашей страницы / используя действия на вашей странице (например, нажатие кнопки), тогда вам лучше разместить его сверху. Если ваш стиль на 100% CSS и у вас есть все запасные варианты для действий кнопки, вы можете поместить его внизу.

Или, что лучше (если это не проблема), вы можете создать модальное окно загрузки, поместить свой javascript внизу страницы и заставить его исчезнуть при загрузке последней строки вашего скрипта. Таким образом, вы можете избежать использования пользователями действий на вашей странице до загрузки сценариев. А также избегайте неправильной укладки.

Включение скриптов в конце используется в основном там, где контент / стили сайта должны быть показаны первыми.

включение сценариев в заголовок загружает сценарии заранее и может использоваться до загрузки всего веб-сайта.

если сценарии введены в конце концов, проверка произойдет только после загрузки всех стилей и дизайна, что не приветствуется для быстро реагирующих веб-сайтов.

Вы можете разместить большую часть <script> ссылки в конце <body>,
Но если на вашей странице есть активные компоненты, использующие внешние скрипты,
тогда их зависимость (js-файлы) должна предшествовать этому (в идеале в заголовке).

В зависимости от сценария и его использования наилучшим вариантом (с точки зрения загрузки страницы и времени рендеринга) может быть не использование обычного тега