Большинство веб-страниц и приложений состоят из множества различных частей. Вместо отправки всего JavaScript, составляющего приложение, сразу после загрузки первой страницы, разделение JavaScript на несколько фрагментов повышает производительность страницы.
В этой лаборатории кода показано, как использовать разделение кода для повышения производительности простого приложения, сортирующего три числа.
Мера
Как всегда, важно сначала измерить, насколько хорошо работает веб-сайт, прежде чем пытаться добавить какие-либо оптимизации.
- Чтобы просмотреть сайт, нажмите «Просмотреть приложение» . Затем нажмите Полноэкранный режим .
- Нажмите «Control+Shift+J» (или «Command+Option+J» на Mac), чтобы открыть DevTools.
- Откройте вкладку Сеть .
- Установите флажок Отключить кеш .
- Перезагрузите приложение.
JavaScript объемом 71,2 КБ просто для сортировки нескольких чисел в простом приложении. Что дает?
В исходном коде ( src/index.js
) библиотека lodash
импортирована и используется в этом приложении. Lodash предоставляет множество полезных служебных функций, но здесь используется только один метод из пакета. Установка и импорт целых сторонних зависимостей, в которых используется лишь небольшая их часть, является распространенной ошибкой.
Оптимизировать
Уменьшить размер пакета можно несколькими способами:
- Напишите собственный метод сортировки вместо импорта сторонней библиотеки.
- Используйте встроенный метод
Array.prototype.sort()
для числовой сортировки. - Импортируйте только метод
sortBy
изlodash
, а не всю библиотеку. - Скачивайте код для сортировки только тогда, когда пользователь нажимает кнопку
Варианты 1 и 2 являются вполне подходящими методами уменьшения размера пакета (и, вероятно, будут иметь наибольший смысл для реального приложения). Однако в этом уроке они используются не для обучения 😈.
Оба варианта 3 и 4 помогают повысить производительность этого приложения. Следующие несколько разделов этой лаборатории посвящены этим шагам. Как и в любом учебнике по программированию, всегда старайтесь писать код самостоятельно, а не копировать и вставлять.
Импортируйте только то, что вам нужно
Необходимо изменить несколько файлов, чтобы импортировать только один метод из lodash
. Для начала замените эту зависимость в package.json
:
"lodash": "^4.7.0",
с этим:
"lodash.sortby": "^4.7.0",
Теперь в src/index.js
импортируйте этот конкретный модуль:
import "./style.css";
import _ from "lodash";
import sortBy from "lodash.sortby";
И обновите способ сортировки значений::
form.addEventListener("submit", e => {
e.preventDefault();
const values = [input1.valueAsNumber, input2.valueAsNumber, input3.valueAsNumber];
const sortedValues = _.sortBy(values);
const sortedValues = sortBy(values);
results.innerHTML = `
<h2>
${sortedValues}
</h2>
`
});
Перезагрузите приложение, откройте DevTools и еще раз взгляните на панель «Сеть» .
Для этого приложения размер пакета был уменьшен более чем в 4 раза без особых усилий, но еще есть возможности для улучшения.
Разделение кода
webpack — один из самых популярных сборщиков модулей с открытым исходным кодом, используемых сегодня. Короче говоря, он объединяет все модули JavaScript (а также другие ресурсы), составляющие веб-приложение, в статические файлы, которые может читать браузер.
Единый пакет, используемый в этом приложении, можно разделить на два отдельных блока:
- Ответственный за код, составляющий наш первоначальный маршрут.
- Вторичный фрагмент, содержащий наш код сортировки.
При использовании динамического импорта вторичный фрагмент можно загружать отложенно или по требованию. В этом приложении код, составляющий чанк, может быть загружен только тогда, когда пользователь нажимает кнопку.
Начните с удаления импорта верхнего уровня для метода сортировки в src/index.js
:
import sortBy from "lodash.sortby";
И импортируйте его в прослушиватель событий, который срабатывает при нажатии кнопки:
form.addEventListener("submit", e => {
e.preventDefault();
import('lodash.sortby')
.then(module => module.default)
.then(sortInput())
.catch(err => { alert(err) });
});
Функция import()
является частью предложения (в настоящее время на этапе 3 процесса TC39) включить возможность динамического импорта модуля. webpack уже включил поддержку этого и использует тот же синтаксис, что и в предложении.
import()
возвращает обещание, и когда оно разрешается, предоставляется выбранный модуль, который разделяется на отдельный фрагмент. После возврата модуля module.default
используется для ссылки на экспорт по умолчанию, предоставляемый lodash. Промис связан с другим .then
, который вызывает метод sortInput
для сортировки трех входных значений. В конце цепочки обещаний . catch()
используется для обработки случаев, когда обещание отклоняется из-за ошибки.
Последнее, что нужно сделать, — это написать метод sortInput
в конце файла. Это должна быть функция, которая возвращает функцию, которая принимает импортированный метод из lodash.sortBy
. Затем вложенная функция может отсортировать три входных значения и обновить DOM.
const sortInput = () => {
return (sortBy) => {
const values = [
input1.valueAsNumber,
input2.valueAsNumber,
input3.valueAsNumber
];
const sortedValues = sortBy(values);
results.innerHTML = `
<h2>
${sortedValues}
</h2>
`
};
}
Монитор
Перезагрузите приложение в последний раз и снова внимательно следите за панелью «Сеть» . Сразу после загрузки приложения загружается только небольшой первоначальный пакет.
После нажатия кнопки для сортировки входных чисел фрагмент, содержащий код сортировки, извлекается и выполняется.
Обратите внимание, как числа по-прежнему сортируются!
Заключение
Разделение кода и отложенная загрузка могут быть чрезвычайно полезными методами для уменьшения первоначального размера пакета вашего приложения, и это может напрямую привести к гораздо более быстрому времени загрузки страницы. Однако есть несколько важных вещей, которые необходимо учитывать, прежде чем включать эту оптимизацию в свое приложение.
Ленивая загрузка пользовательского интерфейса
При отложенной загрузке определенных модулей кода важно учитывать, как это будет выглядеть для пользователей с более слабыми сетевыми подключениями. Разделение и загрузка очень большого фрагмента кода, когда пользователь отправляет действие, может создать впечатление, будто приложение перестало работать, поэтому рассмотрите возможность отображения какого-либо индикатора загрузки.
Ленивая загрузка сторонних модулей узлов
Это не всегда лучший подход к отложенной загрузке сторонних зависимостей в вашем приложении, и это зависит от того, где вы их используете. Обычно сторонние зависимости выделяются в отдельный пакет vendor
, который можно кэшировать, поскольку он не обновляется так часто. Узнайте больше о том, как SplitChunksPlugin может помочь вам в этом.
Ленивая загрузка с помощью JavaScript-фреймворка
Многие популярные фреймворки и библиотеки, использующие веб-пакеты, предоставляют абстракции, упрощающие отложенную загрузку по сравнению с использованием динамического импорта в середине вашего приложения.
- Ленивая загрузка модулей с помощью Angular
- Разделение кода с помощью React Router
- Ленивая загрузка с помощью Vue Router
Хотя полезно понимать, как работает динамический импорт, всегда используйте метод, рекомендованный вашей платформой/библиотекой, для отложенной загрузки определенных модулей.
Предварительная загрузка и предварительная выборка
Там, где это возможно, воспользуйтесь подсказками браузера, такими как <link rel="preload">
или <link rel="prefetch">
чтобы попытаться загрузить важные модули еще быстрее. webpack поддерживает обе подсказки за счет использования магических комментариев в операторах импорта. Более подробно это объясняется в руководстве по предварительной загрузке критических фрагментов .
Ленивая загрузка не только кода
Изображения могут составлять значительную часть приложения. Ленивая загрузка тех, которые находятся ниже сгиба или за пределами области просмотра устройства, может ускорить работу веб-сайта. Подробнее об этом читайте в руководстве Lazysizes .