Вы можете легко публиковать свои идеи на таких сайтах, как Dev.to, Hashnode или Medium, но в идеале иметь полный контроль над собственным контентом. Существует постоянно растущий список инструментов для создания собственного
Первоначально я использовал Jekyll для публикации своего блога, но затем переключился на Gatsby, используя шаблон Lumen. Я использую Gatsby с версии 0, примерно в мае 2017 года.
Я перейду от Hello, World! проекта Гэтсби к блогу о кодировании с подсветкой синтаксиса кода и переключением тем для этого темного режима.
Существует богатая экосистема плагинов, стартеров и тем, доступных для Gatsby, которые помогут вам быстро начать работу, но я хочу использовать прогрессивный подход к представлению Gatsby, сосредоточив внимание на основах того, как работает проект Gatsby.
Почему Гэтсби?
Gatsby — это генератор статических сайтов, поэтому динамическое создание страниц при запросе страниц отсутствует. Построенный вывод для сайта Gatsby может быть размещен на CDN, что делает его глобально доступным и масштабируемым.
Gatsby может использовать файлы Markdown для создания страниц в проекте сайта. Gatsby будет считывать файлы Markdown в файловую систему Gatsby и преобразовывать Markdown в HTML, а затем при создании сайта создавать статические страницы.
Конечным результатом является сверхбыстрый сайт с небольшой задержкой при запросе страниц.
Уценка и многомерные выражения
Я документирую свой путь разработки с 2016 года в Markdown. Markdown предлагает способ простого редактирования текстовых файлов, которые можно преобразовать в HTML.
MDX (или Markdown JSX) — это инструмент, который позволяет вам писать JSX в ваших документах Markdown примерно так:
import { RainbowText } from '. /components/rainbow’;
## A Markdown Heading
Gatsby, безусловно, лучший фреймворк, который я использовал для работы с Markdown и MDX, так как нет необходимости в специальных обозначениях выше, используя переднюю часть ваших сообщений.
Что мне нужно?
Если вы собираетесь следовать этому примеру, вам понадобится несколько вещей:
базовая настройка
текстовый редактор
базовое понимание React
Если у вас нет ни одного из них, есть как StackBlitz, так и GitHub Codespaces, где вы можете создать пустой репозиторий GitHub и начать работу со средой разработки оттуда.
В приведенных ниже примерах я буду использовать VS Code в качестве текстового редактора и Yarn в качестве предпочитаемого менеджера пакетов. Если вы предпочитаете npm, это круто. 👍
Вы также можете найти полный код этого руководства на GitHub.
Ладно, пора начинать!
Привет, мир!
Пришло время раскрутить проект Гэтсби. Я собираюсь сделать большую часть этого из командной строки для начала:
# create the project directory
mkdir
# change into the directory
cd
# initialise a package.json file
yarn init -y
# initialise the git repo
git init
Прохладно. Теперь, прежде чем перейти к
# create.gitignore file in my directory
touch.gitignore
# add ignore contents with echo
echo «# Project dependencies
.cache
node_modules
# Build directory
public
# Other
.DS_Store
Теперь я могу установить все npm, которые мне нужны, без криков VS Code Git о слишком большом количестве активных изменений. Давайте теперь установим некоторые зависимости, чтобы начать работу с Gatsby:
yarn add gatsby
# -p is to create parent directories too if needed
mkdir -p src/pages
# create the index (home) page
touch src/pages/index.js
Далее мы добавим первый компонент React (из многих) для проекта. Я добавлю следующее в index.jsсозданный файл:
import React from «react»;
export default function IndexPage () {
return Hello, World! ;
}
Теперь я готов запустить команду Gatsby developиз командной строки:
# if you’re using npm 👇
# $ (npm bin) /gatsby develop
yarn gatsby develop
Это запустит сервер разработки Gatsby и скажет, что мой проект доступен для просмотра в браузере через порт 8000 (порт Gatsby по умолчанию).
Использование двоичных команд Gatsby непосредственно из интерфейса командной строки (CLI) вполне выполнимо, но большинство людей добавят доступные команды в scriptsраздел package.jsonфайла, например:
«scripts»: {
«build»: «gatsby build»,
«dev»: «gatsby develop»,
«serve»: «gatsby serve»,
«clean»: «gatsby clean»
},
В качестве дополнительного бонуса здесь можно добавить несколько дополнений к сценариям Гэтсби.
Если мы не хотим каждый раз запускать проект на одном и том же порту, его можно изменить с помощью -pфлага, а после этого указать порт. Например, gatsby develop -p 8945.
Если мы хотим открыть вкладку браузера после того, как проект будет готов, мы можем добавить -oв скрипт.
Я сделаю то же самое со serveсценарием, поэтому я знаю, что когда я создал проект, он находится на другом порту, отличном от порта разработки:
«scripts»: {
«build»: «gatsby build»,
«dev»: «gatsby develop -p 8945 -o»,
«serve»: «gatsby serve -p 9854 -o»,
«clean»: «gatsby clean»
},
И при этом обязательное «Hello, World!» Добро пожаловать завершено, и я могу двигаться дальше с остальной частью этого поста! 🤓
Наконец, я зафиксирую изменения, которые я сделал до сих пор:
# add everything for committing
git add.
# commit to repo
git commit -m 'init project’
Контент для блога
Хорошо, сейчас с проектом не так много всего происходит, поэтому сначала я добавлю
# this creates the folders in the root of the project
mkdir -p content/2021/03/{06/
# create individual files
touch content/2021/03/06/
touch content/2021/03/07/
touch content/2021/03/08/
Я буду использовать их во всех примерах, которые делаю.
Вы заметите расширение файла.mdx. Это
Передний вопрос
Прежде чем я добавлю контент для блога, мне нужно поговорить о вступительной части.
Front Matter — это способ хранения информации о файле, который может быть использован Gatsby при построении из них страниц. А пока я добавлю titleпост и файл date. Я также добавлю к ним немного контента. Вот наш первый пост:
---
title: Hello World — from mdx!
date:
---
My first post!!
## h2 Heading
Some meaningful prose
### h3 Heading
Some other meaningful prose
Вот наш второй пост:
---
title: Second Post!
date:
---
This is my second post!
Третий пост:
---
title: Third Post!
date:
---
This is my third post!
> with a block quote!
And a code block:
```js
const wheeeeee = true;
```
Это все, что касается постов на данный момент, потому что эти посты еще не распознаны Гэтсби как страницы. Мне нужно сообщить Гэтсби, где найти контент для добавления в проект. Для этого я собираюсь добавить файл конфигурации в Gatsby.
Давайте зафиксируем сделанные мной изменения в Git:
# add changed file for committing
git add.
# commit to repo
git commit -m 'add markdown files’
Конфигурация Гэтсби
Конфигурация Gatsby — это то, что используется для определения и настройки многих подключаемых модулей Gatsby, которые вы можете использовать. Подробнее об
touch gatsby-config.js
Это создает
Плагины Гэтсби
Теперь я могу установить и настроить плагины, необходимые Гэтсби для поиска и отображения созданных мной файлов. Сейчас я установлю их все и кратко расскажу, для чего они нужны:
yarn add
Беглый взгляд на package.jsonсейчас показывает, что у меня установлена следующая версия зависимостей:
«dependencies»: {
«@
«@
«gatsby»: «^3.1.1»,
«
«
«react»: «^17.0.1»,
«
},
Следует отметить, что в Gatsby нет необходимости импортировать React в ваши компоненты с помощью React 17. Но для полноты картины и во избежание путаницы я включу его в эти примеры.
Теперь мне нужно настроить
module.exports = {
plugins: [
`
{
resolve: `
options: {
path: `${__dirname}/content`,
name: `content`,
},
},
],
};
Зафиксировать изменения до сих пор:
git add.
git commit -m 'add gatsby plugins’
Гэтсби GraphQL
Теперь пришло время посмотреть, где я работаю с файлами в Gatsby, используя клиент Gatsby GraphQL, GraphiQL. Возможно, вы заметили, что CLI указывает два
You can now view
⠀
http: //localhost:8000/
⠀
View GraphiQL, an
⠀
http: //localhost:8000/___graphql
Теперь я собираюсь использовать ___graphqlмаршрут (три символа подчеркивания), чтобы увидеть файлы в файловой системе.
Если это кажется немного пугающим, я попытаюсь охватить все части, которые могут показаться не имеющими особого смысла. Если вы следуете всем инструкциям, у вас должно получиться скопировать примеры в обозреватель GraphiQL.
Когда я открываю проводник GraphiQL, у меня есть несколько панелей проводника. Это все доступные данные для изучения в проекте, и они зависят от того, что я настроил в
Панель запросов GraphiQL и результаты находятся рядом с ней. Здесь я буду писать запросы GraphQL для получения нужных мне данных. В нижней части панели запросов также есть раздел ПЕРЕМЕННЫЕ ЗАПРОСА, о котором я расскажу позже.
В крайнем правом углу находится обозреватель документации GraphQL.
Запрос локальных файлов с помощью GraphQL
Далее я собираюсь запросить файлы, которые я добавил ранее на панели запросов GraphiQL. В этом запросе я запрашиваю заголовок и дату, определенные в шрифте файлов:
{
allMdx {
nodes {
frontmatter {
title
date
}
}
}
}
Если мы вставим это в панель запросов, нажмем большую кнопку воспроизведения, мы вернемся к некоторым данным на панели результатов. Мы также можем использовать проводник на левой панели для выбора данных. Вот что я получаю после выполнения запроса:
{
«data»: {
«allMdx»: {
«nodes»: [
{
«frontmatter»: {
«title»: «Hello World — from mdx!»,
«date»: «
}
},
{
«frontmatter»: {
«title»: «Second Post!»,
«date»: «
}
},
{
«frontmatter»: {
«title»: «Third Post!»,
«date»: «
}
}
]
}
},
«extensions»: {}
}
Это большой объект JSON с соответствующей информацией, которую мы запросили в запросе. Мы скоро рассмотрим, как это использовать. На данный момент это означает, что мы можем использовать эти данные в проекте Gatsby для создания страниц.
Метаданные сайта
В
Это будет полезно в будущем, когда я захочу добавить метатеги на сайт для поисковой оптимизации (SEO). (Опять же, подробнее об этом позже.) Сейчас я собираюсь определить некоторую основную информацию о сайте в
Я мог бы определить метада сайта непосредственно module.exportsтак:
module.exports = {
siteMetadata: {
title: `My Gatsby Blog`,
description: `This is my coding blog. `,
},
plugins: [
// configured plugins here
{
// empty for brevity
},
],
};
Объект метаданных сайта может стать немного большим, и я обнаружил, что хранение его в отдельном объекте может сделать его немного проще для понимания, поэтому вместо этого я собираюсь определить его отдельно:
const siteMetadata = {
title: `My Gatsby Blog`,
description: `This is my coding blog. `,
};
Затем добавьте siteMetadataобъект в файл конфигурации Gatsby:
const siteMetadata = {
title: `My Gatsby Blog`,
description: `This is my coding blog. `,
};
module.exports = {
siteMetadata,
plugins: [
// configured plugins here
{
// empty for brevity
},
],
};
Теперь я могу снова перейти к обозревателю GraphiQL и запросить метаданные этого сайта с помощью следующего запроса:
{
site {
siteMetadata {
title
description
}
}
}
Всегда полезно остановить и перезапустить сервер разработки, если вы вносите изменения в
{
«data»: {
«site»: {
«siteMetadata»: {
«title»: «My Gatsby Blog»,
«description»: «This is my coding blog.»
}
}
},
«extensions»: {}
}
Сделать хук метаданных сайта
Теперь, когда у меня есть метаданные сайта в файловой системе Gatsby, я могу запрашивать их везде, где хочу, с помощью статического обработчика запросов Gatsby useStaticQuery. Я собираюсь убить сервер разработки и перезапустить его после того, как добавлю в src/pages/index.jsфайл следующее:
import { graphql, useStaticQuery } from «gatsby»;
import React from «react»;
export default function IndexPage () {
const {
site: { siteMetadata },
} = useStaticQuery (graphql`
{
site {
siteMetadata {
title
description
}
}
}
`) ;
console.log («=====================») ;
console.log (siteMetadata) ;
console.log («=====================») ;
return Hello World! ;
}
Небольшое примечание о некоторых обозначениях: const { site: { siteMetadata }, }это быстрый способ получить данные в siteзапросе, где я извлекаю их siteMetadataиз siteобъекта. Это называется деструктурированием.
Теперь, после того как я снова запустил сервер разработки, я могу перейти в консоль браузера (Control+ Shift+ Jв Windows/Linux, Command+ Option+ Jв macOS) и увидеть siteMetadataобъект в выводе консоли.
Я получаю следующий вывод консоли:
=====================
{title: «My Gatsby Blog», description: «This is my coding blog.»}
description: «This is my coding blog.»
title: «My Gatsby Blog»
__proto__: Object
=====================
Не беспокойтесь о предупреждении консоли об отсутствующей странице 404, которая не найдена (net: ERR_ABORTED 404 (Not Found)). Я сделаю это позже.
Чтобы не писать этот запрос каждый раз, я хочу использовать его в компоненте. Я собираюсь абстрагировать это в отдельный крючок:
# make a folder for all the hooks to live
mkdir src/hooks
# creathe the file
touch src/hooks/
Теперь я добавлю хук во вновь созданный src/hooks/
import { graphql, useStaticQuery } from «gatsby»;
export const useSiteMetadata = () => {
const { site } = useStaticQuery (
graphql`
query SITE_METADATA_QUERY {
site {
siteMetadata {
title
description
}
}
}
`
) ;
return site.siteMetadata;
};
Вы могли заметить, что этот запрос отличается от запроса из проводника GraphiQL:
+ query SITE_METADATA_QUERY {
site {
siteMetadata {
title
description
}
}
}
Это имя запроса. Поскольку в проекте я буду использовать много запросов, имеет смысл дать им осмысленные имена.
Теперь я реализую новый хук в src/pages/index.jsфайле:
import React from «react»;
import { useSiteMetadata } from «.../hooks/
export default function IndexPage () {
const { title, description } = useSiteMetadata () ;
return (
<>
{title}
{description}
</>
) ;
}
Это намного менее многословно, и я могу выбирать, какие элементы мне нужны из файла SITE_METADATA_QUERY.
Пришло время сообщить об изменениях, сделанных на данный момент:
git add.
git commit -m 'add site metadata and metadata hook’
Стилизация с помощью пользовательского интерфейса темы
Для стилизации этого проекта я буду использовать Theme UI
Есть несколько дополнительных зависимостей для пользовательского интерфейса темы, а именно:
yarn add
После их установки мне нужно добавить
module.exports = {
siteMetadata,
plugins: [
`
`
{
resolve: `
// rest of the module unchanged
Теперь, если я остановлю и перезапущу сервер разработки, у меня будет немного другой вид сайта! Все стало немного голубым — или барвинковым, если быть точным! Это
Плагин Gatsby для Theme UI предлагает множество параметров конфигурации, некоторые из которых я рассмотрю более подробно, когда это необходимо. Сейчас я собираюсь создать папку и определить объект темы для пользовательского интерфейса темы:
# create the folder for the Theme UI theme
mkdir src/
# create the theme file
touch src/
В src/
Для темного режима я использую deepпредустановку Theme UI и распространяю ее на modesобъект для dark. (Подробнее об этом скоро.) А пока знайте, что это позаботится о многих темах для меня:
import { deep, swiss } from «@
const theme = {
...swiss,
colors: {
...swiss.colors,
modes: {
dark: {
...deep.colors,
},
},
},
styles: {
...swiss.styles,
p: {
fontFamily: «body»,
fontWeight: «body»,
lineHeight: «body»,
fontSize: 3,
},
},
};
export default theme;
Теперь, если я перезапущу сервер разработки (опять же, да, вы научитесь с этим справляться), он будет выглядеть немного более приемлемым с применением швейцарской темы. На момент написания Theme UI иногда не обновлял localhostстраницу, поэтому необходимо обновить страницу в браузере.
Зафиксируйте изменения в Git:
git add.
git commit -m 'add Theme UI and configure presets’
Время добавить некоторые компоненты React!
Компонент макета
У Гэтсби нет определенного макета, что возлагает эту ответственность на разработчика. В данном случае я делаю макет всего сайта. Можно включить множество макетов для использования в проекте Gatsby, но в этом примере я буду использовать только один.
Теперь я собираюсь реорганизовать то, что у меня есть на данный момент, чтобы все было обернуто Layoutкомпонентом. То, что у меня сейчас есть, src/pages/index.jsможно использовать для Headerкомпонента, поэтому сейчас я собираюсь создать пару файлов для Layoutи Header:
# create a components folder
mkdir src/components
# create Layout and Header files
touch src/components/header.js src/components/layout.js
Теперь переместим заголовок и описание из src/pages/index.jsво вновь созданный src/components/header.jsкомпонент.
Вместо того, чтобы useSiteMetadataиспользовать в Headerкомпоненте, я передам useSiteMetadataнеобходимые мне реквизиты в заголовок из Layoutкомпонента, где заголовок будет жить. (Подробнее об этом чуть позже.)
import { Link as GatsbyLink } from «gatsby»;
import React from «react»;
import { Box, Heading, Link } from «
export const Header = ({ siteTitle, siteDescription }) => {
return (
<Box
as="div"
sx={{
m: «0 auto»,
maxWidth: «640px»,
p: «1.45rem 1.0875rem»,
}}
>
{siteDescription}
) ;
};
Я добавил несколько основных стилей, используя элементы макета Theme UI. Это выглядит немного иначе, чем раньше: Box, Link, Heading... что? Это все компоненты пользовательского интерфейса темы, которые можно использовать для макетов, элементов форм и многого другого.
Вы можете заметить as={GatsbyLink}ссылку, добавленную к Linkкомпоненту. Это использует asопору в пользовательском интерфейсе темы и позволяет передаваемому компоненту принимать стили пользовательского интерфейса темы.
Есть отличный пост от Пола Скэнлона, в котором более подробно объясняется, как это делается в Theme UI. Для действительно всестороннего объяснения пользовательского интерфейса темы есть также «Понимание пользовательского интерфейса темы «того же автора.
Также есть sxи variantреквизит из Theme UI. sxпозволяет передавать дополнительные стили компоненту. Думайте об этом как об эквиваленте поддержки JSX style={{}}. Свойство variantпозволяет применять группу предопределенных стилей из темы к используемому компоненту.
Теперь о Layoutкомпоненте, который находится в src/components/layout.js:
import React from «react»;
import { Box } from «
import { useSiteMetadata } from «.../hooks/
import { Header } from «. /header»;
export const Layout = ({ children }) => {
const { title, description } = useSiteMetadata () ;
return (
<>
<Box
as="div"
sx={{
margin: «0 auto»,
maxWidth: «640px»,
padding: «0 1.0875rem 1.45rem»,
}}
>
</>
) ;
};
Здесь я сохраняю useSiteMetadataхук и передаю реквизиты, необходимые Headerкомпоненту, опять же с sxреквизитом, чтобы добавить некоторые базовые стили для выравнивания основного содержащего div. Затем я создаю mainоболочку для файла children.
Свойство childrenсостоит в том, чтобы вернуть все, что Layoutинкапсулирует компонент, включая все, к чему я хочу применить макет. Например:
This is wrapped
Это вернет все в Layoutкомпоненте и то, что он обертывает. В приведенном выше примере это в настоящее время будет заголовок и H1, обернутый Layoutкомпонентом.
В качестве примера я вернусь на главную страницу (src/pages.index.js) и добавлю следующее:
import React from «react»;
import { Layout } from «.../components/layout»;
export default function IndexPage () {
return (
<>
This is wrapped
</>
) ;
}
Результатом является заголовок, предоставленный в Layoutкомпоненте и H1 This is wrapped.
Запрос сообщений страницы индекса
Теперь пришло время получить сообщения, которые я создал в начале, и отобразить их на странице индекса в виде списка интерактивных ссылок.
Чтобы получить информацию о публикации, я воссоздам запрос, который я сделал в разделе о запросах к локальным файлам с помощью GraphQL, с парой дополнительных битов:
{
allMdx (sort: { fields: [frontmatter___date], order: DESC }) {
nodes {
id
slug
excerpt (pruneLength: 250)
frontmatter {
title
date (formatString: «YYYY MMMM Do»)
}
}
}
}
Я добавил в idузел и файл slug. Это путь к.mdxфайлам.
Он excerptиспользует функцию Gatsby для получения первых 250 символов из тела сообщения, а также добавляет некоторое форматирование с dateпомощью другой встроенной функции Gatsby.
Затем, чтобы упорядочить сообщения в порядке убывания даты, я добавил сортировку: allMdx (sort: { fields: [frontmatter___date], order: DESC }) {. Это сортировка по дате в первых сообщениях.
Добавление этого в проводник GraphiQL дает мне следующий результат:
{
«data»: {
«allMdx»: {
«nodes»: [
{
«id»: «
«slug»: «2021/03/08/
«excerpt»: «This is my third post! with a block quote! And a code block:»,
«frontmatter»: {
«title»: «Third Post!»,
«date»: «2021 March 8th»
}
},
{
«id»: «
«slug»: «2021/03/07/
«excerpt»: «This is my second post!»,
«frontmatter»: {
«title»: «Second Post!»,
«date»: «2021 March 7th»
}
},
{
«id»: «75391ba1−3d6b−539f−
«slug»: «2021/03/06/
«excerpt»: «My first post!! h2 Heading Some meaningful prose h3 Heading Some other meaningful prose»,
«frontmatter»: {
«title»: «Hello World — from mdx!»,
«date»: «2021 March 6th»
}
}
]
}
},
«extensions»: {}
}
Теперь я могу использовать этот запрос в src/pages/index.jsфайле, чтобы получить эти данные для использования на индексной странице. В IndexPageфункции я деструктурирую dataреквизиты, переданные компоненту через запрос GraphQL:
import { graphql, Link as GatsbyLink } from «gatsby»;
import React from «react»;
import { Box, Heading, Link } from «
import { Layout } from «.../components/layout»;
export default function IndexPage ({ data }) {
return (
<>
{data.allMdx.nodes.map (({ id, excerpt, frontmatter, slug }) => (
<Box
key={id}
as="article"
sx={{
mb: 4,
p: 3,
boxShadow: «0 10px 15px -3px rgba (0, 0, 0, 0.1)»,
border: «1px solid #d1d1d1»,
borderRadius: «15px»,
}}
>
<Link as={GatsbyLink} to={`/${slug}`}>
{frontmatter.date}
{excerpt}
))}
</>
) ;
}
export const query = graphql`
query SITE_INDEX_QUERY {
allMdx (sort: { fields: [frontmatter___date], order: DESC }) {
nodes {
id
excerpt (pruneLength: 250)
frontmatter {
title
date (formatString: «YYYY MMMM Do»)
}
slug
}
}
}
`;
При этом используются ранее детализированные компоненты. Обратите внимание, что excerpt, frontmatterи slugдеструктурируются из data.allMdx.nodes:
{data.allMdx.nodes.map (({ excerpt, frontmatter, slug }) => (
Нажав на ссылку, я попаду на страницу 404 разработки Gatsby.js. Это потому, что я еще не сделал страницы для.mxdфайлов. Это следующее.
Я зафиксирую то, что я сделал до сих пор, прежде чем двигаться дальше:
git add.
git commit -m 'add Header and Layout components’
Использование
Я собираюсь использовать Gatsby File System Route API, чтобы получить пути к файлам сообщений, которые я создал ранее. File System Route API — это способ программного создания страниц из моих данных GraphQL.
Этот подход имеет специальную нотацию файла для страницы, которая будет целевой, когда Gatsby генерирует данные файловой системы во время сборки. В файле указаны узел и слаг. Сначала я создам файл, а затем подробно расскажу, откуда берутся данные:
# create the route api file
touch src/pages/{mdx.slug}.js
В файле я определю запрос GraphQL для данных, которые я хочу включить в этот шаблон:
import { graphql } from «gatsby»;
import { MDXRenderer } from «
import React from «react»;
import { Box } from «
export default function PostPage ({ data }) {
const {
body,
frontmatter: { title },
} = data.mdx;
return (
<>
{title}
</>
) ;
}
export const query = graphql`
query POST_BY_SLUG ($slug: String) {
mdx (slug: { eq: $slug }) {
id
slug
body
frontmatter {
date
title
}
}
}
`;
Кода много, так что я разберу его. В основном это связано с запросом GraphQL:
query POST_BY_SLUG ($slug: String) {
mdx (slug: { eq: $slug }) {
id
slug
body
frontmatter {
date
title
}
}
}
Начало запроса принимает slugwith POST_BY_SLUG ($slug: String), а основной узел — mdx, поэтому я использую mdx.slugподобное имя файла {mdx.slug}.js.
Если я возьму этот запрос и вставлю его в свой проводник GraphiQL и нажму кнопку воспроизведения, я получу следующее:
{
«data»: {
«mdx»: null
},
«extensions»: {}
}
Это потому, что $slugв проводнике GraphiQL не определена переменная. Если вы посмотрите в нижнюю часть панели запроса, вы увидите раздел «Переменные запроса». Нажав на это, вы развернете его. Здесь мне нужно добавить переменную для slug. Я определю его в фигурных скобках путем к одному из файлов:
{
«slug»: «2021/03/08/
}
Запустив запрос еще раз, я получу все данные для этого файла. Я закомментировал bodyвывод для удобства чтения:
{
«data»: {
«mdx»: {
«id»: «105a5c78−
«slug»: «2021/01/08/
«body»: «function _extends ()...», // compiled MDX here
«frontmatter»: {
«date»: «
«title»: «Third Post!»
}
}
},
«extensions»: {}
}
То, что делает API маршрутизации файловой системы, передает отдельные пути к файлам в запрос страницы src/pages/{mdx.slug}.jsи возвращает данные на страницу из этого запроса в ({ data }) реквизите, передаваемом на страницу.
Вы можете заметить, что в этом файле я деструктурировал bodyиз возвращаемых данных, а затем titleиз из frontmatterв двухуровневой деструктуризации:
const {
body,
frontmatter: { title },
} = data.mdx;
Альтернативный способ сделать это:
const body = data.mdx.body;
const title = data.mdx.frontmatter.title;
Использование деструктуризации делает его намного менее подробным.
И последнее, на что следует обратить внимание, это MDXRendererупаковка bodyпоста. Это все, что включено в.mdxфайл после основного блока. Скомпилированный MDX из запроса GraphiQL, который был закомментирован, — это то, что нужно обернуть в MDXRenderer:
Я зафиксирую изменения сейчас:
git add.
git commit -m 'create file route API file’
Концепция корневой оболочки
Теперь, нажав на одну из ссылок на главной странице, я попаду на нужную.mdxстраницу, но она выглядит немного иначе, чем главная, верно?
Это потому, что еще нет макета, обертывающего его. Здесь я могу использовать API браузера Gatsby и использовать wrapPageElementфункцию для переноса всех элементов страницы. Также рекомендуется использовать ту же функцию в Gatsby SSR.
Чтобы избежать дублирования одного и того же кода в двух файлах, я создам третий файл с фактическим кодом, который я собираюсь использовать, и импортирую его в два gatsby-*упомянутых файла.
Сначала я создам необходимые файлы:
# create gatsby-browser.js and gatsby-ssr.js and root-wrapper.js
touch gatsby-browser.js gatsby-ssr.js root-wrapper.js
В корневом файле оболочки я буду использовать wrapPageElementфункцию:
// root-wrapper.js
import React from «react»;
import { Layout } from «. /src/components/layout»;
export const rootWrapper = ({ element }) => {
return
};
Затем в оба файла
import { rootWrapper } from «. /
export const wrapPageElement = rootWrapper;
Если есть
Время остановить и снова перезапустить сервер разработки, чтобы увидеть, как изменения вступили в силу!
Поскольку компонент макета используется здесь для переноса всех элементов страницы на сайт, больше нет необходимости держать его на индексной странице, поэтому я уберу его из src/pages/index.js:
import { graphql, Link as GatsbyLink } from «gatsby»;
import React from «react»;
import { Box, Heading, Link } from «
— import { Layout } from «.../components/layout»;
export default function IndexPage ({ data }) {
return (
<>
—
{data.allMdx.nodes.map (({ id, excerpt, frontmatter, slug }) => (
<Box
key={id}
as="article"
sx={{
mb: 4,
p: 3,
boxShadow: «0 10px 15px -3px rgba (0, 0, 0, 0.1)»,
border: «1px solid #d1d1d1»,
borderRadius: «15px»,
}}
>
<Link as={GatsbyLink} to={`/${slug}`}>
{frontmatter.date}
{excerpt}
))}
—
</>
) ;
};
// rest unchanged
Я зафиксирую изменения, прежде чем двигаться дальше:
git add.
git commit -m 'add root wrapper to Gatsby Browser and SSR’
404 Страница
Пора сделать эту страницу 404!
# create the 404.js page
touch src/pages/404.js
В src/pages/404.jsфайле я добавлю сообщение:
import React from «react»;
import { Box, Heading } from «
export default function NotFound () {
return (
<>
Page not found!
aria-label="crying face">
😢
It looks like that page doesn’t exist
</>
) ;
}
Теперь я могу напрямую перейти на страницу 404, чтобы проверить ее: http: //localhost:8000/404.
Обратите внимание, что при разработке с использованием gatsby developGatsby продолжит использовать страницу 404 по умолчанию, которая переопределяет вашу пользовательскую страницу 404.
Зафиксируйте это и переходите к следующей части:
git add.
git commit -m 'add 404 page’
Переключение темной темы
Темный режим — важная функция кодирования блогов. (Я говорю это наполовину в шутку, если вы не уверены!) Я собираюсь использовать хук цветового режима Theme UI useColorModeи сделать простое переключение между двумя режимами, которые я определил в themeобъекте ранее. Вот что добавляется src/components/header.js:
import { Link as GatsbyLink } from «gatsby»;
import React from «react»;
+ import { Box, Button, Heading, Link, useColorMode } from «
export const Header = ({ siteTitle, siteDescription }) => {
+ const [colorMode, setColorMode] = useColorMode () ;
return (
<Box
as="div"
sx={{
m: «0 auto»,
maxWidth: «640px»,
p: «1.45rem 1.0875rem»,
}}
>
{siteDescription}
+ <Button
+ onClick={ (e) => {
+ setColorMode (colorMode === «default»? «dark»: «default») ;
+ }}
+ >
+ {colorMode === «default»? «Dark»: «Light»}
+
) ;
};
Но это выглядит не очень хорошо, поэтому я оберну контейнер Flexкомпонентом Theme UI и сдвину кнопку вправо:
import { Link as GatsbyLink } from «gatsby»;
import React from «react»;
+import { Box, Button, Flex, Heading, Link, useColorMode } from «
export const Header = ({ siteTitle, siteDescription }) => {
const [colorMode, setColorMode] = useColorMode () ;
return (
<Box
as="div"
sx={{
m: «0 auto»,
maxWidth: «640px»,
p: «1.45rem 1.0875rem»,
}}
>
+
+
{siteDescription}
+
<Button
onClick={ (e) => {
setColorMode (colorMode === «default»? «dark»: «default») ;
}}
>
{colorMode === «default»? «Dark»: «Light»}
+
) ;
};
Git зафиксируйте перед переходом к следующему разделу:
git add.
git commit -m 'add theme toggle to header’
Блоки кода
Блоки кода на данный момент выглядят немного странно, поэтому я собираюсь добавить подсветку синтаксиса с помощью одного из множества удобных пакетов Theme UI. Я использую для этого Prism.
Мне нужно установить пакет и создать компонент в
# install the package
yarn add @
# create Theme UI components file
touch src/
В этом файле мне нужно определить, к чему я хочу применить стили Prism, то есть все preи codeтеги:
import Prism from «@
export default {
pre: (props) => props.children,
code: Prism,
};
После того, как это определено, мне также нужно определить в themeобъекте, какую тему Prism я хочу использовать:
// scr/
import { deep, swiss } from «@
+ import nightOwl from «@
const theme = {
...swiss,
colors: {
...swiss.colors,
modes: {
dark: {
...deep.colors,
},
},
},
styles: {
...swiss.styles,
+ code: {
+...nightOwl,
+ },
// remainder of the file unchanged
Требуется еще одна остановка и запуск сервера разработки, чтобы изменения вступили в силу!
Зафиксируйте изменения и перейдите к следующему разделу:
git add.
git commit -m 'add Prism package and update theme object’
Добавьте компоненты в MDX
Этот следующий бит является необязательным. Markdown JSX позволяет включать компоненты React (JSX) в Markdown. Чтобы продемонстрировать это, я собираюсь добавить RainbowTextкомпонент, который будет анимировать некоторые цвета в цикле анимации. Для анимации мне нужна дополнительная зависимость: keyframesfrom @emotion/react. сейчас установлю:
# create component file
touch src/components/
# install @emotion/react
yarn add @emotion/react
Это, вероятно, приведет к поломке сервера разработки, если он работает, поэтому я пока его остановлю.
В src/components/
import { keyframes } from «@emotion/react»;
import React from «react»;
import { Box } from «
export const RainbowText = ({ children }) => {
const rainbow = keyframes ({
«0%»: {
backgroundPosition: «0 0»,
},
«50%»: {
backgroundPosition: «400% 0»,
},
«100%»: {
backgroundPosition: «0 0»,
},
}) ;
return (
<Box
as="span"
variant="styles.p"
sx={{
fontWeight: «heading»,
cursor: «pointer»,
textDecoration: «underline»,
«: hover»: {
background:
«
animationDuration: «10s»,
animationTimingFunction: «
animationIterationCount: «infinite»,
animationName: `${rainbow}`,
WebkitBackgroundClip: «text»,
WebkitTextFillColor: «transparent»,
},
}}
>
{children}
) ;
};
Поскольку это необязательно, я не буду вдаваться в подробности того, что здесь происходит. Просто знайте, что это хороший
Создав этот компонент, я могу импортировать его в любой.mdxфайл, в котором хочу его использовать. В этом примере я добавляю его в content/2021/03/
---
title: Third Post!
date:
---
+ import { RainbowText } from «.../... /... /... /... /src/components/
This is my third post!
> with a block quote!
+
And a code block:
```js
const wheeeeee = true;
```
После повторного запуска сервера разработки я могу перейти к сообщению, в котором был добавлен этот компонент, и когда я наведу курсор на текст, заключенный в
Вы, вероятно, поморщитесь при таком импорте:... /... /... /. Снова и снова! Однако есть способ обойти это, используя концепцию корневой оболочки, которую я подробно описал ранее, и используя метод MDXProviderwhich will — гм! — предоставить MDX любые компоненты, которые вы ему передаете.
Возвращаясь к корневой обертке (
import { MDXProvider } from «@
import React from «react»;
import { Layout } from «. /src/components/layout»;
import { RainbowText } from «. /src/components/
const MDXComponents = {
RainbowText,
};
export const rootWrapper = ({ element }) => {
return (
) ;
};
Теперь я могу удалить импорт из.mdxфайла:
---
title: Third Post!
date:
---
— import { RainbowText } from «.../... /... /... /... /src/components/
This is my third post!
> with a block quote!
And a code block:
```js
const wheeeeee = true;
```
После остановки и перезапуска сервера разработки я могу перейти к этому сообщению и все еще видеть RainbowTextработу. Дополнительным преимуществом добавления компонентов непосредственно в документ MDXProviderявляется то, что нет необходимости импортировать компонент в.mdxдокумент, когда вы хотите его использовать. Он доступен через поставщика для всех документов MDX.
Я совершу это сейчас:
git add.
git commit -m 'add component for mdx’
Изображения уценки
Если я хочу добавить изображения в свои сообщения в блоге, я могу включить их в файлы MDX, примерно так:
---
title: Hello World — from mdx!
date:
---
My first post!!
## h2 Heading
![mdx logo] (. /
Some meaningful prose
### h3 Heading
Some other meaningful prose
Это. /
yarn add
Затем мне нужно настроить плагины в
const siteMetadata = {
title: `My Gatsby Blog`,
description: `This is my coding blog. `,
};
module.exports = {
siteMetadata,
plugins: [
`
+ `
+ {
+ resolve: `
+ options: {
+ gatsbyRemarkPlugins: [
+ {
+ resolve: `
+ options: {
+ maxWidth: 640,
+ },
+ },
+ ],
+ },
+ },
+ {
+ resolve: `
+ options: {
+ path: `${__dirname}/content/`,
+ },
+ },
{
resolve: `
options: {
path: `${__dirname}/content`,
name: `content`,
},
},
],
};
Дополнительным
Совершите это сейчас:
git add.
git commit -m 'add and configure images’
SEO
SEO очень важно, если я хочу, чтобы поисковые системы находили мой контент в Интернете, поэтому мне нужно добавить соответствующие метатеги в мой блог здесь. Это может быть довольно сложный процесс, определяющий все необходимые релевантные теги, поэтому, чтобы сэкономить время, я создал компонент React SEO для использования в Gatsby для создания всех необходимых метатегов.
Я перейду к yarn addкомпоненту вместе с зависимостями, необходимыми для его работы:
yarn add
Мне нужно добавить
module.exports = {
siteMetadata,
plugins: [
+ `
`
`
{
// rest unchanged
Тогда это случай использования SEOкомпонента на всем сайте, где мне нужны метатеги.
Компонент принимает довольно много свойств, многие из которых определены один раз на сайте, поэтому лучше всего добавить их в siteMetadataобъект. Тогда я смогу вытащить то, что мне нужно, с помощью useSiteMetadataкрючка.
Я собираюсь добавить еще несколько свойств к siteMetadataобъекту:
const siteMetadata = {
title: `My Gatsby Blog`,
description: `This is my coding blog. `,
+ lastBuildDate: new Date (Date.now ()).toISOString (),
+ siteUrl: `https: //
+ authorName: `Author McAuthorson`,
+ twitterUsername: `@authorOfPosts`,
+ siteLanguage: `
+ siteLocale: `en_gb`,
};
Если вы следуете инструкциям, вы можете изменить их по мере необходимости. На siteUrlданный момент это может быть фиктивный URL. Это поможет указать на любые изображения, необходимые для использования в протоколе Open Graph, и это изображение, которое вы видите, например, когда делитесь публикацией, которую вы сделали в Twitter, Facebook, LinkedIn и Reddit.
Теперь, когда эти дополнительные свойства находятся в siteMetadataобъекте, мне нужно иметь возможность запрашивать их. В настоящее время useSiteMetadataхук имеет только titleи description, поэтому я добавлю остальные:
// src/hooks/
import { graphql, useStaticQuery } from «gatsby»;
export const useSiteMetadata = () => {
const { site } = useStaticQuery (
graphql`
query SITE_METADATA_QUERY {
site {
siteMetadata {
title
description
+ lastBuildDate
+ siteUrl
+ authorName
+ twitterUsername
+ siteLanguage
+ siteLocale
}
}
}
`
) ;
return site.siteMetadata;
};
Я добавлю компонент SEO на все страницы.
import { graphql } from «gatsby»;
import { MDXRenderer } from «
import React from «react»;
+ import SEO from «
import { Box } from «
+ import { useSiteMetadata } from «.../hooks/
export default function PostPage ({ data }) {
const {
body,
+ slug,
+ excerpt,
+ frontmatter: { title, date },
} = data.mdx;
+ const {
+ title: siteTitle,
+ siteUrl,
+ siteLanguage,
+ siteLocale,
+ twitterUsername,
+ authorName,
+ } = useSiteMetadata () ;
return (
<>
+ <SEO
+ title={title}
+ titleTemplate={siteTitle}
+ description={excerpt}
+ pathname={`${siteUrl}${slug}`}
+ article={true}
+ siteLanguage={siteLanguage}
+ siteLocale={siteLocale}
+ twitterUsername={twitterUsername}
+ author={authorName}
+ publishedDate={date}
+ modifiedDate={new Date (Date.now ()).toISOString () }
+ />
{title}
</>
) ;
}
export const query = graphql`
query POST_BY_SLUG ($slug: String) {
mdx (slug: { eq: $slug }) {
id
slug
body
+ excerpt
frontmatter {
date
title
}
}
}
`;
siteUrl, slugи excerptнеобходимы для канонической ссылки (очень важно в SEO), а is excerptдля
Я использую siteMetadataхук, чтобы получить остальную информацию, необходимую компоненту. titleи titleTemplateиспользуются для создания того, что вы видите на вкладке браузера.
Логическое articleзначение предназначено для компонента, поэтому он может создать навигационный список в формате JSONLD. Остальные реквизиты помогают определить автора и дату публикации. 😅
Это было много. Надеюсь, что — то из этого имело смысл! В рамках этого поста я оставлю его там, но есть еще много чего, чтобы копаться в этой теме, и я имею в виду многое!
К счастью, src/pages/index.jsстраница немного проще!
import { graphql, Link as GatsbyLink } from «gatsby»;
import React from «react»;
+ import SEO from «
import { Box, Heading, Link } from «
+ import { useSiteMetadata } from «.../hooks/
export default function IndexPage ({ data }) {
+ const {
+ title,
+ description,
+ siteUrl,
+ siteLanguage,
+ siteLocale,
+ twitterUsername,
+ } = useSiteMetadata () ;
return (
<>
+ <SEO
+ title={`Home`}
+ titleTemplate={title}
+ description={description}
+ pathname={siteUrl}
+ siteLanguage={siteLanguage}
+ siteLocale={siteLocale}
+ twitterUsername={twitterUsername}
+ />
{data.allMdx.nodes.map (({ id, excerpt, frontmatter, slug }) => (
// rest of component unchanged
Я намеренно опустил изображение из обоих примеров. Если вы заинтересованы в создании собственных изображений Open Graph для использования в этом компоненте, ознакомьтесь с сообщением «Открыть изображения Graph с помощью Gatsby и Vercel «, чтобы узнать, как это сделать с помощью бессерверной функции. 🔥
Теперь я могу создать сайт (почти готовый к производству), и как только он будет создан, я могу проверить исходный код страницы на наличие метатегов:
# build the site first
yarn build
# use gatsby serve to run built site locally
yarn serve
После завершения сборки я могу использовать yarn serveсозданный сайт для локального обслуживания на localhost:9000. В браузере я могу просмотреть исходный код страницы с помощью сочетания клавиш Ctrl+ u. Отсюда я могу проверить canonicalметатег, который будет фиктивным
Хорошо! Зафиксируйте это в Git и двигайтесь дальше:
git add.
git commit -m 'add SEO component: sweat_smile:'
Отправьте это на GitHub
Вам может быть интересно, почему я делаю коммиты Git в конце каждого раздела. Это потому, что сейчас я собираюсь отправить проект на GitHub.
Я войду в свою учетную запись GitHub, выберу +значок «плюс» рядом с моим аватаром в правом верхнем углу и выберу «Новый репозиторий «.
В поле «Имя репозитория «я добавлю имя проекта,
Следующий экран дает мне команды терминала, которые мне нужны, чтобы отправить мой локальный проект на GitHub:
git remote add origin https://github.com/spences10/my-gatsby-blog
git branch -M main
git push -u origin main
После того, как вы поместите все это в терминал и нажмете Enter, обновите страницу GitHub, чтобы увидеть новый проект!
Развертывать
Пора выложить этого малыша в Сеть! Есть много способов сделать это. Поскольку Gatsby использует плоскую файловую структуру, вы можете разместить сайт Gatsby на любом файловом сервере с доступом в Интернет.
Есть много сервисов, которые предлагают хостинг на CDN, многие из них бесплатно! Такие сервисы, как Netlify, Vercel и Render, позволят вам разместить созданный вами сайт в их CDN через интерфейс командной строки, интеграцию с GitHub или, в случае с Netlify, прямое перетаскивание!
Версель
Для развертывания с помощью Vercel вам потребуется учетная запись GitHub, GitLab или Bitbucket для аутентификации. Затем вам будет предложено установить Vercel CLI:
yarn global add vercel
Он у меня уже установлен, так что теперь нужно запустить команду CLI:
vc
Затем мне будет предложено настроить и развернуть новый проект. Я собираюсь ответить по умолчанию на все вопросы Enter:
Set up and deploy «~/repos/
Which scope do you want to deploy to?
Link to existing project? [y/N]
What’s your project’s name? (
In which directory is your code located?. /
> Upload [====================] 99% 0.
— Build Command: `npm run build` or `gatsby build`
— Output Directory: public
— Development Command: gatsby develop —port $PORT
? Want to override the settings? [y/N]
Вот и все. Затем мне дается
На панели управления Vercel я могу настроить домен, а также купить его у Vercel, если захочу. Я лично использую Namecheap.com, но это вариант.
Нетлайф
Развертывание с помощью Netlify через интерфейс командной строки почти такое же, как и с Vercel, но я собираюсь создать создание с помощью перетаскивания.
Для аутентификации мне понадобится одна из учетных записей GitHub, GitLab, Bitbucket или электронной почты. После аутентификации и входа в систему я могу выбрать «Сайты «в строке меню, а затем появится область перетаскивания. Хотите развернуть новый сайт без подключения к Git? Перетащите сюда выходную папку вашего сайта. Я собираюсь перейти в проводнике к корню моего проекта и перетащить publicпапку в область перетаскивания.
Netlify создаст файлы и развернет их по сгенерированному
Оказывать
Render не имеет CLI или возможности перетаскивания и вместо этого использует интеграцию с GitHub. Для аутентификации мне понадобится учетная запись GitHub, GitLab или Google. После аутентификации и входа в систему я оказываюсь в разделе услуг. Отсюда я могу выбрать «Новый статический сайт «, а затем ввести свой
На следующей странице я дам ему следующие настройки:
Имя:
Ветвь: значение по умолчанию
Команда сборки: yarn build
Опубликовать каталог:. /public
Затем нажмите «Создать статический сайт».
Подождите, пока Render сделает свое дело, а затем щелкните ссылку под названием проекта, чтобы увидеть сайт вживую.
Render также имеет возможность установить собственный домен для сайта!
Дополнительные плагины Гэтсби
Существует множество других плагинов Gatsby для добавления дополнительных функций. Я оставлю это вам, если вы хотите добавить больше. Например:
Вы хотите встроить видео YouTube, твиты, прогоны Strava, CoodePens и Codesandbox? Проверьте
Вы используете консоль поиска Google/Bing? Затем вам нужно создать карту сайта с помощью
Вы хотите, чтобы ваш сайт был доступен в автономном режиме в качестве PWA? Добавьте
Хотите, чтобы на вкладке браузера вашего сайта была фавиконка? Проверьте
Аналитика
Если вам интересно узнать, насколько популярен ваш сайт, есть варианты аналитики. Некоторое время назад я перестал использовать Google Analytics в своих проектах и теперь предпочитаю альтернативы, более ориентированные на конфиденциальность. Я рекомендую Fathom Analytics. (У меня есть партнерская ссылка, если вы хотите получить скидку 10 долларов на подписку в первый месяц.)
Другой альтернативой является Plausible, о котором я также слышал хорошие отзывы.
Чтобы внедрить Fathom Analytics на сайте Gatsby, мне нужно добавить дополнительный тег скрипта в заголовок моего сайта. Что это обозначает? Что ж, сначала мне нужно создать сайт на панели инструментов Fathom, затем перейти на https://app.usefathom.com/#/settings/sites, прокрутить список до конца и добавить мой новый сайт (
Вот разница
import { MDXProvider } from «@
import React from «react»;
+import { Helmet } from «
import Layout from «. /src/components/layout»;
import RainbowText from «. /src/components/
const MDXComponents = {
RainbowText,
};
export const wrapPageElement = ({ element }) => {
return (
+ <>
+
+
+
+
+ </>
) ;
};
Сворачивать!
Это от меня. Большое спасибо, что дошли до конца. 🙏
Я надеюсь, что вы получили то, что вам нужно, из этого довольно подробного руководства по настройке проекта Gatsby с нуля!