Зменшіть розмір вашої пачки

18 червня 2020 р. 9 хв. Читання 2534

зменшення

Незважаючи на те, що сьогодні у нас швидші комп’ютери та мобільні пристрої, ми як розробники повинні думати про аудиторію, для якої ми будуємо продукт в цілому. Не кожен має доступ до одного типу швидких пристроїв або знаходиться в найшвидшій мережі Інтернет. Отже, ми повинні мати більш широкий погляд на проблеми з продуктивністю. Ефективність може бути досягнута різними способами, але в цій статті ми зосередимося на фронтенд-ефективності. Ми розглядаємо цей аспект уважніше і пропонуємо можливі вдосконалення в цій галузі.

Продуктивність на передній панелі

Оптимізація продуктивності інтерфейсу є критично важливою, оскільки на неї припадає близько 80-90% часу відгуку користувача. Отже, коли користувач чекає завантаження сторінки, приблизно 80-90% часу припадає на пов'язаний з інтерфейсом код та активи. На малюнках нижче показано співвідношення зовнішніх/серверних ресурсів, які потрібно завантажити для LinkedIn.

Джерело: http://www.stevesouders.com/

Велика частина часу завантаження інтерфейсу витрачається на виконання файлів JavaScript, а також на рендеринг сторінки. Але найважливішою частиною для покращення продуктивності інтерфейсу є зменшення розміру набору JavaScript, який слід завантажувати через мережу. Чим менший розмір набору JavaScript, тим швидше сторінка може бути доступна для користувачів.

Якщо ми подивимося історичні дані, то побачимо, що файли JavaScript у 2010 році становили в середньому 2 КБ. Але з розвитком JavaScript, введенням нових бібліотек JavaScript, таких як Angular або React, та концепцією односторінкових додатків, середній розмір активів JavaScript збільшився до 357 КБ у 2016 році. Нам потрібно використовувати ці нові технології для кращих рішень. Але нам також потрібно розглянути можливі шляхи підвищення їх продуктивності, наприклад, зменшивши загальний розмір пакета JavaScript. Але перед тим, як заглибитися в цю тему, нам слід ознайомитись із наборами JavaScript. Які вони саме?

Набори JavaScript

Для запуску вашої програми інтерфейсу потрібна купа файлів JavaScript. Ці файли можуть бути у форматі внутрішньої залежності, як файли JavaScript, які ви написали самі. Вони також можуть бути зовнішніми залежностями та бібліотеками, які ви використовуєте для побудови свого додатку, наприклад React, lodash або jQuery. Отже, щоб ваша сторінка завантажилася вперше, ці файли JavaScript повинні бути доступними для програми. Тож як ми їх викриваємо?

Раніше спосіб викриття файлів JavaScript був набагато простішим. Для більшості веб-сторінок не потрібно було багато ресурсів JavaScript. Оскільки ми не мали доступу до стандартного способу отримання залежностей, нам довелося покладатися на використання глобальних залежностей. Уявіть, що нам потрібен як jQuery, так і main.js та other.js, які містять всю логіку нашого додатка JavaScript. Спосіб, яким ми змогли викрити ці залежності, виглядав приблизно так:

Це було просте рішення для цієї проблеми, але швидко вийшло з-під контролю при масштабуванні програми. Наприклад, якщо main.js змінюється таким чином, що залежить від коду в other.js, нам потрібно змінити порядок наших тегів сценаріїв так:

Як ми бачимо, управління такою структурою коду в масштабі швидко стало б безладом. Але через деякий час з’явилися кращі рішення для управління цим у додатках. Наприклад, якщо ви використовували NodeJS, ви могли б покластись на власну модульну систему NodeJS (на основі специфікацій commonJS). Це дозволить вам використовувати функцію require для отримання залежностей. Отже, у середовищі Node наш наведений вище фрагмент коду буде виглядати приблизно так:

На сьогоднішній день у вас немає лише декількох файлів JavaScript для запуску програми. Залежності JavaScript для вашої програми можуть включати кілька сотень або тисяч файлів, і цілком очевидно, що їх перелік, як зазначений вище фрагмент, неможливий. Цьому є кілька причин:

  • Поділ ресурсів JavaScript на окремі файли вимагає багато запитів HTTP, коли різні частини програми вимагають різних залежностей. Це не буде ефективним і займає багато часу
  • Крім того, NodeJS require є синхронним, але ми хочемо, щоб він був асинхронним і не блокував основний потік, якщо актив ще не завантажений

Отже, найкращим підходом є розміщення всього коду JavaScript в одному файлі JavaScript та обробка всіх залежностей у ньому. Ну, це основна робота пакета JavaScript. Хоча різні пакети можуть мати різні стратегії для цього. Давайте розглянемо це трохи далі і побачимо, як пакет досягає цього. Тоді ми побачимо, чи є додаткові вдосконалення, які ми можемо зробити, щоб досягти меншого розміру набору та, отже, більшої продуктивності. Для цілей цієї статті ми використовуватимемо Webpack як пакет, що є одним із найвідоміших варіантів.

