Когда мне следует использовать встроенный или внешний Javascript?

129

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

Какова общая практика для этого?

Реальный сценарий - у меня есть несколько html-страниц, которым требуется проверка формы на стороне клиента. Для этого я использую плагин jQuery, который я включаю на все эти страницы. Но вопрос в том, могу ли я:

  • написать фрагменты кода, которые настраивают этот скрипт встроенным?
  • включить все биты в один файл, который используется всеми этими HTML-страницами?
  • включать каждый бит в отдельный внешний файл, по одному для каждой HTML-страницы?

Спасибо.

Дэн Бурзо
источник

Ответы:

114

На момент публикации этого ответа (2008 г.) правило было простым: все сценарии должны быть внешними. И для обслуживания, и для производительности.

(Почему производительность? Потому что, если код отдельный, его легче кешировать в браузерах.)

JavaScript не входит в HTML-код, и если он содержит специальные символы (например <, >), это даже создает проблемы.

В настоящее время веб-масштабируемость изменилась. Уменьшение количества запросов стало допустимым соображением из-за задержки выполнения нескольких HTTP-запросов. Это усложняет ответ: в большинстве случаев все же рекомендуется иметь внешний JavaScript . Но в некоторых случаях, особенно в очень маленьких фрагментах кода, встраивание их в HTML-код сайта имеет смысл.

Конрад Рудольф
источник
6
@Nick: большинство проблем можно преодолеть. Однако лучше вообще не создавать их.
Конрад Рудольф
17
Иногда вы получаете лучшую производительность при встраивании. Посмотрите на источник google.com . Они знают, что делают.
callum
13
@callum Google использует другой вариант использования, нежели 99,999999% веб-сайтов. Конечно, они измеряют очень тщательно, и даже самая маленькая разница имеет значение. Но только потому, что они обнаружили, что в их конкретном случае встраивание работает лучше (возможно, потому, что скрипт меняется очень часто?), Не означает, что мы можем вывести из этого общее правило или даже что мы должны игнорировать «обычные» правило (для экстернализации скриптов).
Конрад Рудольф
8
@KonradRudolph - Согласен, из подхода Google не следует выводить никаких общих правил. Я просто говорю, что это намек на то, что, возможно, стоит подвергнуть сомнению правило в вашем ответе. В любом случае, я думаю, что причина, по которой Google делает это, состоит в том, чтобы уменьшить количество HTTP-запросов, и это может принести пользу более чем 0,000001% сайтов. Пропускная способность растет, но время приема-передачи остается прежним. Иногда удаление всего последовательного HTTP-запроса лучше, чем кэширование внешнего JS. Конечно, зависит от размера вашего JS.
callum
5
@callum Хотя это правда, вопрос о кешировании все еще остается и остается важным. Уменьшение количества обращений важно только в том случае, если ваши посетители не возвращаются (и тогда у вас не будет достаточного количества обращений к странице, чтобы это было важно) или если ваш контент изменяется так часто, что кеширование файлов сценариев не приносит пользы.
Конрад Рудольф,
31

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

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

Хорст Гутманн
источник
5
Это одна из моих проблем. Наличие отдельного HTTP-запроса для нескольких строк кода кажется расточительным.
Дэн Бурзо,
Не могли бы вы опубликовать образец конфигурации для своего кода? ИМО, если он меньше 300 символов и абсолютно привязан к странице, встроите его.
Хорст Гутманн,
Это должен быть главный ответ imo
sgarcia.dev 08
@Dan имейте в виду, что отдельный запрос выполняется только в первый раз. Если вы ожидаете, что ваши пользователи будут загружать страницу более одного раза, внешнее кэширование (даже для нескольких строк) явно быстрее, чем ожидание байтов для этих нескольких строк по сети при загрузке страницы n = 2 +.
jinglesthula
@HorstGutmann, как внешняя помощь файла связана с ремонтопригодностью? Я лично предпочитаю внешние js, когда это возможно, но есть ли что-то объективное, что упрощает поддержку?
jinglesthula
21

Экстернализация javascript - одно из правил производительности Yahoo: http://developer.yahoo.com/performance/rules.html#external

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

Йери Себрехтс
источник
1
Я думаю, Yahoo также рекомендует добавлять весь Javascript в один HTTP-вызов - это не означает, что все сценарии должны находиться в одном файле во время разработки,
Пол Шеннон
Кроме того, как отмечалось выше, HTTP / 2 также меняет практику «1 вызов».
jinglesthula
19

