Мой стэк для интернет-магазина на NextJS

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

Сайт:

Github:

На момент запуска в магазине было около 19 тыс товаров, сгруппированных по моделям и коллекциям. В дальнейшем планируется расширение ассортимента до 40-50 тыс товаров.

Фреймворк и база данных

Основу проекта составляют фреймворк NextJS и база данных MongoDB (для работы с ней я использовал mongoose). Последняя выбрана во многом из-за гибкости (есть множество специфичных характеристик для разных моделей радиаторов) и наличия отличного приложения MongoDB Compass, позволяющего наполнять и обновлять базу через импорт CSV (база товаров хранится изначально в Google Sheets).

Связь между документами и коллекциями происходит через текстовое поле `slug` вместо `_id`. Такой подход значительно упрощает обновление и перенос данных. Так, в случае неудачной заливки товаров и моделей в базу, их можно просто удалить и добавить заново импортом файла CSV, не опасаясь за сохранение связей между сущностями.

Этот же подход, хорошо работает и для SQL баз.

Кэширование запросов к базе

У меня были опасения по поводу работы `unstable_cache` с `mongoose`, но пока что кэширование работает, как и ожидалось. Так как данные на сайте обновляются редко, то время кэширования выставлено на 12 часов.


Типичный запрос выглядит так:

```

const line= (await unstable_cache(async () => await Line.findOne({ slug: lineSlug }).lean(), ["cache:line", lineSlug], {revalidate: 60 * 60 * 12 )()) as TLine | null;

```

Wordpress в качестве CMS

В качестве CMS здесь используется WordPress. Это значительно упрощает работу по управлению наполнением страниц. Для идентификации нужно контента используются значения поля `slug` для соответствующих сущностей.

Например, описание для коллекции "Cube" находится по адресу `page-content-line-cube`.Саму настройку WP для использования в качестве CMS я подсмотрел в этом видео:

К сожалению, у меня не получилось использовать встроенные в WP мета-теги, поэтому использовал плагин Advanced Custom Fields, позволяющий заводить для страниц и записей собственные поля.

Компонент Image и CDN

Для передачи изображений товаров используется CDNNow.

Настройка довольна проста, достаточно указать в компоненте `Image` требуемые размеры изображений, исходя из размеров окна и далее уже сам компонент передаст подходящую ширину в функцию `loader`:


```

<Image

loader={({ src, width }) =>`${CdnUrl}/${src}?width=${width}`}

src={img.src}alt={img.alt}

sizes="(max-width: 768px) 50vw, (max-width: 1280px) 33vw, 25vw"

/>

```

`CdnUrl` - адрес, который предоставляет сервер при регистрации вашего сайта.

UI

Визуальная часть создана за счет `tailwindcss` и `shadcn`. Это мой выбор по-умолчанию для большинства проектов. Хотя с последней библиотекой периодически и возникают сложности. Так в этом проекте компонент `Drawer` отвечал за вывод вариантов покраски и подключений радиаторов и некорректно работал на мобильных телефонах. Поэтому его пришлось заменить на похожий по функционалу компонент `Sheet`.

11
Начать дискуссию