Оптимизация производительности приложения Vue.js: часть 2 – Отложенная загрузка маршрутов и анти-паттерн использования vendors.js.

Spread the love

В предыдущей статье мы узнали, что такое разбиение кода, как оно работает с Webpack и как его использовать с отложенной загрузкой в приложении Vue. Теперь мы немного углубимся в код и изучим наиболее полезные шаблоны для разбиения кода в приложениях Vue.js.

Часть 1  —  Введение в оптимизацию производительности и отложенную загрузку.

Часть 2  —  Отложенная загрузка маршрутов и анти-паттерн использования vendors.js.

Часть 3 — Отложенная загрузка Vuex и отдельных компонент

Часть 4 — Отложенная загрузка библиотек

Часть 5  —  Использования кеша Service Worker

Часть 6 — Предзагрузка

Проблема с большими приложениями

Vue-router – это библиотека, которая позволяет разделить веб-приложение на отдельные страницы. Каждая страница представляет собой маршрут, связанный с определенным URL

Зная это, представьте, что у нас есть простое приложение для портфолио со следующей структурой:

Как вы, вероятно, заметили, в зависимости от того, какой маршрут мы посещаем, нам может не понадобиться ни Home.vue, ни About.vue (у которой есть зависимость от lodash). Но тем не менее оба они будут находиться в одном пакете app.js и будут загружаться независимо от того, какой у пользователя будет маршрут посещения. Какая трата времени на загрузку страницы!

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

Это недопустимо, когда пользователю достаточно всего 2 – 5 секунд ожидания загрузки что бы покинуть ваш веб-сайт!

Разделение кода на основе маршрутов с помощью vue-router

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

Как и все остальное в Vue.js – это чрезвычайно просто. Вместо того, чтобы импортировать компоненты непосредственно в объекты маршрута, нам просто нужно передать туда динамическую функцию импорта. Компонент маршрута будет загружен ТОЛЬКО после задействование данного маршрута.

Таким образом, вместо обычного статического импорта компонента маршрута:

import RouteComponent form './RouteComponent.vue'

const routes = [{ path: /foo', component: RouteComponent }]

Нам нужно импортировать его динамически, что создаст новый пакет с этим маршрутом в качестве точки входа:

const routes = [
  { path: /foo', component: () => import('./RouteComponent.vue') }
]

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


С помощью этой настройки webpack создаст три пакета:

  • app.js —наш основной пакет с точкой входа приложения (main.js) и библиотеками/компонентами, необходимыми для каждого маршрута
  • home.js — комплект с домашней страницей, которая будет загружаться только при использование маршрута /
  • about.js — пакет с информацией о странице (и ее зависимостью – lodash), которая будет загружена только при использование маршрута /about.

*Имена пакетов не являются такими которые сгенерирует webpack. Имена выбраны такими только для облегчения понимания. Webapck генерирует что-то вроде 0.js 1.js и т. д. В зависимости от конфигурации вашего веб-пакета.

Разделение кода на основе маршрутов во многих случаях может решить все проблемы связанные с производительностью и может быть применено практически к любому приложению менее чем за несколько минут!

Разделение кода в экосистеме Vue

Возможно вы, используете Nuxt или vue-cli для создания своего приложения. Если это так, важно знать, что у них есть свои нюансы поведение в отношении разделения кода:

  • в vue-cli 3  все отложенные части кода будут предварительно подготовлены для предзагрузки по умолчанию. Мы узнаем об использовании предзагрузки позже. Если вы хотите узнать больше о предзагрузки в vue-cli, посмотрите эту ветку
  • в Nuxt все маршруты уже разделены на части по умолчанию, (при использование системы маршрутизации Nuxt)

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

Анти-шаблон использования пакета vendor.js

Пакет vendor.js обычно используется в виде отдельного js-файла, содержащего все модули из node_modules.

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

Видно проблему? Даже если нам нужен lodash (который является одной из зависимостей) только в одном маршруте, он включен в vendor.js вместе со всеми другими зависимостями, и поэтому он всегда будет загружен.

Объединение всех зависимостей в одном файле звучит заманчиво, но это увеличивает время загрузки приложения.

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

Предположим, Home.vue также нуждается в lodash.

В этом случае переход от /about (About.vue) к / (Home.vue) приведет к загрузке lodash дважды.

Это все же лучше, чем загружать тонны избыточного кода, но если у нас уже есть эта зависимость, бессмысленно ее не использовать, верно?

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

// webpack.config.js
optimization: {
  splitChunks: {
    chunks: 'all'
  }
}

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

Вы можете прочитать больше об этом процессе в документации по Webpack.

Заключение

Разделение кода по маршрутам – один из лучших (и самых простых) способов сохранять размер первоночально загружаемого пакета небольшим. В следующей части мы узнаем обо всех других частях (хранилищах Vuex и отдельных компонентах), которые можно отделить от основного пакета и загружать отложено.

Оригинал: Vue.js App Performance Optimization: part 2— Lazy loading routes and vendor bundle anti-pattern.


Spread the love

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *