- Введение в SEO
- Что такое SEO?
- Почему SEO важно?
- Как работает SEO?
- Лучшие практики SEO
- Создание приложения для блога
- Настройте новое приложение React
- Разумность настроек
- Подключение Sanity к нашему приложению React
- Создайте компоненты React
- Оптимизация приложения React для SEO с помощью Sanity
- Оптимизация изображений
- Метаданные
- Что еще мы можем сделать для улучшения SEO?
- Рубрики
- *Добавление карты сайта*
- Рендеринг на стороне сервера и генерация статических сайтов
- Заключение
Введение в SEO
Что такое SEO?
Поисковая оптимизация (SEO) — это практика увеличения количества и качества трафика на ваш сайт через органические результаты поисковых систем. Это достигается путем повышения рейтинга вашего сайта в поисковых системах. Чем выше рейтинг вашего сайта, тем больше вероятность того, что он окажется на первой странице результатов поиска и его посетит больше людей.
Почему SEO важно?
68% пользователей начинают знакомство с интернетом с поисковой системы, а 75% людей никогда не просматривают дальше первой страницы результатов поисковой системы. Это означает, что без SEO ваше веб-приложение может упустить потенциальный рост, успех и будет скрыто от глаз.
Как работает SEO?
Процесс SEO можно разделить на 3 этапа:
- Ползание: Краулеры можно представить как «жителей» поисковой системы, которые посещают веб-страницы. Затем они передают поисковой системе информацию об этих веб-страницах, которая заносится в базу данных, называемую индексом, для последующего поиска.
- Индексирование: Когда люди выполняют поиск в Google, результаты основываются не только на том, какие слова наиболее часто встречаются в вашем контенте, но и на том, какой контент наиболее релевантен для пользователя. Это означает, что поисковым системам, таким как Google, важны метаданные, такие как заголовки и метаописания, когда они ранжируют вашу веб-страницу в результатах поиска по определенному ключевому слову.
- Ранжирование: После того как поисковая система создала индекс вашего сайта, она пытается ранжировать все проиндексированные страницы, которые соответствуют поисковому запросу пользователя. Цель поисковых систем — предоставить пользователю наилучшие результаты, соответствующие его запросу.
Лучшие практики SEO
Теперь, когда мы знаем, как работает SEO, давайте посмотрим, каковы лучшие практики для этого.
- Будьте хорошим гражданином и создайте полезный сайт
Прежде чем мы продолжим, это, пожалуй, самый важный совет: пишите полезный контент! Не имеет значения, сколько усилий вы вложили в оптимизацию вашего React-приложения, если никто этого не увидит. Если вы публикуете контент, который интересен людям, то другие пользователи Интернета, скорее всего, будут ссылаться на ваш сайт и делиться им со своими друзьями, что еще больше увеличивает вероятность того, что он будет виден в результатах поисковых систем.
- Используйте описательные заголовки и метаописания.
Это означает, что вместо заголовков типа «Главная» вам следует писать что-то более описательное. Это связано с тем, что боты поисковых систем недостаточно умны, чтобы понять, о чем ваша страница, на основании того, что разные слова находятся рядом друг с другом.
- Создавайте уникальный контент для каждой страницы вашего сайта
Наличие дублирующегося контента на вашем сайте плохо сказывается на SEO. Например, если у вас есть несколько страниц с одинаковым содержанием, поисковые системы не смогут правильно ранжировать каждую страницу.
- Оптимизируйте скорость страницы
Поисковые системы, такие как Google, заботятся о скорости работы страниц.
Важно помнить, что GoogleBot, который просматривает веб-страницы в поисках контента, имеет очень низкую пропускную способность. Это означает, что у него не должно возникнуть проблем с просмотром страниц вашего сайта, если они не загружаются долго.
Время загрузки страницы может существенно повлиять на количество посетителей. Страницы, которые загружаются менее 2 секунд, имеют средний показатель отказов 9%, а страницы, загружающиеся в течение 5 секунд, — 38%.
- Оптимизируйте изображения
Все мы знаем, что изображения — это отличный способ добавить больше разнообразия и креативности на наши страницы, но есть кое-что, что вы должны делать при их использовании. Оптимизация изображений приведет не только к увеличению скорости проползания бота Google по вашему контенту; она также улучшит скорость загрузки для пользователей!
- Включите разнообразные внутренние ссылки
Внутренние ссылки — это отличный способ сделать ваш сайт более доступным как для людей, так и для поисковых систем. Они дают Google дополнительные сигналы о том, что контент на этих страницах релевантен, что поможет ранжировать их выше в результатах; в то же время они облегчают работу с сайтом благодаря всей своей дополнительной информации!
Создание приложения для блога
В этом разделе мы создадим новое приложение react.js под названием sanity-blog
, которое подключится к Sanity.
Готовый проект можно найти на этом репозитории Github! Вы также можете проверить живую версию этого приложения
Настройте новое приложение React
⚠️ Прежде чем начать, убедитесь, что Node.js установлен в вашем окружении. Чтобы узнать больше, посетите веб-сайт Node.
Откройте свой Shell и выполните следующую команду.
npx create-react-app sanity-blog
Затем выполните следующую команду, чтобы изменить каталог на созданный вами проект
cd sanity-blog
Чтобы убедиться, что все работает нормально, выполните следующую команду в терминале. Ваше приложение React должно открыться в браузере в формате http://localhost:3000.
npm start
Теперь давайте установим несколько зависимостей, которые нам понадобятся. Выполните следующую команду в корне проекта:
npm install @portabletext/reactimport @portabletext/react @sanity/image-url react-router-dom
npm install -D tailwindcss postcss autoprefixer @tailwindcss/typography
npx tailwindcss init
Далее, давайте настроим TailwindCSS для стилизации нашего фронт-энда. Перейдите в src/index.css
и замените содержимое файла на
@tailwind base;
@tailwind components;
@tailwind utilities;
Теперь перейдите к файлу ./tailwind.config.js
и замените его на следующий
module.exports = {
content: ["./src/**/*.{html,js}"],
theme: {
extend: {},
},
plugins: [require("@tailwindcss/typography")],
}
Разумность настроек
Наша цель состоит в следующем:
- Создать новый проект Sanity для нашего блога
- Настроить стандартную схему блога для добавления SEO-полей
- Добавить немного контента
Давайте начнем с установки Sanity CLI в нашем локальном окружении.
⚠️ Перед выполнением этих команд убедитесь, что вы находитесь в директории sanity-blog
.
npm i -g @sanity/cli
После успешной установки Sanity CLI мы можем активировать инициализацию Sanity в нашем проекте React.
sanity init
Теперь вы видите пару вопросов в командной строке. Ответьте на них следующим образом:
? Select project to use **Create new project**
? Your project name: **Sanity Blog**
? Use the default dataset configuration? **Yes**
? Project output path: **[Choose default path]**
? Select project template **Blog (schema)**
После завершения работы вы должны увидеть новую папку sanityblog
под sanity-blog
перейдите туда и выполните следующую команду, чтобы запустить Sanity Studio.
cd sanityblog
sanity start
После выполнения этих команд вы должны увидеть следующее
sanity start
✔ Checking configuration files...
⠧ Compiling...webpack built 2f98f0cdc718c8744e79 in 11987ms
✔ Compiling...
Content Studio successfully compiled! Go to http://localhost:3333
Перейдите по адресу http://localhost:3333, чтобы открыть Sanity Studio.
Теперь давайте добавим несколько новых полей в нашу модель поста, чтобы она была оптимизирована для поисковых систем.
В редакторе кода перейдите в папку sanityblog
→ schemas
и откройте файл post.js
.
Расположение post.js в проекте
Замените содержимое этого файла на следующее:
export default {
name: 'post',
title: 'Post',
type: 'document',
groups: [
{
name: 'seo',
title: 'SEO',
},
],
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
},
{
name: 'seoTitle',
title: 'SEO Title',
group: 'seo',
validation: Rule => [
Rule.required().min(40).max(50).error('SEO titles between 40 and 50 characters with commonly searched words have the best click-through-rates'),
],
type: 'string',
},
{
name: 'seoDescription',
title: 'SEO Description',
group: 'seo',
validation: Rule => [
Rule.required().min(50).max(156).error('Good SEO descriptions utilize keywords, summarize the story and are between 140-156 characters long.'),
],
type: 'text',
},
{
name: "ogTitle",
title: "Open Graph Title",
group: 'seo',
validation: Rule => [
Rule.required().min(40).max(50).error('SEO titles between 40 and 50 characters with commonly searched words have the best click-through-rates'),
],
type: "string",
},
{
name: "ogDescription",
title: "Open Graph Description",
group: 'seo',
validation: Rule => [
Rule.required().min(50).max(156).error('Good SEO descriptions utilize keywords, summarize the story and are between 140-156 characters long.'),
],
type: "text",
},
{
name: "ogImage",
title: "Open Graph Image",
group: 'seo',
type: "image",
},
{
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'title',
maxLength: 96,
},
},
{
name: 'author',
title: 'Author',
type: 'reference',
to: {type: 'author'},
},
{
name: 'mainImage',
title: 'Main image',
type: 'image',
options: {
hotspot: true,
},
},
{
name: 'categories',
title: 'Categories',
type: 'array',
of: [{type: 'reference', to: {type: 'category'}}],
},
{
name: 'publishedAt',
title: 'Published at',
type: 'datetime',
},
{
name: 'body',
title: 'Body',
type: 'blockContent',
},
],
preview: {
select: {
title: 'title',
author: 'author.name',
media: 'mainImage',
},
prepare(selection) {
const {author} = selection
return Object.assign({}, selection, {
subtitle: author && `by ${author}`,
})
},
},
}
Мы добавили 2 важных изменения в схему по умолчанию:
- Мы добавили новую группу под названием SEO, которая будет отображаться в виде вкладки на странице Post. Эта группа содержит все необходимые поля для SEO.
- У нас есть целый набор новых полей для meta title, description, open graph title, description и image. Все эти поля проверяются, чтобы они содержали нужную длину для достижения наилучшего результата в SEO.
Наконец, давайте создадим образец записи в блоге в Sanity Studio.
Подключение Sanity к нашему приложению React
Чтобы подключить Sanity к приложению React, давайте сначала установим Sanity Client. Перейдите в корень проекта и выполните следующую команду
npm install @sanity/client
Далее нам нужно создать экземпляр Sanity Client и установить его в нашем проекте. Для этого в папке src
создайте новый файл под названием client.js
Затем внутри этого файла добавьте следующий код:
import sanityClient from "@sanity/client";
export default sanityClient({
apiVersion: "2022-04-06",
projectId: "Your Project ID Here",
dataset: "production",
useCdn: true,
});
💡 Чтобы найти projectId
, вы можете перейти в sanityblog/sanity.json
и найти projectId
.
Наконец, давайте добавим URL приложения react в CORS-источник проекта Sanity. В командной строке перейдите в папку sanityblog
и выполните следующее и ответьте «да» на вопрос.
sanity cors add http://localhost:3000
Создайте компоненты React
В папке src
создайте новую папку components
, добавьте туда AllPosts.js
и OnePost.js
.
Файл AllPosts.js
должен содержать
import React, { useState, useEffect } from 'react';
import sanityClient from "../client"
import imageUrlBuilder from "@sanity/image-url";
const builder = imageUrlBuilder(sanityClient);
function urlFor(source) {
return builder.image(source);
}
export default function AllPosts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
// This is GROQ syntax for our query, to learn more about it, check out the docs at https://www.sanity.io/docs/groq
sanityClient.fetch(
`*[_type == "post"] | order(publishedAt desc) {
title,
publishedAt,
slug,
body,
"authorName": author->name,
"authorImage": author->image,
mainImage{
asset->{
_id,
url
}
},
categories {
title,
slug,
},
}`
)
.then(posts => {
setPosts(posts);
setLoading(false);
})
}, []);
return loading ? (
<div>Loading...</div>
) : (
<div className="relative bg-gray-50 pt-16 pb-20 px-4 sm:px-6 lg:pt-24 lg:pb-28 lg:px-8">
<div className="absolute inset-0">
<div className="bg-white h-1/3 sm:h-2/3" />
</div>
<div className="relative max-w-7xl mx-auto">
<div className="text-center">
<h2 className="text-3xl tracking-tight font-extrabold text-gray-900 sm:text-4xl">From the blog</h2>
<p className="mt-3 max-w-2xl mx-auto text-xl text-gray-500 sm:mt-4">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Ipsa libero labore natus atque, ducimus sed.
</p>
</div>
<div className="mt-12 max-w-lg mx-auto grid gap-5 lg:grid-cols-3 lg:max-w-none">
{posts.map((post) => (
<div key={post.slug.current} className="flex flex-col rounded-lg shadow-lg overflow-hidden">
<a href={`/${post.slug.current}` } className="block mt-2">
<div className="flex-shrink-0">
<img className="w-full object-cover" src={urlFor(post.mainImage).width(100).url()} alt={post.title} />
</div>
<div className="flex-1 bg-white p-6 flex flex-col justify-between">
<div className="flex-1">
<p className="text-xl font-semibold text-gray-900">{post.title}</p>
</div>
<div className="mt-6 flex items-center">
<div className="flex-shrink-0">
<span className="sr-only">{post.authorName}</span>
<img className="h-10 w-10 rounded-full" src={urlFor(post.authorImage).width(100).url()} alt={post.authorName} />
</div>
<div className="ml-3">
<p className="text-sm font-medium text-gray-900">
{post.authorName}
</p>
<div className="flex space-x-1 text-sm text-gray-500">
<time dateTime={post.publishedAt}>{post.publishedAt}</time>
<span aria-hidden="true">·</span>
</div>
</div>
</div>
</div>
</a>
</div>
))}
</div>
</div>
</div>
);
}
Файл OnePost.js
должен содержать
import React, {useState, useEffect} from 'react';
import sanityClient from '../client';
import imageUrlBuilder from '@sanity/image-url';
import { PortableText } from '@portabletext/react'
const builder = imageUrlBuilder(sanityClient);
function urlFor(source) {
return builder.image(source);
}
export default function OnePost(){
const [post, setPost] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
sanityClient.fetch(
`*[_type == "post" && slug.current == $slug][0]{
title,
publishedAt,
slug,
body,
"authorName": author->name,
"authorImage": author->image,
mainImage{
asset->{
_id,
url
}
},
categories {
title,
slug,
},
}`,
{slug: window.location.pathname.split('/')[1]}
)
.then(post => {
setPost(post);
setLoading(false);
})
}, []);
return loading ? (
<div>Loading...</div>
) : (
<div className="relative py-16 bg-white overflow-hidden">
<div className="hidden lg:block lg:absolute lg:inset-y-0 lg:h-full lg:w-full">
<div className="relative h-full text-lg max-w-prose mx-auto" aria-hidden="true">
<svg
className="absolute top-12 left-full transform translate-x-32"
width={404}
height={384}
fill="none"
viewBox="0 0 404 384"
>
<defs>
<pattern
id="74b3fd99-0a6f-4271-bef2-e80eeafdf357"
x={0}
y={0}
width={20}
height={20}
patternUnits="userSpaceOnUse"
>
<rect x={0} y={0} width={4} height={4} className="text-gray-200" fill="currentColor" />
</pattern>
</defs>
<rect width={404} height={384} fill="url(#74b3fd99-0a6f-4271-bef2-e80eeafdf357)" />
</svg>
<svg
className="absolute top-1/2 right-full transform -translate-y-1/2 -translate-x-32"
width={404}
height={384}
fill="none"
viewBox="0 0 404 384"
>
<defs>
<pattern
id="f210dbf6-a58d-4871-961e-36d5016a0f49"
x={0}
y={0}
width={20}
height={20}
patternUnits="userSpaceOnUse"
>
<rect x={0} y={0} width={4} height={4} className="text-gray-200" fill="currentColor" />
</pattern>
</defs>
<rect width={404} height={384} fill="url(#f210dbf6-a58d-4871-961e-36d5016a0f49)" />
</svg>
<svg
className="absolute bottom-12 left-full transform translate-x-32"
width={404}
height={384}
fill="none"
viewBox="0 0 404 384"
>
<defs>
<pattern
id="d3eb07ae-5182-43e6-857d-35c643af9034"
x={0}
y={0}
width={20}
height={20}
patternUnits="userSpaceOnUse"
>
<rect x={0} y={0} width={4} height={4} className="text-gray-200" fill="currentColor" />
</pattern>
</defs>
<rect width={404} height={384} fill="url(#d3eb07ae-5182-43e6-857d-35c643af9034)" />
</svg>
</div>
</div>
<div className="relative px-4 sm:px-6 lg:px-8">
<div className="text-lg max-w-prose mx-auto">
<h1>
<span className="mt-2 block text-3xl text-center leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl">
{post.title}
</span>
</h1>
<hr className="mt-8 border-b-2 w-24 mx-auto border-gray-200" />
<figure>
<img
className="w-full h-72 rounded-lg mt-12"
src={urlFor(post.mainImage).width(100).url()}
alt={post.title}
/>
<figcaption className='text-gray-700 text-center pt-2'>Sagittis scelerisque nulla cursus in enim consectetur quam.</figcaption>
</figure>
<div className="mt-8 text-xl text-gray-500 leading-8 prose prose-indigo">
<PortableText value={post.body} />
</div>
</div>
</div>
</div>
)
}
Наконец, замените содержимое src/App.js
на следующее
import React from 'react';
import AllPosts from './components/AllPosts';
import OnePost from './components/OnePost';
import { BrowserRouter, Route, Routes } from "react-router-dom";
import './App.css';
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<AllPosts />} />
<Route path=":slug" element={<OnePost />} />
</Routes>
</BrowserRouter>
)
}
Оптимизация приложения React для SEO с помощью Sanity
В этом разделе мы узнаем, как создать seo-friendly React-приложение с помощью практических приемов, используя возможности Sanity.
Оптимизация изображений
Как мы уже говорили ранее, производительность сайта имеет решающее значение для SEO. Изображения — это активы, которые могут навредить производительности сайта, если они имеют неправильный формат или размер. Процесс оптимизации сайта может быть утомительным и отнимать много времени. Очень важно иметь автоматический способ, чтобы не тратить часы на оптимизацию изображений.
Sanity имеет глобальную сеть доставки контента (CDN) для обслуживания активов. Когда мы загружаем изображения для блога, доступ к ним можно получить по адресу cdn.sanity.io.
Когда пользователь запрашивает ресурс, он обрабатывается внутренними системами Sanity, а затем кэшируется на серверах, расположенных рядом с конечными пользователями. Последующие запросы обслуживаются из кэша, что позволяет быстро отвечать на них высококачественным контентом без необходимости замедления работы или загрузки дополнительных ресурсов для каждого отдельного запроса.
Рассмотрим пример. Для примера содержимого блога я загрузил https://unsplash.com/photos/qWwpHwip31M
Размер файла составляет 985 КБ в формате JPEG с размерами 5184 × 3456. Я зашел в Sanity Studio и загрузил его как изображение для блога. В компоненте OnePost.js
мы имеем следующее
<img
className="w-full h-72 rounded-lg mt-12"
src={urlFor(post.mainImage).width(100).url()}
alt={post.title}
/>
Как вы видите, в src мы определяем width
100. Это помогает нам уменьшить размер файла и габариты.
Вы можете посмотреть файл в CDN здесь https://cdn.sanity.io/images/a4zwcx9l/production/ffa097961aeffbde70f97ab81ece18dc80705907-5184×3456.jpg?w=100.
Метаданные
Заголовок
Тег title — это важный SEO-элемент, который пользователи видят, когда переходят на ваш сайт из результатов поиска. Он также является одним из основных факторов, используемых Google при определении того, о чем страница, поэтому использование здесь релевантных ключевых слов поможет вам занять более высокое место в SERPs (страницах результатов поисковых систем).
Чтобы иметь возможность добавить заголовок и остальные метатеги, давайте сначала установим React Helmet
В корне проекта выполните в терминале следующую команду
npm install --save react-helmet
Далее, давайте добавим Meta title в Sanity Studio. В студии нажмите на Post и выберите блог, для которого вы хотите добавить заголовок. На вкладке SEO вы можете заполнить SEO Title
.
Наконец, импортируем Helmet
в верхней части файла и добавим Meta title в компонент OnePost.js
.
import React, {useState, useEffect} from 'react';
import sanityClient from '../client';
import imageUrlBuilder from '@sanity/image-url';
import { PortableText } from '@portabletext/react'
import { Helmet } from 'react-helmet';
export default function OnePost(){
.
.
.
return loading ? (
<div>Loading...</div>
) : (
<div>
<Helmet>
<title>{post.seoTitle}</title>
</Helmet>
.
.
.
</div>
)
}
Описание
Метатег description — это часто игнорируемый SEO-элемент, но он может оказать значительное влияние на количество кликов. Согласно Google, эта часть страницы не учитывается при ранжировании страниц, однако если вы используете здесь ключевые слова, они будут отображаться жирным шрифтом в любом поисковом запросе, включающем их — поэтому убедитесь, что эти слова релевантны!
Далее, давайте добавим Meta Description в Sanity Studio. В студии нажмите на Post и выберите блог, для которого вы хотите добавить описание. На вкладке SEO вы можете заполнить SEO Description.
Наконец, давайте добавим Мета-описание в компонент OnePost.js
.
.
.
.
import { Helmet } from 'react-helmet';
export default function OnePost(){
.
.
.
<div>
<Helmet>
<title>{post.seoTitle}</title>
<meta name="description" content={post.seoDescription} />
</Helmet>
.
.
.
</div>
)
}
Open Graph
известный как og — это способ предоставления мета информации в социальные сети, такие как Facebook и Twitter. Он используется для описания веб-страницы и указания этим платформам, какой контент содержит страница, например, изображения.
Эти теги Open Graph не связаны с поисковой оптимизацией (SEO), но, тем не менее, имеют преимущества для распространения вашего контента в социальных сетях или приложениях для обмена сообщениями, таких как WhatsApp и Telegram.
Далее, давайте добавим информацию Open Graph в Sanity Studio. В студии нажмите на Post и выберите блог, для которого вы хотите добавить информацию og. На вкладке SEO вы можете заполнить Open Graph Title, Description и Image.
Наконец, давайте добавим описание Open Graph в компонент OnePost.js
.
.
.
.
import { Helmet } from 'react-helmet';
export default function OnePost(){
.
.
.
<div>
<Helmet>
<title>{post.seoTitle}</title>
<meta name="description" content={post.seoDescription} />
<meta property='og:title' content={post.ogTitle} />
<meta property='og:description' content={post.ogDescription} />
<meta property='og:image' content={urlFor(post.ogImage).width(300).url()} />
</Helmet>
.
.
.
</div>
)
}
Что еще мы можем сделать для улучшения SEO?
Рубрики
Заголовки используются для организации содержимого страницы и помогают пользователям понять ее структуру. Они также позволяют поисковым системам, таким как Google, Bing или Yahoo! (те, кто действительно читает эти материалы), понять, какие части вашего сайта им следует отнести к более важным для удобства посетителей.
Существует 6 различных заголовков, от H1 до H6. Заголовок H1 должен представлять то, чему посвящена ваша веб-страница — он должен быть похож на тег title.
Заголовки используются для упорядочивания содержимого страницы и помогают пользователям понять ее структуру. Они также позволяют поисковым системам, таким как Google, Bing или Yahoo! (те, кто читает эти материалы), понять, какие части вашего сайта должны быть более важными для удобства посетителей.
Существует 6 различных заголовков, от H1 до H6. Заголовок H1 должен представлять то, чему посвящена ваша веб-страница — он должен быть похож на тег title.
В компоненте src/components/OnePost.js
мы имеем следующее
<h1>
<span className="mt-2 block text-3xl text-center leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl">
{post.title}
</span>
</h1>
*Добавление карты сайта*
Хотя добавление карты сайта на ваш сайт уже не так необходимо, как раньше, это все еще хорошая идея. Google может без труда просмотреть ваш сайт, но добавление карты сайта по-прежнему полезно для обеспечения того, чтобы весь ваш контент был виден.
Существуют такие плагины, как react-router-sitemap-generator, которые могут сделать это за вас.
Рендеринг на стороне сервера и генерация статических сайтов
С помощью React мы можем создавать одностраничные приложения. Одностраничное приложение — это приложение, которое загружает одну HTML-страницу и необходимые активы, такие как файлы Javascript и CSS, которые требуются для работы приложения. При любом взаимодействии с приложением загружается только необходимый контент и не требуется перезагрузка страницы. SPA имеет лучшую производительность по сравнению с традиционными веб-приложениями, но это может быть сложным для SEO, потому что когда поисковая система просматривает приложение, она находит пустой контейнер страницы, который не имеет значимого содержимого для бота, и он должен ждать, пока Javascript загрузится, чтобы отобразить содержимое страницы. Это может привести к задержке индексации содержимого страницы или к тому, что поисковая машина может пропустить важный контент для индексации.
Одним из лучших вариантов решения этой проблемы является использование технологии предварительного рендеринга для создания HTML-файлов заранее, вместо того чтобы все это делалось Javascript на стороне клиента. Далее мы рассмотрим 2 варианта пре-рендеринга, которые есть у разработчиков react для улучшения react SEO.
Рендеринг на стороне сервера (SSR)
Как мы уже говорили, React-сайты обычно создаются в браузере на стороне клиента. Идея SSR, в отличие от рендеринга на стороне клиента, заключается в том, чтобы рендерить начальную HTML-страницу на сервере вместо того, чтобы ждать загрузки Javascript в браузере. Таким образом, сервер обрабатывает начальный рендеринг приложения. Сервер импортирует корневой компонент приложения React, преобразует его в HTML-файл и отправляет этот преобразованный HTML на клиент.
Самостоятельная реализация SSR является трудоемким и сложным процессом, поэтому настоятельно рекомендуется обратить внимание на такие javascript-фреймворки, как next.js, которые предназначены для SSR.
Генерация статических сайтов (SSG)
SSG, как и SSR, генерирует статическую HTML-страницу заранее, а не оставляет это на усмотрение браузера клиента. Но разница между SSG и SSR в том, что при статической генерации сайта мы генерируем HTML файлы во время сборки, в отличие от рендеринга на стороне сервера, который генерирует HTML при каждом запросе. Я также рекомендую взглянуть на next.js для создания SSG React-приложения.
Заключение
SEO является важной частью обеспечения появления вашего сайта/приложения на страницах результатов поиска.
Мы увидели, что Sanity обладает множеством функций, которые помогают нам создавать высокопроизводительные React-приложения и предоставляют возможность любому пользователю добавлять важные SEO-элементы в контент для лучшей видимости и ранжирования в поисковых системах.