В бесчисленных местах онлайн я видел рекомендацию включить CSS до JavaScript. Рассуждения, как правило, имеют следующую форму :
Когда дело доходит до заказа вашего CSS и JavaScript, вы хотите, чтобы ваш CSS был на первом месте. Причина в том, что поток рендеринга имеет всю информацию о стиле, необходимую для отображения страницы. Если JavaScript включает в себя на первом месте, движок JavaScript должен проанализировать все это, прежде чем перейти к следующему набору ресурсов. Это означает, что поток рендеринга не может полностью показать страницу, так как он не имеет всех необходимых стилей.
Мое реальное тестирование показывает что-то совсем другое:
Мой тест жгут
Я использую следующий скрипт Ruby для генерации определенных задержек для различных ресурсов:
require 'rubygems'
require 'eventmachine'
require 'evma_httpserver'
require 'date'
class Handler < EventMachine::Connection
include EventMachine::HttpServer
def process_http_request
resp = EventMachine::DelegatedHttpResponse.new( self )
return unless @http_query_string
path = @http_path_info
array = @http_query_string.split("&").map{|s| s.split("=")}.flatten
parsed = Hash[*array]
delay = parsed["delay"].to_i / 1000.0
jsdelay = parsed["jsdelay"].to_i
delay = 5 if (delay > 5)
jsdelay = 5000 if (jsdelay > 5000)
delay = 0 if (delay < 0)
jsdelay = 0 if (jsdelay < 0)
# Block which fulfills the request
operation = proc do
sleep delay
if path.match(/.js$/)
resp.status = 200
resp.headers["Content-Type"] = "text/javascript"
resp.content = "(function(){
var start = new Date();
while(new Date() - start < #{jsdelay}){}
})();"
end
if path.match(/.css$/)
resp.status = 200
resp.headers["Content-Type"] = "text/css"
resp.content = "body {font-size: 50px;}"
end
end
# Callback block to execute once the request is fulfilled
callback = proc do |res|
resp.send_response
end
# Let the thread pool (20 Ruby threads) handle request
EM.defer(operation, callback)
end
end
EventMachine::run {
EventMachine::start_server("0.0.0.0", 8081, Handler)
puts "Listening..."
}
Вышеупомянутый мини-сервер позволяет мне устанавливать произвольные задержки для файлов JavaScript (как сервера, так и клиента) и произвольные задержки CSS. Например, http://10.0.0.50:8081/test.css?delay=500
дает мне 500 мс задержки при передаче CSS.
Я использую следующую страницу для тестирования.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script type='text/javascript'>
var startTime = new Date();
</script>
<link href="http://10.0.0.50:8081/test.css?delay=500" type="text/css" rel="stylesheet">
<script type="text/javascript" src="http://10.0.0.50:8081/test2.js?delay=400&jsdelay=1000"></script>
</head>
<body>
<p>
Elapsed time is:
<script type='text/javascript'>
document.write(new Date() - startTime);
</script>
</p>
</body>
</html>
Когда я сначала включаю CSS, страница отрисовывается за 1,5 секунды:
Когда я сначала включаю JavaScript, рендеринг страницы занимает 1,4 секунды:
Я получаю похожие результаты в Chrome, Firefox и Internet Explorer. В Opera, однако, порядок не имеет значения.
Кажется, что происходит то, что интерпретатор JavaScript отказывается запускаться до тех пор, пока не будет загружен весь CSS. Таким образом, кажется, что включение JavaScript в первую очередь более эффективно, так как поток JavaScript получает больше времени выполнения.
Я что-то упустил, не является ли правильной рекомендация размещать CSS-включения до JavaScript-включений?
Понятно, что мы могли бы добавить асинхронность или использовать setTimeout, чтобы освободить поток рендеринга, или поместить код JavaScript в нижний колонтитул, или использовать загрузчик JavaScript. Суть здесь в том, чтобы упорядочить основные биты JavaScript и биты CSS в голове.
источник
delay=400&jsdelay=1000
иdelay=500
это далеко не 100 мс или 89 мс. Думаю, мне неясно, на какие цифры вы ссылаетесь.Ответы:
Это очень интересный вопрос. Я всегда ставил свои CSS
<link href="...">
перед своими JS,<script src="...">
потому что «я прочитал один раз, что это лучше». Итак, вы правы; давно пора заняться исследованиями!Я установил свой собственный тестовый жгут в Node (код ниже). В основном я:
<head>
для выполнения<body>
, что аналогичноDOMReady
.Результаты
Во-первых, с задержкой файла CSS на 500 мс:
Затем я установил задержку jQuery на 500 мс вместо CSS:
Наконец, я установил как JQuery и CSS , чтобы задержать на 500мс:
Выводы
Во-первых, важно отметить, что я работаю при условии, что в
<head>
вашем документе есть сценарии (в отличие от конца<body>
). Существуют различные аргументы относительно того, почему вы можете ссылаться на свои сценарии по<head>
сравнению с концом документа, но это выходит за рамки этого ответа. Это строго о том,<script>
должен ли s идти перед<link>
s в<head>
.В современных браузерах DESKTOP, похоже, что ссылки на CSS сначала никогда не обеспечивают выигрыша в производительности. Помещение CSS в сценарий дает вам тривиальный выигрыш при задержке как CSS, так и сценария, но дает большой выигрыш при задержке CSS. (Показано
last
столбцами в первом наборе результатов.)Учитывая, что последние ссылки на CSS, похоже, не снижают производительность, но могут обеспечить выигрыш при определенных обстоятельствах, вы должны ссылаться на внешние таблицы стилей после ссылки на внешние скрипты только в браузерах настольных компьютеров, если производительность старых браузеров не является проблемой. Продолжайте читать для мобильной ситуации.
Почему?
Исторически, когда браузер сталкивался с
<script>
тегом, указывающим на внешний ресурс, он прекращал синтаксический анализ HTML, извлекал скрипт, выполнял его, а затем продолжал анализ HTML. Напротив, если браузер обнаружил<link>
для внешней таблицы стилей, он продолжит анализ HTML, пока он извлекает файл CSS (параллельно).Следовательно, широко распространенный совет ставить таблицы стилей на первое место - они будут загружаться первыми, а первый загружаемый скрипт может загружаться параллельно.
Однако современные браузеры (включая все браузеры, с которыми я тестировал выше) реализовали умозрительный синтаксический анализ , при котором браузер «смотрит вперед» в HTML и начинает загрузку ресурсов до загрузки и выполнения скриптов.
В старых браузерах без спекулятивного анализа, размещение сценариев на первом месте повлияет на производительность, поскольку они не будут загружаться параллельно.
Поддержка браузера
Спекулятивный анализ впервые был реализован в: (вместе с процентом пользователей браузеров настольных компьютеров по всему миру, использующих эту версию или более позднюю на январь 2012 года)
В целом, примерно 85% используемых сегодня настольных браузеров поддерживают спекулятивную загрузку. Размещение сценариев до CSS приведет к снижению производительности для 15% пользователей во всем мире ; YMMV в зависимости от конкретной аудитории вашего сайта. (И помните, что это число уменьшается.)
В мобильных браузерах получить определенное число немного сложнее просто из-за разнородности мобильного браузера и операционной системы. Поскольку спекулятивный рендеринг был реализован в WebKit 525 (выпущен в марте 2008 г.), и почти каждый достойный мобильный браузер основан на WebKit, мы можем заключить, что «большинство» мобильных браузеров должны его поддерживать. Согласно quirksmode , iOS 2.2 / Android 1.0 используют WebKit 525. Я понятия не имею, как выглядит Windows Phone.
Однако я запустил тест на своем устройстве Android 4 и, увидев числа, похожие на результаты на рабочем столе, я подключил его к фантастическому новому удаленному отладчику в Chrome для Android, и вкладка Сеть показала, что браузер действительно ждет загрузки CSS до полной загрузки JavaScripts - другими словами, даже самая новая версия WebKit для Android не поддерживает спекулятивный анализ. Я подозреваю, что он может быть отключен из-за ограничений процессора, памяти и / или сети, присущих мобильным устройствам.
Код
Прости за разгильдяйство - это был Q & D.
app.js
css.html
js.html
test.js
jquery.js был jquery-1.7.1.min.js
источник
<head>
вашем документе есть сценарии (в отличие от конца<body>
)». Я бы выделил это намного раньше в ответе, как наверху. Включениеscript
вhead
это относится к внешнему файлу почти никогда не является правильным, практически с любой точки зрения (конечно, не производительность). Я не помню, чтобы мне приходилось делать это в реальной жизни. Может быть, нечетная строка или два встроенного скрипта, но это все. По умолчанию, не очень хорошие противоположные причин, должно быть конец тела.Есть две основные причины использовать CSS перед JavaScript.
Старые браузеры (Internet Explorer 6-7, Firefox 2 и т. Д.) Блокировали все последующие загрузки, когда они начали загружать скрипт. Так что, если вы
a.js
последовали,b.css
они загружаются последовательно: сначала a, а затем b. Если выb.css
подписались,a.js
они загружаются параллельно, поэтому страница загружается быстрее.Ничего не отображается, пока не будут загружены все таблицы стилей - это верно для всех браузеров. Сценарии разные - они блокируют рендеринг всех элементов DOM, которые находятся ниже тега сценария на странице. Если вы помещаете свои скрипты в HEAD, это означает, что вся страница блокируется от рендеринга до тех пор, пока не будут загружены все таблицы стилей и все скрипты. Хотя имеет смысл блокировать весь рендеринг для таблиц стилей (таким образом, вы получаете правильный стиль в первый раз и избегаете флэш-памяти нестандартного содержимого FOUC), не имеет смысла блокировать рендеринг всей страницы для сценариев. Часто сценарии не затрагивают элементы DOM или только часть элементов DOM. Лучше всего загружать скрипты как можно ниже на странице или даже лучше загружать их асинхронно.
С Cuzillion интересно создавать примеры . Например, на этой странице есть сценарий в заголовке, поэтому вся страница остается пустой, пока она не завершит загрузку. Однако, если мы переместим скрипт в конец блока BODY, будет отображен заголовок страницы, поскольку эти элементы DOM находятся над тегом SCRIPT, как вы можете видеть на этой странице .
источник
async
атрибут, который Стив рекомендует здесь, когда он говорит: «Еще лучше загрузить их асинхронно» - stackoverflow.com/questions/1834077/…@import
директивами?jQuery
+jQuery UI
+$(document).ready(function () { });
в конце страницы? Будет ли это всегда работать так, как ожидалось?Я бы не стал особо подчеркивать результаты, которые вы получили, я считаю, что это субъективно, но у меня есть причина объяснить вам, что лучше ставить CSS перед js.
Во время загрузки вашего сайта вы увидите два сценария:
Случай 1: белый экран> веб - сайт без стилей> стиль сайта> взаимодействие> стиль и интерактивный веб - сайт
СЛУЧАЙ 2: белый экран> веб - сайт без стилей> взаимодействие> стиль сайта> стиль и интерактивный веб - сайт
, я честно не могу представить , чтобы кто выбирая Случай 2. Это будет означать что посетители, использующие медленное интернет-соединение, столкнутся с нестандартным веб-сайтом, что позволяет им взаимодействовать с ним с помощью Javascript (поскольку он уже загружен). Кроме того, количество времени, затрачиваемое на просмотр сайта без стилей, будет таким образом максимально увеличено. Зачем кому-то этого хотеть?
Это также работает лучше, как заявляет jQuery
Когда файлы загружаются в неправильном порядке (сначала JS, затем CSS), любой код Javascript, основанный на свойствах, установленных в файлах CSS (например, ширина или высота div), не будет загружен правильно. Кажется, что при неправильном порядке загрузки правильные свойства «иногда» известны Javascript (возможно, это вызвано состоянием гонки?). Этот эффект кажется больше или меньше в зависимости от используемого браузера.
источник
Были ли ваши тесты выполнены на вашем персональном компьютере или на веб-сервере? Это пустая страница, или это сложная онлайн-система с изображениями, базами данных и т. Д.? Ваши сценарии выполняют простое действие при наведении на них, или они являются основным компонентом того, как ваш веб-сайт отображает и взаимодействует с пользователем? Здесь нужно учитывать несколько моментов, и актуальность этих рекомендаций почти всегда становится правилом, когда вы начинаете заниматься веб-разработкой высокого уровня.
Цель правила «размещать таблицы стилей вверху и сценарии внизу» состоит в том, что, в общем, это лучший способ добиться оптимального прогрессивного рендеринга , что очень важно для взаимодействия с пользователем.
Кроме всего прочего: если ваш тест действителен, и вы действительно производите результаты, противоречащие популярным правилам, то это неудивительно. Каждый веб-сайт (и все, что нужно для того, чтобы все это отображалось на экране пользователя) отличается, и Интернет постоянно развивается.
источник
Я включаю файлы CSS перед Javascript по другой причине.
Если моему Javascript необходимо выполнить динамическое изменение размера какого-либо элемента страницы (для тех угловых случаев, когда CSS на самом деле является основным в задней части), тогда загрузка CSS после того, как JS русирует, может привести к условиям гонки, где размер элемента изменяется до стилей CSS. применяются и, таким образом, выглядят странно, когда стили, наконец, вступают в силу. Если я загружаю CSS заранее, я могу гарантировать, что все будет работать в намеченном порядке и что окончательный макет будет таким, каким я его хочу.
источник
Является ли рекомендация включать CSS перед использованием JavaScript недействительной?
Нет, если вы рассматриваете это как просто рекомендацию. Но если вы относитесь к этому как к жесткому и быстрому правилу? Да, это недействительно.
С https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded
Похоже, вам нужно знать, на что опирается каждый сценарий, и убедиться, что выполнение сценария отложено до момента правильного события завершения. Если скрипт использует только DOM, он может возобновить работу в ondomready / domcontentloaded, если он полагается на загружаемые изображения или применяемые таблицы стилей, тогда, если я правильно прочитал приведенную выше ссылку, этот код должен быть отложен до события onload.
Я не думаю, что один размер носка подходит всем, хотя так они продаются, и я знаю, что один размер обуви подходит не всем. Я не думаю, что есть определенный ответ, на который нужно сначала загрузить стили или скрипт. Это в большей степени индивидуальное решение о том, что должно быть загружено в каком порядке и что может быть отложено до тех пор, пока оно не окажется на «критическом пути».
Поговорить с наблюдателем, который прокомментировал, что лучше отложить способность пользователей взаимодействовать, пока лист не будет красивым. Многие из вас там, и вы раздражаете своих коллег, которые чувствуют обратное. Они пришли на сайт, чтобы достичь цели, и задержки с их способностью взаимодействовать с сайтом в ожидании того, что вещи, которые не имеют значения для завершения загрузки, очень расстраивают. Я не говорю, что вы не правы, только то, что вы должны знать, что существует другая фракция, которая не разделяет ваш приоритет.
Этот вопрос особенно относится ко всем объявлениям, размещаемым на веб-сайтах. Я был бы рад, если бы авторы сайта создавали только элементы-заполнители для содержания рекламы и следили за тем, чтобы их сайт был загружен и интерактивен, прежде чем вставлять рекламу в событие загрузки. Даже тогда я хотел бы видеть рекламу, загружаемую поочередно, а не все сразу, потому что они влияют на мою способность даже прокручивать контент сайта во время загрузки раздутых объявлений. Но это точка зрения только одного человека.
источник
Обновлено 2017-12-16
Я не был уверен насчет тестов в ОП. Я решил немного поэкспериментировать и в итоге разрушил некоторые мифы.
Это больше не правда . Взгляните на водопад, созданный Chrome 63:
Это неверно . Таблица стилей не будет блокировать загрузку , но он будет блокировать выполнение скрипта ( мало объяснений здесь ). Посмотрите на график производительности, сгенерированный Chrome 63:
Учитывая вышесказанное, результаты в ОП можно объяснить следующим образом:
CSS First:
JS First:
источник
The reason is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above. Naturally, it has to wait for styles to load.
javascript.info/… Почему то же самое предположение не применяется в случае JS в первую очередь? Для меня это не имеет особого смысла, порядок выполнения JS ничего не говорит о его назначении.Я не совсем уверен, как ваше тестирование «рендерится» так же, как вы используете java-скрипт. Однако учтите это
Одна страница на вашем сайте - 50 Кб, что не является необоснованным. Пользователь находится на восточном побережье, а ваш сервер на западе. MTU определенно не 10к, так что будет несколько поездок туда-сюда. Получение вашей страницы и таблиц стилей может занять 1/2 секунды. Обычно (для меня) javascript (через плагин jquery и т. Д.) Гораздо больше, чем CSS. Существует также то, что происходит, когда ваше интернет-соединение захламляется на полпути на странице, но давайте проигнорируем это (иногда это случается со мной, и я верю, что CSS рендерится, но я не уверен на 100%).
Поскольку css находится в голове, могут быть дополнительные соединения, чтобы получить его, что означает, что он может закончить раньше, чем страница. Во всяком случае, во время ввода текста остальная часть страницы и файлы javascript (а это намного больше байтов) не стилируются, что делает сайт / соединение медленным.
ДАЖЕ ЕСЛИ интерпретатор JS отказывается запускаться до тех пор, пока CSS не потратит время, затрачиваемое на загрузку кода javascript, особенно когда вдали от сервера сокращается время css, из-за которого сайт выглядит не очень красиво.
Это небольшая оптимизация, но это и есть причина.
источник
Вот РЕЗЮМЕ всех основных ответов выше (или, может быть, ниже позже :)
Для современных браузеров ставьте css там, где вам нравится. Они будут анализировать ваш HTML-файл (который они называют спекулятивный анализ ) и начнут загружать css параллельно с html-анализом.
Для старых браузеров продолжайте помещать CSS вверху (если вы не хотите сначала показывать голую, но интерактивную страницу).
Для всех браузеров поместите javascript как можно дальше вниз на страницу, так как это остановит анализ вашего html. Желательно, загружать его асинхронно (т. Е. Ajax-вызов)
Существуют также некоторые экспериментальные результаты для конкретного случая, в котором утверждается, что размещение javascript на первом месте (в отличие от традиционной мудрости использования CSS на первом месте) дает лучшую производительность, но для этого нет логического обоснования и отсутствует проверка в отношении широкого применения, поэтому вы можете игнорируйте это сейчас.
Итак, чтобы ответить на вопрос: да. Рекомендация включать CSS перед JS недопустима для современных браузеров. Размещайте CSS там, где вам нравится, и ставьте JS ближе к концу, насколько это возможно.
источник
Стив Соудерс уже дал окончательный ответ, но ...
Интересно, есть ли проблема как с оригинальным тестом Сэма, так и с повторением Джоша?
Оба теста, по-видимому, были выполнены на соединениях с низкой задержкой, где настройка соединения TCP будет стоить тривиально.
Как это влияет на результат теста, я не уверен, и я хотел бы взглянуть на водопады для тестов через «нормальное» соединение с задержкой, но ...
Первый загруженный файл должен получить соединение, используемое для html-страницы, а второй загруженный файл получит новое подключение. (Очистка ранних версий изменяет эту динамику, но здесь это не делается)
В более новых браузерах второе TCP-соединение открывается спекулятивно, поэтому накладные расходы на соединение уменьшаются / исчезают, в более старых браузерах это не так, и второе соединение будет иметь накладные расходы на открытие.
Как / если это повлияет на результаты тестов, я не уверен.
источник
Я думаю, что это не будет правдой для всех случаев. Потому что CSS будет загружать параллельно, но JS не могу. Рассмотрим для того же случая,
Вместо того, чтобы иметь один CSS, возьмите 2 или 3 файла CSS и попробуйте это следующим образом,
1) css..css..js 2) css..js..css 3) js..css..css
Я уверен, что css..css..js даст лучший результат, чем все остальные.
источник
Мы должны помнить, что новые браузеры работали на своих движках Javascript, их синтаксических анализаторах и т. Д., Оптимизируя общие проблемы с кодом и разметкой таким образом, что проблемы, возникающие в древних браузерах, таких как <= IE8, больше не актуальны, не только с Что касается разметки, но также и использования переменных JavaScript, селекторов элементов и т. д. Я могу видеть в не столь отдаленном будущем ситуацию, когда технологии достигли точки, когда производительность больше не является проблемой.
источник
Лично я бы не стал особо подчеркивать такую «народную мудрость». То, что могло быть правдой в прошлом, может и не быть правдой сейчас. Я бы предположил, что все операции, связанные с интерпретацией и отображением веб-страницы, являются полностью асинхронными («извлечение» чего-либо и «воздействие на него» - это две совершенно разные вещи, которые могут обрабатываться разными потоками и т. Д. ), И в любом случае, полностью вне вашего контроля или вашего беспокойства.
Я бы поместил ссылки CSS в «головной» части документа вместе с любыми ссылками на внешние скрипты. (Некоторые сценарии могут требовать помещения в тело и, если да, обязать их.)
Кроме того ... если вы заметили, что «в этом / этом браузере« это кажется быстрее / медленнее, чем это »», воспринимайте это наблюдение как интересное, но не относящееся к делу любопытство и не позволяйте ему влиять на ваши дизайнерские решения. Слишком много вещей меняется слишком быстро. (Любой хотите положить любые ставки на то, сколько минут он будет до того , как команда Firefox выходит с еще одним временным высвобождением своего продукта? Да, я ни.)
источник