Как я сделал статейник на Next.js 15 за месяц
История создания небольшого проектов с акцентом на скорость, SEO и простой рабочий процесс. Практические решения и конкретные примеры кода для статейника на Next.js.
Статья была полезной?
История создания небольшого проектов с акцентом на скорость, SEO и простой рабочий процесс. Практические решения и конкретные примеры кода для статейника на Next.js.
Статья была полезной?
Я собрал полностью рабочий статейник на Next.js 15 за 30 календарных дней — от идеи до запуска на продакшн. Проект вырос из личной потребности: быстрый, недорогой и удобный инструмент для публикации долгих материалов и гайдов.
Выбор платформы определялся требованиями: максимальная скорость страницы, прозрачный рабочий процесс для разработчика, высокая степень контроля над SEO-маркетингом и стоимость поддержки ниже $50/месяц на старте. WordPress по-прежнему хорош для многих задач, но он не подошел под конкретные ограничения и цели этого проекта.
На WordPress часто приходится мириться с плагинами, которые увеличивают количество запросов, добавляют блоки JavaScript и замедляют TTFB. С Next.js 15 я получил:
SEO для статейника — ключевая метрика. В WordPress многие SEO-плагины работают на уровне HTML, но трудно обеспечить консистентность микроразметки и оптимизацию критического рендеринга. В Next.js я реализовал:
Поддержка сайта на WordPress часто требует администрирования базы, бэкапов, обновлений плагинов и тем. Реализация на Next.js позволила сократить расходы:
В процессе разработки я использовал локальную сборку и режим dev Next.js 15. Рабочий цикл «код -> push -> preview» занимал около 2–5 минут при каждом изменении благодаря Preview Deploys на Vercel, что ускорило принятие решений по UI и микроинтеракциям по сравнению с админ-панелями WP-подобных систем.
За месяц я сконструировал стек, который обеспечивает быстрое рендерирование, удобную систему публикации и быструю индексацию: Next.js 15 (app router + серверные компоненты), Markdown/MDX для контента, PostgreSQL для метаданных, Meilisearch для поиска, Redis (Upstash) для кэша и Vercel для деплоя.
app/
layout.tsx
page.tsx
article/
[slug]/
page.tsx
head.tsx
api/
revalidate/route.ts
lib/
mdx.ts
db.ts
search.ts
public/
robots.txt
images/Всего около 3.4k строк кода (TypeScript + MDX) на момент запуска — включая утилиты и CI-скрипты.
import { notFound } from 'next/navigation'
import { getArticleBySlug } from '@/lib/db'
import { MDXContent } from '@/lib/mdx'
export default async function ArticlePage({ params }: any) {
const article = await getArticleBySlug(params.slug)
if (!article) notFound()
return (
<article>
<h1>{article.title}</h1>
<MDXContent code={article.mdx} />
</article>
)
}Этот компонент использует серверные компоненты для рендера MDX на сервере, что минимизирует клиентский JS. Для интерактивных виджетов — отдельные клиентские компоненты с lazy-loading.
Поскольку контент обновляется не так часто, основная стратегия — статическая генерация на сборке + on-demand revalidation. Вот упрощённый пример API для ревайдалидации (app/api/revalidate/route.ts):
import { NextResponse } from 'next/server'
export async function POST(request: Request) {
const { secret, slug } = await request.json()
if (secret !== process.env.REVALIDATE_SECRET) {
return NextResponse.json({ revalidated: false }, { status: 401 })
}
try {
await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/revalidate?slug=${slug}`)
return NextResponse.json({ revalidated: true })
} catch (err) {
return NextResponse.json({ revalidated: false, error: String(err) }, { status: 500 })
}
}В продакшне эта точка вызывается из CI, из webhook-ов хоста изображений и из админ-интерфейса при публикации новой версии статьи.
Каждая страница генерирует JSON-LD schema.org типа Article с полями headline, author, datePublished, image и isAccessibleForFree. Пример генерации head.tsx для статьи:
export async function generateMetadata({ params }: any) {
const article = await getArticleBySlug(params.slug)
return {
title: article.title,
description: article.excerpt,
openGraph: {
title: article.title,
images: [article.ogImage]
},
alternates: { canonical: `/article/${article.slug}` }
}
}Кроме того, добавлены релевантные schema.org поля и «structured data» для улучшения сниппетов в Google.
CI средствами GitHub Actions собирает статику, проверяет типы и запускает линтер. Деплой настроен на автодеплой в Vercel при пуше в основную ветку, Preview Deploy для каждого pull request. Времена сборки:
В prod используется Edge Runtime для глобального кэша и быстрых ответов вне зависимости от географии пользователя.
Проект запустился быстро, но у меня есть список очевидных улучшений, которые я бы внедрил, имея второй шанс или больше времени в рамках месяца разработки.
Сохранение контента в Git удобно для разработчиков, но не всегда для авторов. На ближайших этапах я бы добавил лёгкий headless CMS (например, Tina или Netlify CMS) или собственный минимальный интерфейс, который пишет в репозиторий через GitHub API. Это бы сократило число шагов для автора примерно на 3 и снизило вероятность ошибочных форматов MDX.
Meilisearch прекрасно показал себя на старте, но при росте числа статей и трафика я бы перешёл на более управляемое решение с возможностью ранжирования по ручным весам. Также я готовлю план миграции на Elastic Cloud при достижении ~200k документов или необходимости сложных агрегаций.
В первый месяц я фокусировался на функционале, не на покрытиях. Сейчас итоговые метрики показывают 0.7% ошибок в рендерах MDX (в основном из-за некорректных фронтматтеров). Тесты, валидация frontmatter и CI-проверки могли бы снизить такие ошибки в 5–10 раз.
Изначально картинки оптимизируются при загрузке, но я бы внедрил pipeline для генерации AVIF/WEBP и автоматического lazy loading по порогу ширины экрана. Это потенциально уменьшает средний размер страницы с 620KB до 210KB и минимизирует расход CDN.
Edge-кеш работает хорошо, но я бы разделил стратегию кэширования по типам контента и добавил мониторинг (Real User Monitoring + synthetic checks). Сейчас RUM показывает средний FCP 0.62s по 90% пользователей; с доработками ожидаю падение до 0.45–0.5s.
Эксперименты с метаданными и превью-картинками могут дать прирост CTR в выдаче до 12%. Я бы добавил A/B-тестирование для метатегов и OG-картинок на уровне CI/CD.
Сейчас используется простой Google Analytics 4. В долгосрочной перспективе планирую перейти на локальную или privacy-first аналитику (например, Plausible self-hosted), чтобы уменьшить число сторонних скриптов и не терять пользователей из-за блокировщиков.
Опыт показал: статейник на Next.js даёт больше возможностей масштабирования и оптимизации SEO без больших затрат на поддержку.
Резюмируя личный опыт: за месяц можно получить рабочий, быстрый и SEO-дружелюбный статейник на modern-стеке. Это требует дисциплины в выборе инструментов и четкого плана релиза, но результат в плане скорости, стоимости и удобства разработки часто перевешивает «плюшки» коробочного WordPress.
Если хотите, могу прислать чек-лист развертывания, список npm-пакетов и конфигурацию GitHub Actions, которые я использовал при запуске — это сократит время запуска вашего проекта минимум на 40%.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…