Как я мигрировал flaming.codes с Next.js на Qwik

Моя двухнедельная история миграции flaming.codes с Next.js на Qwik и Qwik City

Прежде всего: как всё закончилось

Если вы хотите пропустить всю историю и сразу увидеть результат, вот он:

  • flaming.codes был переписан с нуля (поэтому далее будем называть его версией 2) и теперь использует Qwik и Qwik City в качестве основного фреймворка, ранее использовался Next.js
  • Я удалил все зависимости, связанные с системой управления контентом (CMS) третьей стороны и кеширующим слоем, и теперь сам хостю весь контент в репозитории на Github этого PWA (Progressive Web App)
  • Я сделал это, потому что заметил, что поддержка всего стека версии 1 flaming.codes отнимала слишком много времени - последней каплей стало обновление CMS (Sanity), после которого мне всё равно пришлось бы что-то переписывать
  • Компонент перевода v1, который включал в себя настраиваемый парсер документов и перевод через Google Translate, был заменен на чистый маркдаун и, соответственно, GPT-4 от OpenAI
  • Еще я не реализовал функцию TTS (текст в речь), но сделаю это в ближайшем будущем, используя модель Whisper от OpenAI
  • flaming.codes все еще размещен на Vercel, но теперь использует Edge Functions для обслуживания сайта вместо Build Output API, так как на данный момент для него нет адаптера развертывания от Qwik City
  • Дизайн также обновлен и теперь поддерживает как светлый, так и темный режим, используя Windy Radix Colors, чтобы цвета Radix были доступны как классы Tailwind

Стартовая страница flaming.codes версии 2

CMS исчез, да здравствует CMS

Основная причина, по которой я написал версию 2 flaming.codes, заключалась в уменьшении зависимостей от сервисов:

  • исключение CMS (и ее CDN), а также управление и хостинг всего контента (посты, категории, активы и т. д.) напрямую в репозитории, который также будет опубликован с открытым исходным кодом
  • как часть этого перехода, удаление кеширующего слоя для контента CMS, поскольку он больше не нужен
  • замена использования Google Translate, а также Microsoft текст в речь на API от OpenAI

Переход от мощной CMS, такой как Sanity и ее динамического конструктора запросов, требует определенных затрат, чтобы реализовать некоторые (легковесные) средства управления контентом самостоятельно. Я не хочу заботиться о необходимости обновления и поддержания такой ключевой части проекта. Моя цель - чтобы это решение работало, даже если я не буду писать пост в течение года, потому что единственное требование должно заключаться в открытии репозитория, написании статьи, а затем просто в отправке изменений в ветку main для запуска новой сборки.

Вы можете ознакомиться с /cms-директорией в корне проекта на GitHub, чтобы увидеть исходный код самостоятельно. Это работает довольно хорошо, просто и полностью самостоятельно, без дополнительного аккаунта и входа в CMS. Текущий опыт теперь на самом деле мощнее, чем раньше, так как теперь я могу использовать Markdown для всего контента, что намного проще писать и поддерживать, чем пользовательский редактор Sanity. Я добавил опцию автоматической перезагрузки для запуска скрипта редактора, чтобы видеть изменения в реальном времени - если я захочу, даже для нескольких языков одновременно.

Более подробно о CMS я расскажу в отдельном посте.

Почему я выбрал Qwik и Qwik City вместо Next.js

Qwik и его полноценный фреймворк под названием "Qwik City" с самого начала показались мне очень привлекательными: ленивая загрузка любого JS автоматически до тех пор, пока он действительно не понадобится, без какой-либо гидратации. В контексте flaming.codes выгода от этой архитектуры уменьшается, так как мой сайт по своей сути является блогом. Чем больше компонентов и взаимодействий имеет веб-приложение, тем больше улучшений можно получить от использования Qwik. Тем не менее, мне было любопытно и хотелось получить собственный опыт работы с ним.

i18n в Qwik по сравнению с Next.js

