Files
homepage/spec/migration.md

14 KiB
Raw Blame History

План миграции сайта vakhrushev.me с Sculpin на Astro

Обзор текущего состояния

Стек

  • Генератор: Sculpin 3 (PHP 8)
  • Шаблоны: Twig (base → internal → article, три уровня наследования)
  • Фронтенд: Webpack 4, SCSS, Vue 2 (интерактивная демка гадалки)
  • Сборка: Docker (PHP + Node контейнеры), Taskfile
  • Деплой: Docker-образ nginx, Ansible на личный сервер
  • Аналитика: Яндекс.Метрика
  • Шрифты: Google Fonts (PT Serif, Source Code Pro), Font Awesome 5
  • Кастомные бандлы Sculpin: HtmlPrettier, SiteMap, TwigExtension (hashed_asset)

Контент

  • 8 статей в markdown (2019-2020), русский язык
  • 1 статья с интерактивным Vue-компонентом (гадалка Шеннона)
  • Страницы: главная, список статей, 404
  • Atom-лента (ручной шаблон)
  • Sitemap (кастомный бандл + шаблон)
  • robots.txt

Структура стилей

  • Переменные SCSS: шрифт PT Serif 20px, ширина 740px, цвета GitHub
  • Базовые стили, стили главной, стили внутренних страниц, навигация
  • BEM-подобная методология

Целевое состояние

Стек

  • Генератор: Astro
  • Стилизация: Tailwind CSS
  • Интерактивность: Vue 3 (islands, для гадалки и будущих компонентов)
  • Сборка: Docker (один Node-контейнер), Taskfile
  • Деплой: Docker-образ nginx, Ansible (без изменений)

Разделы сайта

  1. Главная — краткое описание, ссылки
  2. Блог — статьи и эссе по программированию
  3. Галерея — фотографии (новый раздел, реализуется позже)

Задачи

Этап 1. Инициализация проекта Astro

1.1. Создать проект Astro

  • Инициализировать Astro в корне проекта (или в отдельной ветке)
  • Настроить astro.config.mjs: site URL https://vakhrushev.me, язык ru
  • Установить интеграции: @astrojs/sitemap, @astrojs/rss, @astrojs/vue, @astrojs/tailwind
  • Настроить TypeScript (strict или relaxed — на усмотрение)

1.2. Настроить Tailwind CSS

  • Установить и настроить Tailwind
  • Перенести дизайн-токены из SCSS-переменных в Tailwind-конфигурацию:
    • Шрифты: PT Serif (serif), Source Code Pro (mono)
    • Цвета: #24292e (текст), #0366d6 (ссылки), #e6e6e6 (линии)
    • Ширина контента: 740px
    • Размер шрифта: 20px базовый

1.3. Настроить Docker для сборки

  • Заменить два Docker-образа (PHP + Node) одним Node-образом
    • Использовать актуальную LTS-версию Node (22)
  • Удалить PHP Dockerfile — он больше не нужен
  • Сохранить Dockerfile.nginx.prod, обновить путь: dist/ вместо output_prod/

1.4. Обновить Taskfile

  • Убрать задачи: composer, sculpin, shell-node, format-php
  • Обновить задачи сборки:
    • build-dev: astro build (dev-режим — через astro dev)
    • build-prod: astro build
  • Обновить задачу deploy: путь к собранным файлам dist/
  • Добавить задачу dev: запуск astro dev для локальной разработки
  • Сохранить структуру Docker-команд через Taskfile

Этап 2. Лейауты и компоненты

2.1. Создать базовый лейаут BaseLayout.astro

Аналог текущего base.html.twig. Должен включать:

  • <html lang="ru">, мета-теги (charset, viewport, description, keywords)
  • Open Graph мета-теги (og:site_name, og:title, og:description, og:url, og:locale)
  • Подключение шрифтов Google Fonts (PT Serif, Source Code Pro)
  • Яндекс.Метрика (вынести в отдельный компонент YandexMetrika.astro)
  • Yandex verification мета-тег
  • Слот для контента

Параметры (props): title, description, keywords

2.2. Создать лейаут для внутренних страниц InternalLayout.astro

Аналог internal.html.twig:

  • Использует BaseLayout
  • Навигация (компонент Navigation.astro)
  • Контейнер .page с ограничением ширины

2.3. Создать лейаут для статей ArticleLayout.astro

Аналог article.html.twig:

  • Использует InternalLayout
  • Заголовок статьи <h1>
  • Дата публикации и email внизу
  • Слот для содержимого статьи

2.4. Создать общие компоненты

  • Navigation.astro — навигация (Главная, Блог, Галерея)
  • YandexMetrika.astro — код счетчика аналитики
  • ArticleList.astro — список статей, сгруппированных по годам

Особенность: Font Awesome больше не нужен (социальные ссылки удалены в коммите 63a324c). Если понадобятся иконки — использовать astro-icon или inline SVG.


Этап 3. Content Collections и перенос статей

3.1. Настроить Content Collection для статей

  • Создать src/content/articles/ для markdown-файлов
  • Определить схему в src/content.config.ts:
    {
      title: z.string(),
      description: z.string().optional(),
      date: z.date(),              // извлечь из имени файла или добавить в frontmatter
      keywords: z.array(z.string()).optional(),
      tags: z.array(z.string()).optional(),
      draft: z.boolean().default(false),
    }
    

3.2. Перенести статьи

Перенести 8 markdown-файлов из source/_articles/ в src/content/articles/.

Необходимые изменения в каждом файле:

  • Удалить Sculpin-специфичные поля frontmatter (layout, styles, scripts, use)
  • Добавить поле date (сейчас дата в имени файла, нужно продублировать в frontmatter)
  • Оставить title, description, keywords
  • Опционально: добавить tags для будущей фильтрации

