Как я оптимизировал нынешний проект

В этой записи буду рассказывать про свой последний опыт оптимизации NextJS-проекта (который ещё в процессе оптимизации)

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

Оптимизация сборки проекта ♻️

В последнее время, наш проект в GitLab CI/CD начал показывать время сборки и деплоя больше 20 минут! Это очень долго и особенно, когда тебя просят сделать срочный фикс. Тогда эти 20 минут превращаются в вечность.

Само приложение собирается 4 минут. В проекте более 300 компонентов и 160 страниц в папке /pages

Решил попробовать сократить время хотя бы до 15 минут и начал с оптимизации сборки NextJS.

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

Проанализировал проект с помощью @next/bundle-analyzer, заранее нашёл несколько библиотек из-за которых сборка весила на +1.4 мб. больше (gzip 378kb)! Это mapbox-gl и ckeditor.

Так как ими практически не будет пользоваться покупатель (хоть они и выполняют важную часть сайта), решил их выпилить из package.json и написал два компонента, которые будут подгружать асинхронно через <script /> эти либы только в тех местах, где они реально будут использоваться.

Скажу сразу, что сборку это ускорило незначительно, только на 5-10 секунд.

Далее, я решил настроить next.config.js и заменить стандартный лоадер на esbuild (а если точней, то esbuild-loader).

Если смотреть на доку esbuild, то можно обратить внимание, что он быстрей почти в 100 раз, чем другие JS-сборщики. Дело в том, что он написан на языке Go, который компилируется в нативный код, что положительно влияет на быстродействие приложения. Проще говоря, сборщик написанный на Go будет выполнять свою работу намного быстрей, чем написанный на JS. Подробнее тут

Говоря про наш рабочий проект, тооооо, да, удалось сэкономить +-60 сек. Иногда даже сборка выполнялась на 100 сек. быстрей (как на скрине выше).

Удаление лишних библиотек из package.json ❌

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

Так как до сборки проекта, наш CI/CD начинает устанавливать все необходимые зависимости для проекта, это занимает тоже какое-то время из 20 минут. Установка зависимостей занимала более двух минут (120-150 сек).

Решил удалить сразу CKEditor, mapbox-gl, ибо их решил подключить через <script />.

Вспомнил про Storybook, который я установил в самом начале, в надежде на то, что у нас будет крутая дока и набор UI-компонентов. И я понял, что много мечтать тоже не есть хорошо.

Удалил еще несколько неиспользуемых библиотек и в итоге, удалось сэкономить 10-15 секунд.

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

В итоге, из 20-22 минут, удалось сделать ~15 минут ✅, что уже довольно неплохой результат.

Пока, из-за недостатка опыта в оптимизации сборки проекта, я могу не знать каких-то нюансов в том же Docker или в Webpack и думаю, битва ещё не окончена. Надеюсь, что сборку удастся сократить до 10 минут.

Позже попробую рассказать, как я смог довольно неплохо оптимизировать загрузку сайта с помощью ленивой и динамической подгрузки ресурсов. Ускорив загрузку сайта на 40%

Увы, но esbuil-loader и NextJS не подружились полностью 😞

Возник баг из-за которого не отображались товары. На локалхосте всё работало отлично, если запускать через next dev, но если сбилдить проект и запустить next start, то при переходе между страницами, getServerSideProps просто не выполнялся.

Поочерёдно начал избавляться от кода, что я писал при оптимизации проекта в надежде на то, что этот долбанный метод всё же заработает.

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

Вспомнил, что в next.config.js я подключал esbuild-loader, который без единого бага запустил мой проект, что меня очень насторожило.

Попробовал выпилить esbuild-loader из конфигов.

И, о чудо, метод getServerSideProps снова заработал!

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