Каковы плюсы и минусы добавления элементов <script>и <link>с использованием JavaScript? - PullRequest
10 голосов
/ 14 марта 2011

Недавно я увидел некоторый HTML-код только с одним <script> элементом в <head> ...

<head>
    <title>Example</title>
    <script src="script.js" type="text/javascript"></script>
    <link href="plain.css" type="text/css" rel="stylesheet" />
</head>

. Этот script.js затем добавляет любые другие необходимые <script> элементы и <link>элементы к документу, используя document.write(...): (или он может использовать document.createElement(...) и т. д.)

document.write("<link href=\"javascript-enabled.css\" type=\"text/css\" rel=\"styleshet\" />");
document.write("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js\" type=\"text/javascript\"></script>");
document.write("<script src=\"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js\" type=\"text/javascript\"></script>");
document.write("<link href=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/trontastic/jquery-ui.css\" type=\"text/css\" rel=\"stylesheet\" />")
document.write("<script src=\"validation.js\" type=\"text/css\"></script>")

Обратите внимание, что в документе есть plain.css файл CSS <head> и script.js просто добавляетлюбой и все CSS и JavaScript, которые будут использоваться пользовательским агентом с поддержкой JS.

Каковы некоторые плюсы и минусы этого метода?

Ответы [ 9 ]

12 голосов
/ 27 марта 2011

Блокирующий характер document.write

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

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

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

Потеря оптимизации и предсказуемости скорости браузера

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

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

Некоторые браузеры откладывают выполнение сценариев до конца после их завершения.

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

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

Зачем кому-то делать это так?

Причина, по которой вы можете захотеть использовать что-то подобное, обычно заключается в удобстве обслуживания.Например, у вас может быть огромный сайт с тысячами страниц, каждая из которых загружает один и тот же набор скриптов и таблиц стилей.Однако, когда вы добавляете файл сценария, вы не хотите редактировать тысячи файлов HTML, чтобы добавить теги сценария.Это особенно проблематично при загрузке библиотек JavaScript (например, Dojo или jQuery) - вам необходимо изменить каждую HTML-страницу при обновлении до следующей версии.

Проблема в том, что в JavaScript нет @include или@import для вас, чтобы включить другие файлы.

Некоторые решения

Решение этого, вероятно, не путем введения сценариев через document.write, а с помощью:

  1. Использование директив @import в таблицах стилей
  2. Использование языка сценариев сервера (например, PHP) для управления вашей "главной страницей" и создания всех других страниц (однако, если вы не можете использовать это и должны поддерживать много HTMLстраницы по отдельности, это не решение)
  3. Избегайте document.write, но загрузите файлы JavaScript через XHR, а затем eval () их - хотя это может иметь проблемы с безопасностью, хотя
  4. Используйте JavaScriptБиблиотека (например, Dojo), которая имеет функции загрузки модулей, так что вы можете сохранить основной файл JS, который загружает другие файлы.Вы не сможете избежать необходимости обновлять номера версий файла библиотеки, хотя ...
8 голосов
/ 27 марта 2011

Ну, я тоже могу накинуть свою шляпу на ринг на этом ...

Если вы изучите библиотеку google закрытия, base.js, вы увидите, что document.write используется в их функции writeScriptTag_(). Это неотъемлемая часть системы управления зависимостями, которую обеспечивает «замыкание», и является огромным преимуществом при создании сложного многофайлового javascript-приложения на основе библиотеки - оно позволяет предварительным условиям для файла / кода определять порядок загрузки. В настоящее время мы используем эту технику, и у нас мало проблем с ней. TBH, у нас не было ни одной проблемы с совместимостью с браузерами, и мы регулярно тестируем IE 6/7/8, FF3 / 2, Safari 4/5 и Chrome.

Единственный недостаток, который у нас был до сих пор, заключается в том, что может быть сложно отследить проблемы, вызванные двойной загрузкой ресурса или невозможностью его загрузки вообще. Поскольку процесс загрузки ресурсов является программным, он подвержен программным ошибкам, и в отличие от добавления тегов непосредственно в HTML, может быть трудно понять, каков точный порядок загрузки. Однако эту проблему можно в значительной степени преодолеть, используя библиотеку с некоторой формой системы управления зависимостями, такой как закрытие или dojo.

РЕДАКТИРОВАТЬ: Я сделал несколько комментариев к этой природе, но я подумал, что лучше всего подвести итог в моем ответе: Есть некоторые проблемы с dojo.require () и jQuery.getScript () (обе из которых в конечном итоге выполняют ajax-запрос и eval).

  1. загрузка через ajax означает отсутствие кросс-скриптинга - то есть не загрузка javascript, который не с вашего сайта. Это будет проблемой, если вы хотите включить https://ajax.googleapis.com, как указано в описании.
  2. Сценарии Eval'd не будут отображаться в списке сценариев страниц отладчика javascript, что делает отладку довольно сложной. Последние выпуски Firebug покажут вам eval'd код, однако имена файлов теряются, что делает процесс установки точек останова утомительным. AFAIK, javascript-консоль Webkit и инструменты разработчика IE8 не не показывают сценарии eval'd.
8 голосов
/ 14 марта 2011

Одним из основных недостатков является несовместимость браузера.Не все браузеры правильно выбирают и включают ресурсы в DOM, поэтому рискованно использовать этот подход.Это в большей степени относится к таблицам стилей, чем к сценариям.

Другая проблема связана с ремонтопригодностью.Объединение и написание строк для добавления элементов DOM на стороне клиента может стать кошмаром обслуживания.Для семантического создания элементов лучше использовать методы DOM, такие как createElement.

Одно очевидное преимущество заключается в том, что это значительно упрощает условное использование ресурсов.Вы можете иметь логику, которая определяет, какие ресурсы загружать, тем самым уменьшая потребление полосы пропускания и общее время обработки страницы.Я бы использовал библиотечный вызов, такой как jQuery $ .getScript (), чтобы загрузить сценарии вместо document.write.Преимущество заключается в том, что такой подход более понятен, а также позволяет выполнять код при завершении или сбое запроса.

4 голосов
/ 14 марта 2011

Преимущество заключается в том, что вам не нужно повторять ссылки на скрипты в каждом файле HTML.Недостатком является то, что браузер должен извлечь и выполнить основной файл JavaScript, прежде чем он сможет загрузить другие.

2 голосов
/ 27 марта 2011

Также возможно, что это было написано в качестве рекомендации SEO-фирмы, чтобы сделать элемент заголовка короче, если это возможно, чтобы уникальный контент был ближе к верху документа - также создавая более высокое отношение текста к HTML. Хотя это звучит, в целом, как не очень хороший способ сделать это; хотя это сделает обслуживание более трудоемким, лучшим подходом, вероятно, будет сжатие javascript в один файл .js и css в один файл .css, если это будет крайне необходимо для уменьшения размера элемента head.

2 голосов
/ 27 марта 2011

В Google PageSpeed ​​они настоятельно не рекомендуют вам использовать эту технику, потому что она замедляет работу.Помимо последовательной загрузки вашего script.js перед всеми остальными, есть еще один улов:

Современные браузеры используют спекулятивные анализаторы для более эффективного обнаружения внешнихресурсы [...] Таким образом, использование JavaScript document.write () для извлечения внешних ресурсов делает невозможным для умозрительного синтаксического анализатора обнаружение этих ресурсов, что может задержать загрузку, анализ и рендеринг этих ресурсов.

2 голосов
/ 14 марта 2011

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

1 голос
/ 27 марта 2011

Большим недостатком является то, что добавление script s в заголовок приостановит обработку документа до тех пор, пока эти скрипты не будут полностью загружены, проанализированы и выполнены (поскольку браузер считает, что они могут использовать document.write). - Это повредит отзывчивости.

В наши дни рекомендуется ставить теги скриптов прямо перед </body>. Конечно, это невозможно в 100% случаев, но если вы используете unobtrusve Javascript (как вам следует), все сценарии могут быть расположены в конце документа.

В HTML5 появился атрибут async, который предлагает браузеру выполнять скрипты только после загрузки основного документа. Это поведение скриптов, вставленных скриптами, во многих браузерах, но не во всех.

Я советую против , используя document.write любой ценой. Даже без этого это приводит к одному дополнительному запросу к серверу. (Нам нравится увеличивать количество запросов, например, с помощью css sprites .)

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

0 голосов
/ 27 марта 2011
  1. Если JavaScript отключен - <script> and <link> элементы вообще не будут добавлены.

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

...