it-swarm.com.ru

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

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

Итак, где есть правильное место для размещения тегов <script>?

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

1276
mipadi

Вот что происходит, когда браузер загружает веб-сайт с тегом <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/#feat=script-async , 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/#feat=script-defer , 94,59% всех браузеров поддерживают это. 94,92% поддерживают его хотя бы частично.

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

Заключение

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

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

1606
Bart

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

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

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

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

224
Cammel

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

<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 поддерживают неблокирующее выполнение. Вот пример асинхронная загрузка Google Maps API .

64
Salman A

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

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

Есть некоторые отличные слайды от Стива Соудерса (эксперт по производительности на стороне клиента) о:

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

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

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

22
Andrew Hare

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

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

9
Allain Lalonde
<script src="myjs.js"></script>
</body>

тег script должен всегда использоваться перед body close или Bottom в файле HTML.

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

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

8
AmanKumar

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

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

5
dkretz

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

Есть несколько различных методов, но наиболее прямым является использование document.createElement («script»), когда инициируется событие window.onload. Затем сценарий загружается первым при отображении самой страницы, что не влияет на время, в течение которого пользователь должен ждать появления страницы.

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

Для получения дополнительной информации см. Пост Сочетание асинхронных скриптов от Стива Соудерса (создатель YSlow, но теперь в Google).

1
stpe

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

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

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

0
Sanjeev S

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

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

0
ahmedmzl
  • Если вы все еще заботитесь о поддержке и производительности в IE <10, лучше ВСЕГДА сделать так, чтобы ваш скрипт помечал последние теги вашего тела HTML. Таким образом, вы уверены, что остальная часть DOM была загружена, и вы не будете блокировать и рендеринг.

  • Если вас больше не волнует IE <10, вы можете поместить свои скрипты в заголовок документа и использовать defer, чтобы они работали только после загрузки вашего DOM (<script type="text/javascript" src="path/to/script1.js" defer></script>). Если вы по-прежнему хотите, чтобы ваш код работал в IE <10, не забудьте обернуть ваш код даже в window.onload!

0
user5803163

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

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

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

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

https://stackoverflow.com/a/53821485/731548

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

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

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

https://caniuse.com/#feat=es6-module

0
cquezel

Я думаю, что это зависит от исполнения веб-страницы. Если страница, которую вы хотите отобразить, не может отображаться должным образом без предварительной загрузки JavaScript, то сначала следует включить файл JavaScript. Но если вы можете отображать/отображать веб-страницу без первоначальной загрузки файла JavaScript, то вам следует поместить код JavaScript внизу страницы. Поскольку он будет эмулировать быструю загрузку страницы, и с точки зрения пользователя кажется, что эта страница загружается быстрее. 

0
Amit Mhaske

Скрипт блокирует загрузку DOM, пока он не загружен и не выполнен.

Если вы поместите сценарии в конце <body>, все DOM смогут загрузить и отобразить (страница будет «отображаться» быстрее). <script> будет иметь доступ ко всем этим элементам DOM.

С другой стороны, размещение его после <body> start или выше запустит скрипт (там, где до сих пор нет элементов DOM).

Вы включаете jQuery, что означает, что вы можете разместить его где угодно и использовать .ready ()

0
Szymon Toda

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

0
Tech AG

В конце HTML-документа

Так что это не повлияет на загрузку HTML-документа в браузере во время выполнения.

0
Mr_Blue