Уменьшите полезную нагрузку JavaScript с помощью разделения кода

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

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

В окне браузера отображается приложение Magic Sorter с тремя полями для ввода чисел и кнопкой сортировки.

Мера

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

  1. Чтобы просмотреть сайт, нажмите «Просмотреть приложение» . Затем нажмите Полноэкранный режим полноэкранный .
  2. Нажмите «Control+Shift+J» (или «Command+Option+J» на Mac), чтобы открыть DevTools.
  3. Откройте вкладку «Сеть» .
  4. Установите флажок Отключить кеш .
  5. Перезагрузите приложение.

Панель «Сеть» показывает пакет JavaScript размером 71,2 КБ.

JavaScript объемом 71,2 КБ просто для сортировки нескольких чисел в простом приложении. Что дает?

В исходном коде ( src/index.js ) библиотека lodash импортирована и используется в этом приложении. Lodash предоставляет множество полезных служебных функций, но здесь используется только один метод из пакета. Установка и импорт целых сторонних зависимостей, в которых используется лишь небольшая их часть, является распространенной ошибкой.

Оптимизировать

Уменьшить размер пакета можно несколькими способами:

  1. Напишите собственный метод сортировки вместо импорта сторонней библиотеки.
  2. Используйте встроенный метод Array.prototype.sort() для числовой сортировки.
  3. Импортируйте только метод sortBy из lodash , а не всю библиотеку.
  4. Скачивайте код для сортировки только тогда, когда пользователь нажимает кнопку

Варианты 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 и еще раз взгляните на панель «Сеть» .

Панель «Сеть» показывает пакет JavaScript размером 15,2 КБ.

Для этого приложения размер пакета был уменьшен более чем в 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>
    `
  };
}

Монитор

Перезагрузите приложение в последний раз и снова внимательно следите за панелью «Сеть» . Сразу после загрузки приложения загружается только небольшой первоначальный пакет.

На панели «Сеть» показан пакет JavaScript размером 2,7 КБ.

После нажатия кнопки для сортировки входных чисел фрагмент, содержащий код сортировки, извлекается и выполняется.

На панели «Сеть» показан пакет JavaScript размером 2,7 КБ, за которым следует пакет JavaScript размером 13,9 КБ.

Обратите внимание, как числа по-прежнему сортируются!

Заключение

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

Ленивая загрузка пользовательского интерфейса

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

Ленивая загрузка сторонних модулей узлов

Это не всегда лучший подход к отложенной загрузке сторонних зависимостей в вашем приложении, и это зависит от того, где вы их используете. Обычно сторонние зависимости выделяются в отдельный пакет vendor , который можно кэшировать, поскольку он не обновляется так часто. Узнайте больше о том, как SplitChunksPlugin может помочь вам в этом.

Ленивая загрузка с помощью JavaScript-фреймворка

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

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

Предварительная загрузка и предварительная выборка

Там, где это возможно, воспользуйтесь подсказками браузера, такими как <link rel="preload"> или <link rel="prefetch"> чтобы попытаться загрузить важные модули еще быстрее. webpack поддерживает обе подсказки за счет использования магических комментариев в операторах импорта. Более подробно это объясняется в руководстве по предварительной загрузке критических фрагментов .

Ленивая загрузка не только кода

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

,

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

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

В окне браузера отображается приложение Magic Sorter с тремя полями для ввода чисел и кнопкой сортировки.

Мера

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

  1. Чтобы просмотреть сайт, нажмите «Просмотреть приложение» . Затем нажмите Полноэкранный режим полноэкранный .
  2. Нажмите «Control+Shift+J» (или «Command+Option+J» на Mac), чтобы открыть DevTools.
  3. Откройте вкладку «Сеть» .
  4. Установите флажок Отключить кеш .
  5. Перезагрузите приложение.

Панель «Сеть» показывает пакет JavaScript размером 71,2 КБ.

JavaScript объемом 71,2 КБ просто для сортировки нескольких чисел в простом приложении. Что дает?

В исходном коде ( src/index.js ) библиотека lodash импортирована и используется в этом приложении. Lodash предоставляет множество полезных служебных функций, но здесь используется только один метод из пакета. Установка и импорт целых сторонних зависимостей, в которых используется лишь небольшая их часть, является распространенной ошибкой.

Оптимизировать

Уменьшить размер пакета можно несколькими способами:

  1. Напишите собственный метод сортировки вместо импорта сторонней библиотеки.
  2. Используйте встроенный метод Array.prototype.sort() для числовой сортировки.
  3. Импортируйте только метод sortBy из lodash , а не всю библиотеку.
  4. Скачивайте код для сортировки только тогда, когда пользователь нажимает кнопку

Варианты 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 и еще раз взгляните на панель «Сеть» .

Панель «Сеть» показывает пакет JavaScript размером 15,2 КБ.

Для этого приложения размер пакета был уменьшен более чем в 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>
    `
  };
}

Монитор

Перезагрузите приложение в последний раз и снова внимательно следите за панелью «Сеть» . Сразу после загрузки приложения загружается только небольшой первоначальный пакет.

На панели «Сеть» показан пакет JavaScript размером 2,7 КБ.

После нажатия кнопки для сортировки входных чисел фрагмент, содержащий код сортировки, извлекается и выполняется.

На панели «Сеть» показан пакет JavaScript размером 2,7 КБ, за которым следует пакет JavaScript размером 13,9 КБ.

Обратите внимание, как числа по-прежнему сортируются!

Заключение

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

Ленивая загрузка пользовательского интерфейса

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

Ленивая загрузка сторонних модулей узлов

Это не всегда лучший подход к отложенной загрузке сторонних зависимостей в вашем приложении, и это зависит от того, где вы их используете. Обычно сторонние зависимости выделяются в отдельный пакет vendor , который можно кэшировать, поскольку он не обновляется так часто. Узнайте больше о том, как SplitChunksPlugin может помочь вам в этом.

Ленивая загрузка с помощью JavaScript-фреймворка

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

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

Предварительная загрузка и предварительная выборка

Там, где это возможно, воспользуйтесь подсказками браузера, такими как <link rel="preload"> или <link rel="prefetch"> чтобы попытаться загрузить важные модули еще быстрее. webpack поддерживает обе подсказки за счет использования магических комментариев в операторах импорта. Более подробно это объясняется в руководстве по предварительной загрузке критических фрагментов .

Ленивая загрузка не только кода

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