flaming.codes переведен на 14 языков, включая некоторые, пишущиеся справа налево. Когда я впервые взглянул на Qwik в начале 2023 года (примерно за 10 месяцев до фактической перезаписи версии 2), мне показалось, что настоящего решения для i18n нет, и мои усилия за пределами некоторых первоначальных тестов затухли.

Когда я посмотрел на это снова в декабре, qwik-speak оказался необходимым решением для включения переводов в flaming.codes, поэтому я отпустил старую кодовую базу и приступил к перезаписи.

Новый переводчик

Старый стек использовал API Google Translate, который хорошо мне служил, но весь компонент пришел с некоторой сложностью:

  • контент на исходном языке извлекался из CMS Sanity, анализировался и разбивался на промежуточные фрагменты
  • Каждый фрагмент затем переводился на доступные целевые языки
  • Переведенные фрагменты снова собирались, чтобы оригинальный контент, включая форматирование, был восстановлен и доступен для интерфейса

Это работало достаточно хорошо, но код был относительно сложен для чтения и поддержки.

Теперь flaming.codes использует OpenAI для перевода всего контента. Вся настройка стала намного проще:

  • новая статья пишется в простом Markdown
  • статья отправляется в OpenAI и переводится целиком
  • LLM достаточно умны, чтобы переводить только необходимые части, но не, например, весь «frontmatter» (подсказка даёт руководство LLM относительно того, какие поля не должны подвергаться процедуре)

Развертывание на Vercel

Qwik City мог бы быть экспортирован как статический сайт (SSG), но это означало бы, что я не мог бы использовать динамические конечные точки, поэтому flaming.codes использует адаптер "Vercel Edge" для продолжения развертывания и хостинга через Vercel. Я бы хотел, чтобы "Build Output API" от Vercel также был доступен в качестве адаптера, но пока этого достаточно.

flaming.codes ранее использовал Build Output API, что означало, что серверный код использовал API Node.js - на Vercel Edge это больше не возможно, так как это довольно странная и запутанная смесь API Web и Node.js. Это потребовало от меня переписывания некоторых компонентов для обеспечения совместимости.

ИИ и прозрачность

Хотя и не готов к первоначальному выпуску версии 2, я обновлю метаданные для новых статей, чтобы они содержали больше информации о том, какие аспекты статьи были созданы с использованием ИИ.

В том же движении я также сделаю аналитику сайта публично доступной, чтобы ещё больше повысить прозрачность. flaming.codes использует Plausible.io, аналитический сервис, уважающий конфиденциальность, для базовой агрегации использования.

Новый дизайн

Герой статьи flaming.codes версии 2

В рамках переосмысления я также обновил дизайн немного. Он похож на большинстве страниц, но с новой краской.

Поля метаданных статьи flaming.codes версии 2

Новые цвета + светлый и темный режимы

Благодаря Windy Radix Colors, поддержка светлого и темного режимов была легко реализована, так как библиотека предоставляет все варианты цветов для обоих режимов.

Страница всех постов flaming.codes версии 2 в темном режиме

Страница всех постов flaming.codes версии 2 в светлом режиме

Теперь я использую палитру Radix Color как плагин Tailwind, который поставляется с тщательным подбором вариантов цветов, а также простой поддержкой светлого/темного режима. Я также перешел на Lucide Icons, так как они доступны через библиотеку для Qwik. Для сравнения, вот некоторые скриншоты старого дизайна:

Стартовая страница flaming.codes версии 1

Герой статьи flaming.codes версии 1

Заключение и что дальше

Версия 1 flaming.codes очень хорошо мне служила с момента ее первоначального запуска, но я почувствовал, что стек нужно упростить, уменьшив зависимости от других служб.

На перезапись мне потребовалось около двух недель. Управление контентом с этого момента будет значительно проще и также поможет мне избежать излишних затрат.

Версия 2 flaming.codes не достигла функциональной паритетности с версией 1 к моменту запуска, но я добавлю недостающие функции в ближайшие недели, такие как кнопка «нравится/не нравится» или функция TTS (текст в речь).