Список статей:

  1. 2019-05-01-predictor.mdОСОБЫЙ СЛУЧАЙ, см. задачу 3.3
  2. 2019-06-01-php-serialization.md
  3. 2019-06-28-storytelling.md
  4. 2019-08-08-yandex-disk-image-hosting.md
  5. 2019-09-26-highload-videos.md
  6. 2020-06-27-interesting-programming-blogs.md
  7. 2020-06-27-type-discriminant.md
  8. 2020-11-08-nullable-fields.md

3.3. Перенести статью с интерактивным компонентом (гадалка)

Статья predictor.md содержит встроенный Vue-компонент <div id="app"></div>.

Шаги:

  • Переименовать файл в .mdx
  • Обновить Vue-компонент PredictorDemo.vue до Vue 3 (Composition API или Options API)
    • @anwinged/predictor — проверить совместимость с Vue 3, при необходимости обновить
    • Перенести scoped-стили компонента на Tailwind или оставить scoped CSS
  • В MDX-файле: импортировать компонент и использовать <PredictorDemo client:visible />
  • Удалить ручное подключение JS/CSS через frontmatter (styles, scripts)

Этап 4. Страницы

4.1. Главная страница src/pages/index.astro

  • Использовать BaseLayout
  • Имя, краткое описание (обновить текст — актуализировать информацию о себе)
  • Ссылки: email, git, другие
  • Список последних статей (через getCollection('articles'))

4.2. Страница списка статей src/pages/articles/index.astro

  • Использовать InternalLayout
  • Список всех статей, сгруппированных по годам (как сейчас в article_list.twig)
  • Сортировка по дате, от новых к старым

4.3. Динамические страницы статей src/pages/articles/[...slug].astro

  • Использовать ArticleLayout
  • Рендеринг markdown/MDX содержимого через render()
  • SEO мета-теги из frontmatter

4.4. Страница 404 src/pages/404.astro

  • Использовать InternalLayout
  • Текст "Страница не найдена" и ссылка на главную

4.5. Страница галереи src/pages/gallery/index.astro (заглушка)

  • Использовать InternalLayout
  • Placeholder-страница "Скоро здесь будут фотографии"
  • Полноценная реализация — отдельная задача в будущем

Этап 5. RSS, Sitemap, SEO

5.1. Настроить RSS-ленту

  • Создать src/pages/rss.xml.ts с использованием @astrojs/rss
  • Включить все статьи (title, description, date, link)
  • URL: /rss.xml
  • Для обратной совместимости: добавить редирект /atom.xml/rss.xml (в nginx или через Astro)

5.2. Настроить Sitemap

  • Интеграция @astrojs/sitemap уже генерирует sitemap автоматически
  • Убедиться, что 404 и служебные страницы исключены

5.3. Настроить robots.txt

  • Создать public/robots.txt со ссылкой на sitemap

5.4. Open Graph и мета-теги

  • Уже реализовано в BaseLayout (задача 2.1)
  • Проверить корректность на каждом типе страниц

Этап 6. Сборка и деплой

6.1. Обновить Docker-сборку

  • Новый docker/node/Dockerfile на Node 22 LTS
  • PHP Dockerfile удалить
  • Обновить Dockerfile.nginx.prod:
    FROM nginx:stable
    COPY dist /usr/share/nginx/html
    
  • Добавить конфиг nginx для SPA fallback (404.html) и кэширования статики

6.2. Обновить Taskfile

Финальная версия задач:

tasks:
  dev:        # astro dev (локальная разработка)
  build-prod: # astro build
  deploy:     # build-prod → docker build → ansible

6.3. Проверить деплой

  • Собрать Docker-образ
  • Проверить, что все страницы отдаются корректно
  • Проверить 404
  • Проверить RSS и sitemap

Этап 7. Очистка

7.1. Удалить файлы Sculpin

  • app/ — SculpinKernel, конфиги
  • bundle/ — кастомные бандлы (HtmlPrettier, SiteMap, TwigExtension)
  • source/ — старые шаблоны, ассеты, контент (после проверки, что всё перенесено)
  • composer.json, composer.lock
  • docker/php/Dockerfile
  • webpack.config.js
  • .php-cs-fixer.php

7.2. Обновить package.json

  • Удалить старые зависимости (webpack, babel, vue 2, node-sass, и т.д.)
  • Удалить старые npm-скрипты
  • Оставить только Astro и его зависимости

7.3. Обновить .gitignore

  • Убрать output_dev/, output_prod/, vendor/
  • Добавить dist/, .astro/, node_modules/

7.4. Обновить README.md

  • Описание нового стека
  • Инструкции по локальной разработке и деплою

Сохранение URL-совместимости

Текущие URL статей имеют формат: /articles/YYYY/MM/DD/slug/ (например, /articles/2019/05/01/predictor/).

Нужно сохранить эти URL, чтобы не сломать внешние ссылки. Варианты:

  1. Настроить slug в Astro — использовать getStaticPaths() с кастомными slug, повторяющими текущую структуру
  2. Редиректы в nginx — если хочется упростить URL-структуру (например, /articles/predictor/), настроить 301-редиректы со старых URL

Рекомендация: упростить URL до /articles/slug/ и настроить редиректы в nginx для старых URL.


Порядок выполнения

Этап 1 (инициализация) → Этап 2 (лейауты) → Этап 3 (контент)
    → Этап 4 (страницы) → Этап 5 (RSS/sitemap) → Этап 6 (деплой) → Этап 7 (очистка)

Этапы 2 и 3 можно частично выполнять параллельно. Этап 7 выполняется только после полной проверки нового сайта.