Выбор технического стека для моего личного блога разработчиков в 2020 году

Проверьте HN обсуждение здесь ! 🤗

Недавно я решил создать свой личный сайт - тот, который вы сейчас читаете, как это бывает!

Удивительно, но собрать "стек технологий", соответствующий моим критериям, оказалось гораздо сложнее, чем ожидалось. Мои критерии довольно просты; я бы ожидал, что большинство разработчиков React имеют аналогичный список. Тем не менее, было удивительно трудно собрать все эти части вместе.

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

tl; dr: Клонируйте репозиторий, чтобы начать работу с этой настройкой: https://github.com/vriad/devii.

Давайте быстро пробежимся по моему списку целей дизайна:

React (+ TypeScript)

Я хочу построить сайт на React и TypeScript. Я люблю их от всего сердца, я использую их для своей повседневной работы, и они будут рядом еще долгое время. Плюс написание непечатного JS заставляет меня чувствовать себя грязным.

Мне не нужны ограничения на то, каким может быть/быть мой личный сайт. Конечно, в настоящее время мой сайт состоит из двух простых, статических постов в блоге. Но в дальнейшем, возможно, я захочу построить страницу, которая содержит интерактивную визуализацию, фильтруемую таблицу, или демо-версию компонента React, который я открыт для просмотра. Даже что-то простое (например, форма подписки на электронную рассылку внизу этой страницы) было гораздо приятнее для реализации в React; как мы использовали, чтобы построить формы заново?

Плюс: я хочу получить доступ к экосистеме npm и всем моим любимым библиотекам пользовательского интерфейса, анимации и стилей. Я искренне надеюсь, что никогда больше не напишу еще одну строку необработанного CSS; CSS-in-JS 4 lyfe baby. Если вы хотите начать со мной вражду в Twitter по этому поводу, во что бы то ни стало на меня.

Хороший авторский опыт

Если это неприятно - писать новые посты в блоге, я не буду этого делать. Это прискорбный закон вселенной. Даже написание постов в блоге с простым HTML - просто набор <p> тегов в div - просто раздражает достаточно, чтобы доставить мне неприятности. Ответ: уценка конечно!

Статические генераторы сайта (ПНГ) , как Гюго и Джекила обеспечивают неоспоримо замечательный опыт разработки. Все, что вам нужно сделать, touch это новый файл .md в нужном каталоге и приступить к записи. К сожалению, все известные мне SSG на основе Markdown слишком строгие. Смешивать React и Markdown на одной странице невозможно или сложно. Если это возможно, вероятно, потребуется какой-нибудь плагин / модуль / расширение, файл конфигурации, блоб шаблона или вопиющий взлом. Извините, Хьюго, я не собираюсь переписывать свой код React, React.createElement как будто это 2015 год.

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

Статическая генерация

Как бы я ни любил Jamstack, он не ограничивает его с точки зрения SEO. Многим блогам, работающим на «безголовой CMS», требуется два обхода перед отображением содержимого блога (один для извлечения статического пакета JS, а другой для извлечения содержимого блога из CMS). Это снижает скорость загрузки страницы и удобство работы с пользователем, что соответственно снижает ваш рейтинг в Google.

Вместо этого я хочу, чтобы каждая страница моего сайта была предварительно обработана для набора полностью статических ресурсов, чтобы я мог развернуть их в CDN и получить быструю загрузку страниц везде. Вы можете получить те же преимущества при рендеринге на стороне сервера, но для этого требуется фактическая балансировка нагрузки на сервере и во всем мире для достижения сопоставимой скорости загрузки страниц. Я люблю такие вещи как следующий парень, даже если у меня есть линия. 😅

Мое решение

Я опишу мой окончательный дизайн архитектуры ниже, вместе с моим обоснованием для каждого выбора. Я перенес эту настройку в стартовый / шаблонный сайт, доступный здесь: https://github.com/vriad/devii. Ниже я ссылаюсь на определенные файлы / функции, которые я реализовал; чтобы увидеть их исходный код, просто клонируйте репозиторий git clone git@github.com:vriad/devii.git

Next.js

Я решил создать свой сайт с помощью Next.js. Это не будет неожиданным решением для тех, кто играл в React со статической или серверной визуализацией в последние годы. Next.js быстро обедает на этом рынке, особенно GatsbyJS (извините, фанаты GatsbyJS).

Next.js - безусловно, самый элегантный (на данный момент) способ создания статической генерации или рендеринга на стороне сервера с помощью React. Они только что выпустили свой генератор статических сайтов следующего поколения (игра слов) в версии 9.3 еще в марте. Таким образом, в духе использования технологий весной их жизни Next.js не представляет никакой сложности.

Вот быстрая разбивка структуры проекта. Не нужно понимать каждую его часть; но может быть полезно сослаться на всю оставшуюся часть этого поста.