Ми зробили власну демонстрацію для .
Насправді ні. Клацніть тут, щоб перевірити .

Створення зразкового набору за допомогою Webpack

Почнемо з налаштування простого проекту Webpack. Ми збираємось використовувати основні пакети для запуску простого проекту веб-додатків. React, ReactDOM як фреймворк інтерфейсу, SWC як швидша альтернатива Babel для транпіляції, а також серія інструментів і завантажувачів Webpack. Ось як виглядатиме наш package.json:

Нам також знадобиться webpack.config.js, який є точкою входу конфігурації для наших команд Webpack. У цьому файлі є кілька варіантів, але давайте пояснимо кілька важливих:

  • режим - це можливість для Webpack дізнатися, чи слід робити оптимізацію, виходячи з опції, якій він передається. Ми обговоримо це далі пізніше
  • вихід - Цей параметр повідомляє Webpack, де він повинен завантажувати або розміщувати зібрані пакети на кореневому рівні. Він бере як шлях, так і ім'я файлу
  • HTMLWebpackPlugin - Ця опція допомагає нам полегшити обслуговування наших файлів HTML за допомогою пакета Webpack
  • навантажувачі - ці доповнення навантажувача допоможуть вам перетворити більшість сучасних функцій мови кодування в зрозумілий код для всіх браузерів

Вимірювання та аналіз

Тепер настав час провести початкові вимірювання для нашої збірки Webpack. Коли Webpack робить компіляцію, нам потрібна якась статистика про вбудовані модулі, швидкість компіляції та сформований графік залежностей. Webpack вже пропонує нам інструменти для отримання цієї статистики за допомогою простої команди CLI:

Передаючи --json> compilation-stats.json, ми просимо Webpack генерувати статистику збірки та графік залежностей у вигляді файлу json із зазначеним назвою. Передаючи прапор --profile, ми отримуємо більш детальну статистику побудови окремих модулів. Після запуску цієї команди ви отримуєте файл json, що включає багато корисної інформації. Але щоб полегшити ситуацію, ми будемо використовувати рекомендований інструмент, який буде візуалізувати всі ці статистичні дані побудови. Все, що вам потрібно зробити, це перетягнути compilation-stats.json у зазначений розділ цього офіційного інструменту аналізу. Після цього ми отримуємо наступні результати.

Аналіз Webpack

Ми отримуємо наступну таблицю із загальною інформацією про аналіз побудови Webpack:

Версія Webpack, яка використовується для компіляції 4.43.0
Спеціальний хеш компіляції a770d6c609235bbb24fe
Час компіляції в мілісекундах 522
Кількість модулів 8
Кількість шматків 1
Кількість активів 2

Графік залежностей

Якщо ми клацнемо на розділі залежностей, ми отримаємо подібну діаграму та таблицю, яка відображає різні залежності в нашому додатку, детальну інформацію про кожну залежність та спосіб їх зв’язку між собою.

Графік залежності

Зараз ця статистика побудови дуже корисна, але оскільки ми будемо зосереджуватися виключно на зменшенні та оптимізації розміру набору, ми будемо використовувати спеціалізований інструмент Webpack, який називається webpack-bundle-analyzer. Цей інструмент дозволить вам візуалізувати розмір вихідних файлів Webpack та показати інтерактивну масштабовану карту дерева. Давайте налаштуємо це для нашого проекту. Перше, що потрібно встановити:

Наступне, що нам потрібно зробити, це встановити відповідну конфігурацію у файлі webpack.config.js:

Тепер все, що вам потрібно зробити, це підключити скрипт у своєму package.json для запуску аналізатора:

Отже, після запуску звіту про пакет npm run-script, ми отримуємо візуальне зображення того, що знаходиться в нашому наборі, і бачимо, хто з них займає більшу частину розміру. Ось як це виглядає для нашого проекту:

Аналізатор пакетів Webpack

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

Оптимізація пакета №1: Запустіть Webpack у виробничому режимі

Ця стратегія оптимізації набору та зменшення загального розміру набору є простою та зрозумілою. Webpack має робочий прапор (-p), який робить кілька оптимізацій нестандартними. Отже, якщо ми запустимо наш сценарій збірки за допомогою наведеної нижче команди, ми повинні отримати деяку оптимізацію:

Після запуску цього ми можемо побачити, що розмір нашого пакета зменшиться з 970 КБ до 128 КБ. Але як Webpack впорався з цією рішучою оптимізацією за допомогою такої простої команди? Ну, це в основному дві причини:

  • Під капотом React використовуватиме плагін під назвою UglifyJS, який обробляє мініфікацію коду та усунення мертвого коду, видаляючи зайвий пробіл або невикористаний код.
  • Він також встановлює NODE_ENV на виробництво. Таким чином, деякі пакунки, такі як React, не включатимуть код налагодження

Це хороший крок до зменшення розміру набору та зменшення часу завантаження для користувачів. Давайте подивимося, що ще ми можемо зробити.

Оптимізація пакета №2: Встановіть легші альтернативні бібліотеки

