Поместить JavaScript в один файл.js или разбить его на несколько файлов.js?
Мое веб-приложение использует jQuery и некоторые плагины jQuery (например, валидация, автозаполнение). Мне было интересно, стоит ли мне вставлять их в один файл.js, чтобы его было проще кэшировать, или разбивать их на отдельные файлы и включать только те, которые мне нужны для данной страницы.
Я должен также упомянуть, что меня беспокоит не только время, которое требуется для загрузки файлов.js, но и то, насколько медленно страница замедляется в зависимости от содержимого загруженного файла.js. Например, добавление плагина автозаполнения имеет тенденцию замедлять время отклика примерно на 100 мс из моего базового тестирования, даже когда оно кэшируется. Я предполагаю, что он должен сканировать элементы в DOM, что вызывает эту задержку.
11 ответов
Я думаю, это зависит от того, как часто они меняются. Давайте возьмем этот пример:
- JQuery: меняйте раз в год
- Сторонние плагины: меняйте каждые 6 месяцев
- Ваш пользовательский код: меняйте каждую неделю
Если ваш пользовательский код составляет всего 10% от общего кода, вы не хотите, чтобы пользователи загружали остальные 90% каждую неделю. Вы должны разделить как минимум на 2 js: плагины JQuery + и ваш пользовательский код. Теперь, если ваш пользовательский код представляет 90% от полного размера, имеет смысл поместить все в один файл.
При выборе способа объединения файлов JS (и того же для CSS) я балансирую:
- относительный размер файла
- ожидаемое количество обновлений
Общий, но актуальный ответ:
Это зависит от проекта.
Если у вас достаточно ограниченный веб-сайт, где большая часть функций используется повторно в нескольких разделах сайта, имеет смысл поместить весь ваш сценарий в один файл.
Однако в нескольких крупных веб-проектах, над которыми я работал, имело больше смысла объединять общие функциональные возможности для всего сайта в один файл и помещать более специфичные для каждого раздела функциональные возможности в свои собственные файлы. (Мы говорим здесь о больших файлах сценариев, для поведения нескольких отдельных веб-приложений, все они обслуживаются в одном домене.)
Преимущество разделения скрипта на отдельные файлы заключается в том, что вам не нужно обслуживать пользователей ненужным контентом и пропускной способностью, которые они не используют. (Например, если они никогда не посещают "Приложение A" на веб-сайте, им никогда не понадобится 100К сценариев для раздела "Приложение A". Но им потребуется общая функциональность для всего сайта.)
Преимущество хранения сценария в одном файле - простота. Меньше попаданий на сервер. Меньше загрузок для пользователя.
Как обычно, правда, YMMV. Там нет жесткого и быстрого правила. Делайте то, что наиболее целесообразно для ваших пользователей, исходя из их использования и структуры вашего проекта.
Я в основном дошел до того, что сократил целое веб-приложение до 3 файлов.
- vendor.js
- app.js
- app.css
Продавец аккуратен, потому что в нем есть все стили. Т.е. я конвертирую весь CSS моего вендора в минимизированный css, затем конвертирую его в javascript и включаю в файл vendor.js. Это после того, как это было дерзко преобразовано тоже.
Потому что мои материалы продавцов не обновляются часто, когда они в производстве, это довольно редко. Когда он обновляется, я просто переименовываю его в нечто вроде vendor_1.0.0.js.
Также есть уменьшенные версии этих файлов. В dev я загружаю unminified версии и в производственном процессе я загружаю minified версии.
Я использую глоток, чтобы справиться со всем этим. Основными плагинами, которые делают это возможным, являются....
- проглатывать-включают
- проглатывать-css2js
- Глоток-CONCAT
- Глоток-csso
- глотнуть-HTML-к-JS
- Глоток режим
- глоток переименование
- проглатывать-уродовать
- Узел-Сасс-тильда-импортер
Теперь это также включает в себя мои изображения, потому что я использую sass, и у меня есть функция sass, которая будет компилировать изображения в URL-адреса данных в моем листе CSS.
function sassFunctions(options) {
options = options || {};
options.base = options.base || process.cwd();
var fs = require('fs');
var path = require('path');
var types = require('node-sass').types;
var funcs = {};
funcs['inline-image($file)'] = function (file, done) {
var file = path.resolve(options.base, file.getValue());
var ext = file.split('.').pop();
fs.readFile(file, function (err, data) {
if (err) return done(err);
data = new Buffer(data);
data = data.toString('base64');
data = 'url(data:image/' + ext + ';base64,' + data + ')';
data = types.String(data);
done(data);
});
};
return funcs;
}
Таким образом, в моем app.css будут все образы моих приложений в css, и я могу добавить изображения в любой кусок стилей, который захочу. Обычно я создаю классы для изображений, которые являются уникальными, и я просто возьму материал с этим классом, если я хочу, чтобы у него было это изображение. Я избегаю использовать теги изображений полностью.
Кроме того, используя плагин html to js, я компилирую весь свой html в файл js в объект шаблона, хэшированный по пути к html-файлам, т.е. "html \ templates \ header.html", а затем, используя что-то вроде нокаута, могу привязать этот HTML к элементу или нескольким элементам.
В результате я могу получить целое веб-приложение, которое раскручивается в одном "index.html", в котором нет ничего, кроме этого:
<html>
<head>
<script src="dst\vendor.js"></script>
<script src="dst\app.css"></script>
<script src="dst\app.js"></script>
</head>
<body id="body">
<xyz-app params="//xyz.com/api/v1"></xyz-app>
<script>
ko.applyBindings(document.getTagById("body"));
</script>
</body>
</html>
Это запустит мой компонент "xyz-app", который является целым приложением, и не имеет никаких событий на стороне сервера. Он не работает на PHP, DotNet Core MVC, MVC в целом или что-то в этом роде. Это просто базовый html, управляемый с помощью системы сборки, такой как Gulp, и все, что ему нужно для получения данных, - все остальное apis.
- Аутентификация -> Rest Api
- Продукты -> Rest Api
- Поиск -> Google Compute Engine (Python API построен для индексации контента, возвращаемого из остальных API).
Так что я никогда не получал html, возвращающихся с сервера (только статические файлы, которые быстро сходят с ума). И есть только 3 файла для кэширования, кроме самого index.html. Веб-серверы поддерживают документы по умолчанию (index.html), поэтому вы просто увидите "blah.com" в URL-адресе и любые строки запроса или фрагменты хеша, используемые для поддержания состояния (маршрутизация и т. Д. Для URL-адресов закладок).
Безумно быстро, все в ожидании на движке JS.
Поисковая оптимизация сложнее. Это просто другой способ думать о вещах. Т.е. Google сканирует ваш API-интерфейс, а не физический веб-сайт, и вы сообщаете Google, как получить доступ к своему веб-сайту по каждому результату.
Допустим, у вас есть страница продукта для ABC Thing с идентификатором продукта 129. Google будет сканировать api ваших продуктов, чтобы просмотреть все ваши продукты и проиндексировать их. Там вы api возвращает URL-адрес в результате, который говорит Google, как получить этот продукт на веб-сайте. Т.е. " http: // blah # products / 129".
Поэтому, когда пользователи ищут "ABC вещь", они видят список и, щелкая по нему, переводят их в " http: // blah # products / 129".
Я думаю, что поисковые системы должны начать становиться умными, как это, это будущее IMO.
Я люблю создавать такие сайты, потому что это избавляет от всей сложности бэк-энда. Вам не нужны веб-формы RAZOR, PHP, Java, ASPX, или вы избавляетесь от всех этих стеков... Все, что вам нужно, это способ написать rest apis (WebApi2, Java Spring или ж / д и т. д.).
Это разделяет веб-дизайн на UI Engineering, Backend Engineering и Design и создает четкое разделение между ними. У вас может быть команда UX, создающая все приложение, и команда Архитектуры, выполняющая всю остальную API-работу, и нет необходимости в разработке полного стека.
Безопасность также не является проблемой, потому что вы можете передавать учетные данные в запросах AJAX, и если ваши материалы находятся в одном домене, вы можете просто создать свой cookie для аутентификации в корневом домене и Presto (автоматический, единый SSO со всеми остальными API).,
Не говоря уже о том, насколько проще настройка фермы серверов. Потребности в распределении нагрузки намного меньше. Дорожные возможности намного выше. На балансировщике нагрузки проще кластеризовать остальные серверы API, чем целые веб-сайты.
Просто настройте 1 обратный прокси-сервер nginx, чтобы обслуживать ваш индекс.html, а также направлять запросы API к одному из 4 остальных серверов API.
- Api Server 1
- Api Server 2
- Api Server 3
- Api Server 4
И ваши sql-боксы (реплицированные) просто сбалансированы по нагрузке от 4-х остальных серверов API (все используют SSD, если это возможно)
- Бокс 1
- Бокс 2
Все ваши серверы могут находиться во внутренней сети без публичных ips и просто сделать обратный прокси-сервер общедоступным со всеми входящими запросами.
Вы можете загрузить баланс обратного прокси-сервера на круговой DNS.
Это означает, что вам нужен только 1 сертификат SSL, так как это один публичный домен.
Если вы используете Google Compute Engine для поиска и поиска, это в облаке, так что вам не о чем беспокоиться, только $.
Если файлы нужны на каждой странице, поместите их в один файл. Это уменьшит количество HTTP-запросов и улучшит время отклика (для большого количества посещений).
Посмотрите лучшие практики Yahoo для других советов
Если люди собираются посетить более одной страницы на вашем сайте, вероятно, лучше всего поместить их все в один файл, чтобы их можно было кэшировать. Они сразу получат один удар, но это будет все, что они проводят на вашем сайте.
Это в значительной степени зависит от того, как пользователи взаимодействуют с вашим сайтом.
Некоторые вопросы для вас, чтобы рассмотреть:
- Насколько важно, чтобы загрузка первой страницы была очень быстрой?
- Пользователи обычно проводят большую часть своего времени в отдельных разделах сайта с подмножеством функций?
- Нужны ли вам все сценарии готовы в тот момент, когда страница готова, или вы можете загрузить некоторые из них после загрузки страницы, вставив
<script>
элементы на страницу?
Хорошее представление о том, как пользователи используют ваш сайт и что вы хотите оптимизировать, является хорошей идеей, если вы действительно хотите повысить производительность.
Тем не менее, мой метод по умолчанию состоит в том, чтобы просто объединить и свести весь мой JavaScript в один файл. jQuery и jQuery.ui небольшие и имеют очень низкие накладные расходы. Если плагины, которые вы используете, оказывают влияние 100 мс на время загрузки страницы, значит, что-то может быть не так.
Несколько вещей, чтобы проверить:
- Включен ли gzipping на вашем HTTP-сервере?
- Вы генерируете статические файлы с уникальными именами как часть своего развертывания?
- Вы обслуживаете статические файлы с бесконечным сроком действия кэша?
- Вы включаете свой CSS вверху своей страницы и свои сценарии внизу?
- Есть ли лучший (меньше, быстрее) плагин JQuery, который делает то же самое?
Я бы согласился с тем, что сказал бигматтых, это зависит.
Как правило, я стараюсь максимально агрегировать файлы сценариев, но если у вас есть несколько сценариев, которые используются только в нескольких областях сайта, особенно те, которые выполняют большие обходы DOM при загрузке, было бы целесообразно оставьте те в отдельном файле (ах).
например, если вы используете проверку только на своей странице контактов, зачем загружать ее на свою домашнюю страницу?
Кроме того, вы можете иногда скрывать эти файлы на промежуточных страницах, где больше ничего не происходит, поэтому, когда пользователь попадает на достаточно тяжелую в противном случае страницу, которая нуждается в этом, его уже следует кэшировать - используйте с осторожностью - но можно полезный трюк, когда кто-то сравнивает вас.
Таким образом, как можно меньше сценариев, в пределах разумного.
Если вы отправляете монолит 100 КБ, но только для 80% страниц используете его по 20 КБ, рассмотрите возможность его разделения.
В конце дня это зависит от вас.
Однако чем меньше информации содержит каждая веб-страница, тем быстрее она будет загружена конечным пользователем.
Если вы включаете только js-файлы, необходимые для каждой страницы, более вероятно, что ваш веб-сайт будет более эффективным и оптимизированным
Если вам нравится код в отдельных файлах для разработки, вы всегда можете написать быстрый скрипт для объединения их в один файл перед минификацией.
Один большой файл лучше для уменьшения HTTP-запросов, как указали другие авторы.
Я также думаю, что вы должны пойти по одному пути, как предложили другие. Тем не менее, к вашей точке зрения плагины поглощают циклы, просто будучи включены в ваш большой файл js:
Прежде чем выполнять дорогостоящую операцию, используйте некоторые проверки, чтобы убедиться, что вы находитесь даже на странице, которая нуждается в операциях. Возможно, вы сможете обнаружить наличие (или отсутствие) dom-узла перед запуском плагина автозаполнения и инициализировать плагин только при необходимости. Нет необходимости тратить накладные расходы на обход dom на страницах или разделах, которые никогда не будут нуждаться в определенных функциях.
Простое условие перед дорогим фрагментом кода даст вам преимущества обоих подходов, которые вы выбираете.
Я попытался разбить свой JS на несколько файлов и столкнулся с проблемой. У меня была форма входа, код для которой (отправка AJAX и т. Д.) Я поместил в отдельный файл. После успешного входа в систему обратный вызов AJAX вызывал функции для отображения других элементов страницы. Поскольку эти элементы не были частью процесса входа в систему, я поместил их JS-код в отдельный файл. Проблема в том, что JS в одном файле не может вызывать функции во втором файле, если второй файл не загружен первым (см. Переполнение стека, вопрос 25962958), и поэтому в моем случае вызываемые функции не могли отображать другие элементы страницы. . Есть способы обойти эту проблему с последовательностью загрузки (см. Stack Overflow Q. 8996852), но я обнаружил, что проще поместить весь код в один более крупный файл и четко разделить и прокомментировать разделы кода, которые попали бы в одну функциональную группу, напримердержите код входа отдельно и четко комментируйте его как код входа.