Если вы заботитесь только о производительности, большинство советов в этом потоке совершенно неверны и становятся все более и более неправильными в эпоху SPA, когда мы можем предположить, что страница бесполезна без кода JS. Я провел бесчисленное количество часов, оптимизируя время загрузки страницы SPA и проверяя эти результаты в разных браузерах. Повсеместно повышение производительности за счет повторной оркестровки вашего html может быть весьма значительным.

Чтобы добиться максимальной производительности, вы должны думать о страницах как о двухступенчатых ракетах. Эти две стадии примерно соответствуют <head>и <body>фазы, но думать о них вместо того, чтобы, как <static>и <dynamic>. Статическая часть - это в основном строковая константа, которую вы вставляете в канал ответа так быстро, как только можете. Это может быть немного сложно, если вы используете много промежуточного программного обеспечения, которое устанавливает файлы cookie (их необходимо установить перед отправкой содержимого http), но в принципе он просто очищает буфер ответа, надеюсь, перед тем, как перейти к некоторому шаблонному коду (razor, php, и т. д.) на сервере. Это может показаться трудным, но я просто объясняю это неправильно, потому что это почти тривиально. Как вы уже догадались, эта статическая часть должна содержать весь встроенный и минифицированный javascript. Это будет выглядеть примерно так

<!DOCTYPE html>
     <html>
         <head>
             <script>/*...inlined jquery, angular, your code*/</script>
             <style>/* ditto css */</style>
         </head>
         <body>
             <!-- inline all your templates, if applicable -->
             <script type='template-mime' id='1'></script>
             <script type='template-mime' id='2'></script>
             <script type='template-mime' id='3'></script>

Поскольку отправка этой части по сети почти ничего не стоит, вы можете ожидать, что клиент начнет получать ее где-то около 5 мс + задержка после подключения к вашему серверу. Предполагая, что сервер достаточно близко, эта задержка может составлять от 20 мс до 60 мс. Браузеры начнут обрабатывать этот раздел, как только они его получат, и время обработки обычно будет преобладать над временем передачи в 20 или более раз, что теперь является вашим амортизированным окном для обработки на стороне сервера<dynamic> .

Браузеру требуется около 50 мсек (хром, отдых может быть на 20% медленнее), чтобы обработать встроенный jquery + signalr + angular + ng animate + ng touch + ng routes + lodash. Это довольно удивительно само по себе. В большинстве веб-приложений меньше кода, чем во всех этих популярных библиотеках вместе взятых, но предположим, что у вас столько же, так что мы выиграем задержку + 100 мс обработки на клиенте (эта задержка достигается за счет второго фрагмента передачи). К тому времени, когда приходит второй чанк, мы обработали весь js-код и шаблоны и можем начать выполнять преобразования dom.

Вы можете возразить, что этот метод ортогонален концепции встраивания, но это не так. Если вы, вместо встраивания, ссылаетесь на cdns или свои собственные серверы, браузеру придется открыть другое соединение (я) и отложить выполнение. Поскольку это выполнение в основном бесплатное (поскольку серверная сторона обращается к базе данных), должно быть ясно, что все эти переходы будут стоить больше, чем их отсутствие. Если бы была причуда браузера, которая говорила, что внешний js выполняется быстрее, мы могли бы измерить, какой фактор доминирует. Мои измерения показывают, что лишние запросы убивают производительность на этом этапе.

Я много работаю над оптимизацией SPA-приложений. Люди часто думают, что объем данных имеет большое значение, в то время как на самом деле задержка и выполнение часто доминируют. Минифицированные библиотеки, которые я перечислил, добавляют до 300 КБ данных, и это всего лишь 68 КБ в сжатом виде, или загрузка 200 мс на 2-мегабитный телефон 3g / 4g, что является именно той задержкой, которую потребуется на том же телефоне, чтобы проверить, были ли у него те же данные. в своем кэше уже, даже если он был кэширован прокси, потому что налог на задержку мобильной связи (задержка от телефона к вышке) все еще применяется. Между тем, подключения к настольным компьютерам с более низкой задержкой первого прыжка в любом случае обычно имеют более высокую пропускную способность.

Короче говоря, прямо сейчас (2014 г.) лучше всего встроить все скрипты, стили и шаблоны.

ИЗМЕНИТЬ (МАЙ 2016)

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