Розмір пакета React все ще трохи великий (124 КБ у нашому проекті), навіть після попередньої оптимізації, яку ми зробили. Перевіряючи звіт webpack-bundle-analyzer, ми бачимо, що React зайняв значну частину нашого пакета. Тож ми розглянемо можливість замінити його на більш легку версію React, яка називається preact, розміром лише 3 КБ.

Коли ми встановлюємо цей пакет як залежність, ми отримуємо як ядро ​​React API, так і підтримку DOM; і як додатковий крок ми можемо встановити preact-compat як рівень сумісності для React розміром 2 КБ. Таким чином, ми можемо просто використовувати preact як замінник React у нашому проекті. Preact є більш продуктивним, ніж React, як ми бачимо у наведеному нижче порівнянні продуктивності між різними бібліотеками, які використовувались для побудови простого тесту MVC “To To”:

Джерело: https://developit.github.io/

Отже, зараз ми збираємось встановити Preact для нашого проекту і подивитися, як це впливає на наш розмір пакета. Спочатку ми встановлюємо preact та preact-compat:

І тоді нам потрібно лише встановити псевдонім config у wepack.config.js, щоб сумісність цієї бібліотеки з усім вашим кодом React працювала:

Отже, після того, як це налаштовано та запущено наш звіт про пакет npm run-script, ми отримуємо наступний аналіз пакета. На цій інтерактивній діаграмі ми бачимо, що розміри наборів, пов’язаних з React, тепер зменшуються приблизно до 23 КБ порівняно з тим, що було раніше, як 124 КБ. Це велике зменшення розміру пакета для нас:

Використання веб-пакета-аналізатора дозволяє нам візуально бачити пакунки, які встановлені в нашому додатку. Якщо пакет займає багато місця, ми можемо розглянути такі стратегії, як заміна його на легшу бібліотеку версій (як це було зроблено вище).

Висновок

Наразі нам вдалося зменшити розмір набору з 970 Кб до 23 Кб, що є зменшенням розміру набору в 42 рази. Крім того, пам’ятайте, що структура та залежності нашого проекту були невеликими, але ініціатива щодо зменшення розміру пакета для більших та складніших проектів може бути більш вигідною.

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

  • Подумайте про переписування великих бібліотек, де вам можуть не знадобитися всі його функціональні можливості. Наприклад, багато розробників використовують Moment.js для синтаксичного аналізу та перевірки дат у великому за розміром JavaScript, але не всім потрібна вся бібліотека для простих синтаксичних аналізацій дат. Подумайте над тим, щоб писати прості утилітні функції, а не покладатися на великі бібліотеки
  • Перевірте, чи використовуєте ви лише функціональний модуль бібліотеки, який можна імпортувати окремо, не імпортуючи всю бібліотеку. Хорошим прикладом цього випадку використання є lodash, для якого ви можете імпортувати будь-яку його функцію бібліотеки утиліти окремо
  • Нарешті, розглянемо розділення коду. Не кожну залежність потрібно завантажувати при кожному завантаженні сторінки, тому було б сенс згрупувати їх окремо. Наприклад, зовнішні залежності NPM змінюються не так сильно, як код нашого додатка. Отже, розділення їх на окремий пакет дозволить браузеру кешувати їх, поки вони не були змінені, а отже зменшить кількість пакетів, які потрібно завантажувати при кожному завантаженні сторінки

Ресурси

  • https://www.sciencefocus.com/future-technology/can-computers-keep-getting-faster/
  • https://www.keycdn.com/support/the-growth-of-web-page-size
  • https://medium.com/better-programming/reducing-js-bundle-size-58dc39c10f9c
  • https://www.contentful.com/blog/2017/10/10/put-your-webpack-on-a-diet-part-1/
  • https://medium.com/@rajaraodv/using-preact-instead-of-react-70f40f53107c
  • https://medium.com/a-young-devoloper/analyzing-and-reducing-react-bundle-size-bb2d2577b22a
  • https://codeengineered.com/blog/why-front-end-performance-important/
  • http://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/
  • https://www.keycdn.com/support/the-growth-of-web-page-size
  • https://medium.com/better-programming/reducing-js-bundle-size-58dc39c10f9c
  • https://medium.com/@gimenete/how-javascript-bundlers-work-1fc0d0caf2da
  • https://blog.jakoblind.no/3-ways-to-reduce-webpack-bundle-size/

Повна видимість робочих програм React

LogRocket - це як відеореєстратор для веб-додатків, що записує буквально все, що відбувається у вашому додатку React. Замість того, щоб здогадуватися, чому трапляються проблеми, ви можете зібрати та повідомити про те, у якому стані знаходилась ваша програма, коли сталася проблема. LogRocket також відстежує продуктивність вашого додатка, звітуючи за допомогою таких показників, як завантаження клієнтського процесора, використання пам’яті клієнта тощо.

Проміжний пакет LogRocket Redux додає додатковий рівень видимості до ваших сеансів користувача. LogRocket реєструє всі дії та стан із ваших магазинів Redux.

Модернізуйте спосіб налагодження програм React - починайте моніторинг безкоштовно.