.
├── README.md
├── public // all static files (images, etc) go here
├── pages // every .tsx component in this dir becomes a page of the final site
|   ├── index.tsx // the home page (which has access to the list of all blog posts)
|   ├── blog
|       ├── [blog].md // a template component that renders the blog posts under `/md/blog`
├── md
|   ├── blog
|       ├── devii.md // this page!
        ├── whatever.md // every MD file in this directory becomes a blog post
├── components
|   ├── Code.tsx
|   ├── Markdown.tsx
|   ├── <various others>
├── loader.ts // contains utility functions for loading/parsing Markdown
├── node_modules
├── tsconfig.json
├── package.json
├── next.config.js
├── next-env.d.ts
├── .gitignore

TypeScript + React

И React, и TypeScript встроены в ДНК Next.js, так что вы получаете их бесплатно, когда настраиваете проект Next.js.

Gatsby, с другой стороны, имеет специальный плагин для поддержки TypeScript, но он официально не поддерживается и, похоже, находится в низком списке их приоритетов. Кроме того, после того, как я возился с ним в течение часа, я не мог заставить его играть хорошо с горячей перезагрузкой.

Разметка авторинга

Используя специальный getStaticPropsхук Next и великолепный динамический импорт, он тривиален для файла Markdown и передает его содержимое в компоненты React в качестве реквизита. Это позволяет получить священный Грааль, который я искал: способность легко смешивать React и Markdown.

Поддержка Frontmatter

Каждый файл Markdown может включать в себя «блок frontmatter», содержащий метаданные. Я реализовал простую служебную функцию (loadPost), которая загружает файл Markdown, анализирует его содержимое и возвращает объект TypeScript со следующей подписью:

type PostData = {
  path: string; // the relative URL to this page, can be used as an href
  content: string; // the body of the MD file
  title?: string;
  subtitle?: string;
  date?: number;
  author?: string;
  author_image?: string;
  tags?: string[];
  cover_image?: string;
  thumb_image?: string;
};

Я реализовал отдельную функцию, loadPosts которая загружает все файлы Markdown /md/blogи возвращает их в виде массива ( PostData[]). Я использую loadPosts на главной странице этого сайта для отображения списка всех сообщений, которые я написал.

Вдохновленный дизайн

Я использовал замечательный react-markdownпакет для рендеринга Markdown как компонента React. Компонент My Markdown Rendered ( /components/Markdown.tsx) предоставляет некоторые стили по умолчанию, вдохновленные дизайном Medium. Просто измените style плюсы, Markdown.tsx чтобы настроить дизайн по своему вкусу.

Блоки кода в стиле GitHub

Вы можете легко вставлять блоки кода в сообщения блога, используя синтаксис с тройным обратным тэгом. Укажите язык программирования с помощью «языкового тега», как GitHub!

Чтобы добиться этого, я реализовал пользовательский coderenderer ( /components/Code.tsx), для react-markdownкоторого используется response-syntax-highlighter для обработки выделения. Итак, это:

 ```ts // pretty neat huh? const test = (arg: string) => {   return arg.length > 5; }; ``` 

превращается в это:

// pretty neat huh?
const test = (arg: string) => {
  return arg.length > 5;
};

Генерация RSS

RSS-канал генерируется автоматически из вашего блога. Этот канал генерируется с помощью rss модуля (для преобразования JSON в формат RSS) и showdown для преобразования файлов уценки в формат HTML, совместимый с RSS. Фид генерируется на этапе сборки и записывается в виде статического файла /rss.xmlв папку статических ресурсов. Это очень просто. Это радость от возможности легко писать собственные сценарии сборки поверх хуков Next.js getStaticProps!

SEO

Каждая страница блога автоматически заполняет метатеги на основе метаданных поста. Сюда входят titleтег, metaтеги, og:теги, метаданные Twitter и link тег, содержащий канонический URL. Вы можете изменить / дополнить это в PostMeta.ts компоненте.

Статическая генерация

Вы можете создать полностью статическую версию вашего сайта, используя yarn build && yarn export. Этот шаг полностью поддерживается Next.js. Статический сайт экспортируется в out каталог.

После его создания используйте выбранный вами статический хостинг файлов (Firebase Hosting, Vercel, Netlify) для развертывания вашего сайта.

Безумно настраиваемый

Здесь нет ничего "под капотом". Вы можете просматривать и изменять все файлы, которые предоставляют функции, описанные выше. Devii просто предоставляет среду проекта, некоторые утилиты загрузки Markdown-загрузки (in loader.ts) и некоторые разумные настройки стиля по умолчанию (особенно in Markdown.tsx).

Чтобы начать настройку, измените index.tsx(домашняя страница), BlogPost.tsx(шаблон сообщения блога) и Markdown.tsx(средство визуализации Markdown).

Начать

Отправляйтесь в репозиторий GitHub, чтобы начать работу: https://github.com/vriad/devii. Если вам нравится этот проект, оставьте «звезду», чтобы помочь большему количеству людей найти Devii! 😎

Чтобы сразу перейти к коду, клонируйте репозиторий и запустите сервер разработки следующим образом:

git clone git@github.com:vriad/devii.git mysite
cd mysite
yarn
yarn dev