Глено
источник
Я не получил то, что теперь является вашим амортизированным окном для серверной обработки части <dynamic> - сервер обрабатывает все, что ему нужно, и только затем обслуживает весь визуализированный html (голова + тело), ​​что еще обрабатывает сервер нужно после этого?
BornToCode
@BornToCode Идея состоит в том, чтобы дать клиенту что-то делать, в то время как серверная сторона чем-то занимается. Поскольку клиентские библиотеки необходимо интерпретировать, лучше запустить этот процесс, прежде чем выполнять какие-либо вычисления на сервере. Амортизированное окно - это время, необходимое клиенту для обработки JS. Вы получите это окно бесплатно, если будете дирижировать двухступенчатой ​​ракетой.
Gleno
9

На самом деле, есть довольно хороший случай использовать встроенный javascript. Если js достаточно мал (однострочный), я предпочитаю встроенный javascript из-за двух факторов:

  • Местонахождение . Нет необходимости перемещаться по внешнему файлу, чтобы проверить поведение некоторого javascript
  • AJAX . Если вы обновляете какой-либо раздел страницы через AJAX, вы можете потерять все свои обработчики DOM (onclick и т. Д.) Для этого раздела, в зависимости от того, как вы их связали. Например, используяjQuery вы можете использовать методы liveили, delegateчтобы обойти это, но я считаю, что, если js достаточно мал, предпочтительнее просто поместить его в строку.
Мигель Пинг
источник
5

Еще одна причина, по которой вы всегда должны использовать внешние сценарии, - это упрощение перехода на политику безопасности контента (CSP) . По умолчанию CSP запрещает все встроенные скрипты, что делает ваш сайт более устойчивым к XSS-атакам.

chiborg
источник
4

Я бы посмотрел на требуемый код и разделил его на столько отдельных файлов, сколько нужно. Каждый файл js будет содержать только один «логический набор» функций и т. Д., Например. один файл для всех функций, связанных с входом в систему.

Затем при разработке сайта на каждой странице html вы включаете только те, которые необходимы. Когда вы запускаете свой сайт, вы можете оптимизировать, объединив каждый файл js, который нужен странице, в один файл.

Ген
источник
4

Единственная защита, которую я могу предложить для встроенного javascipt, заключается в том, что при использовании строго типизированных представлений с .net MVC вы можете ссылаться на переменные С # в середине javascript, которые я нашел полезными.

Austin_G
источник
3

Три соображения:

  • Сколько кода вам нужно (иногда библиотеки - первоклассный потребитель)?
  • Специфика: работает ли этот код только в контексте этого конкретного документа или элемента?
  • Каждый код внутри документа имеет тенденцию делать его длиннее и, следовательно, медленнее. Помимо того, что соображения SEO делают очевидным, что вы минимизируете внутренние сценарии ...
roenving
источник
2

Внешние скрипты также легче отлаживать с помощью Firebug. Мне нравится модульное тестирование моего JavaScript и иметь все внешние подсказки. Я ненавижу видеть JavaScript в коде PHP и HTML, мне это кажется большим беспорядком.

сцепление
источник
2

Что касается сохранения внешнего кода JavaScript:

ASP.NET 3.5SP1 недавно представил функциональность для создания ресурса Composite script (слияние нескольких файлов js в один). Еще одно преимущество этого заключается в том, что когда сжатие веб-сервера включено, загрузка одного файла немного большего размера будет иметь лучший коэффициент сжатия, чем многие файлы меньшего размера (также меньше накладных расходов HTTP, двустороннего трафика и т. Д.). Я предполагаю, что это позволяет сэкономить на начальной загрузке страницы, после чего включается кеширование браузера, как упоминалось выше.

Помимо ASP.NET, этот скринкаст более подробно объясняет преимущества: http://www.asp.net/learn/3.5-SP1/video-296.aspx

Брендан Ковиц
источник
2

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

кругозор
источник
1

В вашем сценарии это звучит так, как будто запись внешнего материала в один файл, совместно используемый страницами, будет вам полезна. Я согласен со всем сказанным выше.

mattlant
источник
1

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

Я бы даже осмелился сказать, что если вы не можете разместить весь свой Javascript извне, значит, у вас в руках плохой дизайн, и вам следует реорганизовать свои данные и скрипты.

Роберт Гулд
источник
1

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

Кис Хессельс
источник
1

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

Зак Шейх
источник
-3

Всегда старайтесь использовать внешние JS, так как встроенный JS всегда сложно поддерживать.

Более того, профессионально требуется, чтобы вы использовали внешний js, поскольку большинство разработчиков рекомендуют использовать js извне.

Сам использую внешние js.

Даниэль Пуйу
источник
2
Профессионально требуется? Зачем? Кто так говорит?
Сия