Это первая история из серии Real Dev Engineering (Как строится Real Dev). В этом рассказе мы поговорим о NextJS и NestJS, что это такое, как их объединить.

Скажи еще раз. Что есть что?

Я знаю, это немного сбивает с толку :) Я дам небольшой контекст. Если вы знаете, что это такое, можете пропустить эту часть.

NestJS - это прогрессивный фреймворк Node.js для создания эффективных, надежных и масштабируемых серверных приложений. Слишком абстрактно? Это фреймворк для создания серверной части, такой как Django для Python или Spring Boot для Java.

Вы спросите, а как насчет Экспресса или Коа? Express больше похож на Flask в Python. Он обрабатывает только HTTP-части, не давая вам «батарейки», такие как аутентификация, ORM, реальное «промежуточное ПО» (промежуточное ПО Express - это другое понятие), кэширование и т. Д. И т. Д. Здесь также не так много передового опыта.

NestJS, с другой стороны, обеспечивает структуру кодирования (вдохновленную Angular) и имеет лучшие практики по всем вышеперечисленным вещам. Фактически, он использует Express в качестве бэкэнда, поэтому все совместимо. Вы можете заменить серверную часть на fastify, если вам нужна производительность.

NextJS - это версия React для внешнего интерфейса с батарейным питанием. Фреймворк выполняет следующие функции:

  • Рендеринг на стороне сервера: преимущества SEO и время начальной загрузки
  • Маршрутизация
  • Объединение ваших CSS, JS и их динамическая загрузка
  • Поддержка CSS является нативной (и будет встроенной)

Обе эти платформы имеют открытый исходный код и полностью поддерживают TypeScript. Уже есть масса успешных сценариев использования в производственной среде.

Начиная

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

Обычно с NextJS вы можете использовать его встроенный веб-сервер в качестве бэкэнда (на основе Express), но он довольно ограничен. Большинство людей используют рукописный сервер (также в основном на основе Express 😆) и просто используют «сервер» Next для его визуализации. Подумайте о вызове функции render. Наша цель - заменить этот пользовательский Express на NestJS.

Чтобы представить Nest на картинке, мы создаем веб-сервер с помощью NestJS. Он внутренне поддерживает экземпляр сервера Next. Когда приходит запрос типа https://real.dev/tasks:

  • Сервер NextJS принимает его, видит как запрос, не связанный с API, направляет его на NextController (см. Ниже)
  • NextController вызывает свою внутреннюю render функцию
  • Функция рендеринга ищет task.tsx в папке pages
  • Экспортированный по умолчанию компонент React из task.tsx отображается и возвращается в качестве ответа

Следующий модуль в Nest

NestJS организует код в модули (как модуль task выше). Мы создадим специальный модуль для взаимодействия с сервером Next.

Мы создаем следующий экземпляр сервера и предоставляем его контроллерам для использования.

Мы должны использовать FactoryProvider, поскольку следующий сервер необходимо prepare() перед использованием.

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

Контроллер прост: просто отправьте запрос на сервер Next.

Далее мы подробно рассмотрим две проблемы, которые у нас возникли с этим подходом.

Конфигурация сборки Next

NextJS берет конфигурацию либо из конструктора, либо из next.config.js. Там две конфигурации относительно каталога в NextJS, которые не очень хорошо документированы. Если у вас стандартная установка, она, вероятно, «просто работает». Но в целом знать о них полезно.

  • dir: исходный каталог. Вы можете просто подумать, что это каталог, содержащий папку pages. По умолчанию это .- текущая папка. Это также используется, когда вы делаете next build <dir>. В нашем случае это packages/website
  • distDir: относительный путь от исходной папки к выходным данным сборки. По умолчанию .next. Вот почему по умолчанию встроенный актив будет помещен в ./.next. В нашем случае это должно быть что-то вроде path.relative('packages/website', <BUILD_DIR>). Это связано с тем, что у нас есть специальный каталог сборки, который отделен от сборки для разработки и сборки.

Я узнал об этом, посмотрев на этот код. При правильных настройках в next.config.ts мы сможем развернуть сервер в стадии разработки!

Еще одна вещь, которую нужно сделать. Для сборки prod запускаем next build packages/website. Он будет искать файл с именем next.config.js под dir и там объект конфигурации. Мы не используем этот файл для разработки, потому что следующий сервер строится на лету при разработке и берет конфигурацию из нашего next.config.ts (не JS!). Чтобы поделиться конфигурацией, мы можем легко сделать что-то вроде:

Здесь требуемый путь указывает на скомпилированный JS-вывод от TSC. Это должно быть типичным, если проект настроен с возможностью публикации NPM. (На самом деле нет, но это уже другая история 😛)

Горячая перезагрузка всего материала

На данный момент у нас есть работающая интеграция Next + NextJS. Работает как на разработку, так и на продакшн. Еще кое-что.

В документации NestJS есть небольшая хитрость: горячая перезагрузка сервера с помощью webpack. Я рекомендую всем попробовать.

Это в основном означает, что каждое изменение в коде вашего сервера требует быстрой перезагрузки, вместо того, чтобы ждать 5 секунд для перезапуска сервера. Он работает ненавязчиво, то есть ничего не меняет. Как это круто! Следуя документу, чтобы настроить его.

Одна проблема после того, как у нас есть NextJS на картинке: провайдер будет перезагружен, когда экземпляр app будет закрыт. Это означает, что экземпляр сервера Next создается повторно, поэтому кэш компиляции страниц и компонентов в памяти теряется. Несмотря на то, что внутреннему серверу требуется меньше секунды для перезагрузки, NextJS перекомпилирует все материалы внешнего интерфейса, что займет еще 3–4 секунды. Это возвращает нас на круги своя!

Решение на самом деле довольно простое: кэшируйте объект сервера в провайдере.

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

Заключение

Вот все, что я сделал для создания проекта backend + frontend, со следующими полезностями:

  • Хорошая структура кодирования
  • Поддержка SSR из коробки
  • Горячая перезагрузка любых изменений

Это ни в коем случае не идеальное решение. Есть и другие способы интеграции, например nest-next в справочнике. Если вы видите что-нибудь, что может быть лучше, дайте мне знать!

Надеюсь, вам понравится! Следите за новостями.

P.S: Я рад поговорить о деталях или технологиях в целом, ответьте здесь или напишите мне на почту [email protected].

О нас @ Real Dev

Real Dev - это сообщество разработчиков с практическими инженерными навыками. Мы стремимся помочь разработчикам проявить себя, а компаниям - нанять талантливых разработчиков.

Вы можете продемонстрировать свои навыки, решая наши задачи, и мы поможем вам найти работу разработчика в поисках такого способного разработчика, как вы! Попробуйте!

использованная литература