От автора: мы часто рекомендуем использование одностраничных приложений. Мы продолжим делать это, потому что они великолепны. Я имею в виду, они быстрые, они предлагают невероятный UX и у них крутой вид. Тем не менее, мы также всегда обращаем внимание на вещи, с которыми нужно быть осторожными, когда речь идет о работе с SPA — такие важные вещи, как поисковая оптимизация (SEO).
Нельзя сказать, что с SPA вы не можете получить отличные результаты в SEO — можете. Вам просто нужно сделать все правильно, работаете ли вы с Angular, Vue или React. В этой статье я расскажу о Next.js и о том, как он может помочь вам создать SEO-оптимизированные React SPA. Все это в несколько простых шагов:
Создание проекта Next.js
Генерация компонентов
SEO-оптимизация приложения Next.js
Сделать пререндеринг сканируемым
Создать карту сайта
Добавить метаданные
Разместить SPA на Netlify
К концу этого руководства ваш проект должен быть застрахован от того, чтобы впасть в немилость у нашего Господа Всемогущего ака Google.
Что такое Next.js?
В двух словах, Next.js — это облегченная среда для статических и серверных приложений React.
Не путайте его с Nuxt, который является основой для универсальных приложений Vue.js — на самом деле он был вдохновлен Next. У них очень похожие цели.
К настоящему времени вы, по крайней мере, должны были уже слышать о React, но для ясности мы определим его как библиотеку JavaScript на основе компонентов для создания интерфейсов.
А что мы подразумеваем под универсальным JavaScript? Ну, это относится к приложениям, где JavaScript работает как на стороне клиента, так и на стороне сервера. Это отлично подходит как для производительности при загрузке первой страницы, так и для целей SEO, как мы увидим ниже.
Next берет все хорошее от React и делает запуск приложения еще проще. Это достигается благодаря нескольким встроенным конфигурациям — автоматическое разделение кода, маршрутизация файловой системы, рендеринг на стороне сервера, экспорт статических файлов и стилизация. Он также может быть использован в качестве генератора статического сайта.
В настоящее время он находится на вершине списка самых популярных инструментов в своем роде и продолжает набирать популярность. Что понятно, учитывая растущее принятие концепции React.
Неудивительно, что крупные компании, такие как Netflix, Uber и GitHub, уже используют его.
Проблема с одностраничными приложениями и SEO
Сначала я хочу сообщить вам, что у нас есть полное руководство по SEO-оптимизации SPA. Вы можете найти его здесь. В этом посте представлена (очень) сжатая версия.
Возможность работы SPA в браузере полностью основана на JavaScript. С точки зрения SEO это палка о двух концах.
С одной стороны, это приносит отличную производительность и UX, которые являются важными факторами хороших результатов в SEO. Формула проста:
Лучший UX = более длительное среднее время просмотра страницы и более низкий показатель отказов = лучший рейтинг в Google.
Однако в React SPA, как и во многих фреймворках, рендеринг выполняется динамически с помощью JavaScript. Роботы поисковых систем с трудом сканируют асинхронный контент страниц, что приводит к снижению эффективности SEO.
Google неоднократно заявлял, что он стал лучше сканировать JS, но у нас никогда не было доказательств того, что он делает это на 100%. Кроме того, помните, что существуют другие поисковые системы, которые, безусловно, не могут успешно сканировать код JavaScript.
Учитывая, насколько конкурентной стала область поисковой оптимизации, любая небольшая ошибка может стоить вашему онлайн-бизнесу большого количества трафика (и, следовательно, денег). Посмотрим, как мы можем это исправить!
Как я могу проверить, правильно ли сканируется контент моего SPA?
Я предлагаю вам запустить Просмотреть как Google из поисковой консоли Google для каждой ключевой странице сайта.
Название довольно очевидно, но вы можете использовать этот инструмент, чтобы убедиться, что боты находят ваш контент. Он сообщит вам, действительно ли боты могут получить доступ к странице, как он ее отображает и не заблокированы ли какие-либо ресурсы страницы (изображения или скрипты).
Если вы обнаружите, что динамический рендеринг JS создает какие-либо препятствия для сканирования, вы можете быстро на это среагировать.
Как обеспечить сканирование моего контента?
Есть несколько решений этой проблемы. В данном случае мы используем Next.js. Все, что вам нужно определить, это правильный подход для конкретных потребностей:
Рендеринг на стороне сервера. При настройке SSR вы передаете процесс рендеринга на сервер. Затем клиенту возвращаются полностью визуализированные представления HTML, что упрощает логику front-end. По этой причине данный подход отлично подходит для чувствительных ко времени приложений.
Генерация статических файлов. Этот простой процесс выполняет загрузку всех ресурсов в статический HTML-код, чтобы сканеры могли получить его. Он выполняется только для страниц, запрашиваемых ботами, поэтому они не блокируют весь JavaScript, в других случаях (для обычных пользователей) все загружается как обычно.
Сторонние инструменты, такие как Prerender SPA Plugin & Prerender.io, также выполняют этот же процесс, с отличными результатами.
Для этой демонстрации я решил использовать статическую генерацию файлов, потому что для этого не требуется сервер, который напрямую соответствует логике JAMstack.
Чтобы узнать больше об этих подходах рендеринга, посмотрите этот подробный видеоурок. Он посвящен Vue.js, но те же концепции применимы к React.js.
Другие соображения SEO
Очевидно, что SEO — это нечто большее, чем правильное отображение и индексация контента. Существует множество способов оптимизировать контент, чтобы сделать его более привлекательным и качественным. Всегда помните, что для SEO в 2019 году вовлечение пользователей является ключевым аспектом.
Вы можете сказать, что эта часть в основном относится к сфере ответственности создателей контента. Вы будете правы только отчасти. Поисковая оптимизация является задачей команды и всегда должна быть в центре внимания разработчиков.
Многие другие технические аспекты окажут ОГРОМНОЕ влияние на SEO (некоторые из них я опишу в руководстве ниже):
Скорость сайта
Мобильная оптимизация (без вариантов)
Структурированные метаданные
HTTPS-сертификат
Карта сайта
Пришло время рассмотреть, как вы можете в значительной степени охватить все это с помощью Next.js.
Руководство по Next.js: Создание SEO-оптимизированного React SPA
Мы рассмотрим данную тему на примере небольшого интернет-магазина, потому что сайты электронной коммерции являются отличными бизнес-примерами, для которых SEO является жизненно важным. Знайте, что вам не нужно изучать интеграцию корзины для покупок, чтобы понять особенности SEO Next.js. Это демо актуально для любого другого варианта использования.
Предпосылки
Основное понимание одностраничных приложений (SPA)
Учетная запись Snipcart (навсегда бесплатно в тестовом режиме)
1. Создание проекта Next.js
Для этой демонстрации мы начнем с нуля. Создайте новую папку для своего проекта и инициализируйте ее как проект NPM с помощью следующей команды.
1 |
npm init -y |
После этого вы можете установить Next.js, а также зависимости react и react-dom.
1 |
npm i --save react react-dom next |
Я также буду использовать для этой демонстрации Sass. Если вы хотите тоже сделать это, то можете установить следующие пакеты.
1 |
npm i --save @zeit/next-sass node-sass |
В этом случае вам также нужно указать Next.js, что вы хотите использовать этот инструмент. Создайте новый файл в корне проекта с именем next.config.js и добавьте в него следующий код.
1 2 |
const withSass = require('@zeit/next-sass') module.exports = withSass() |
Это задаст обработку автоматического преобразования Sass в CSS. Очень аккуратно! Наконец, обновите package.json и добавьте в него следующие начальные скрипты:
1 2 3 4 5 6 7 8 |
{ "scripts": { "dev": "next", "build": "next build", "start": "next start", "export": "next build && next export" }, } |
Это позволяет использовать команду npm run dev и протестировать сайт локально, введя следующий URL в браузере: localhost:3000.
2. Создание компонентов
В Next.js, как и в большинстве современных фронтенд-фреймворков, используется система компонентов. Однако в Next.js существует различие между обычными компонентами и компонентами страницы. Подробнее об этом в следующем разделе.
Сначала создайте папку с именем components в корневом каталоге. Эта папка будет содержать следующие файлы: Product.js, ProductList.js и ProductDefinition.js.
Файл ProductDefintion.js будет содержать кнопку покупки продукта, как описано в документации.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const ProductDefinition = (props) => { return ( <button className="snipcart-add-item" data-item-id={props.product.id} data-item-name={props.product.name} data-item-price={props.product.price} data-item-image={props.router.pathname} data-item-url="/"> Add to cart ${props.product.price} </button> ) } export default ProductDefinition; |
Здесь мы создали экспортированную переменную, которая содержит функцию, возвращающую элемент HTML. Это все возможно благодаря синтаксису JSX. Параметр функции props будет в конечном итоге передан со страницы index.js. Вам не нужно беспокоиться об этом сейчас.
В файле Product.js мы выведем информацию о товаре, которую должны увидеть пользователи.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import ProductDefinition from './ProductDefinition' const Product = (props) => { return ( <div className="product"> <div className="product__information"> <h2 className="product__title">{props.product.name}</h2> <p className="product__description">{props.product.description}</p> <ProductDefinition product={props.product} /> </div> <img src={props.product.image} alt="product image" className="product__image" /> </div> ) } export default Product; |
Мы также импортировали компонент ProductDefintion и добавили его в оператор return с атрибутом с именем product. В мире React это то, что мы называем свойством, и оно позволяет обмениваться информацией между компонентами. Компонент ProductList просто перебирает каждый товар с использованием функции map и возвращает компонент Product.
1 2 3 4 5 6 7 8 9 |
import Product from "./Product"; const ProductList = (props) => { return ( <div className="products"> {props.products.map((product, index) => <Product product={product} key={index} />)} </div> ) } export default ProductList; |
Примечание. По мере того, как вы вкладываете больше компонентов, вы можете понять, что прохождение свойства через каждый из них может стать повторяющимся. Это анти-паттерн, известный как сквозная передача, и его можно избежать, используя React’s context API или другие инструменты, такие как Redux!
3. Создание домашней страницы
Теперь, когда все «стадартные» компоненты готовы к работе, мы создадим новую папку pages с файлом index.js. Внутри мы импортируем список товаров и таблицу стилей.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import ProductList from "../components/ProductList" import '../assets/index.scss' const Index = (props) => { return ( <div className="app"> <Head> <title>Beautiful, high quality carpets | CarpetCity</title> <link rel="stylesheet" href="//cdn.snipcart.com/themes/v3.0.0-beta.3/default/snipcart.css" /> </Head> <main className="main"> <ProductList products={props.products} /> </main> <script src="//cdn.snipcart.com/themes/v3.0.0-beta.4/default/snipcart.js"></script> <div hidden id="snipcart" data-api-key="<your-public-api-key>"></div> </div> ) } Index.getInitialProps = async () => { return { products: [ { id: "nextjs-seo_carpet1", name: "Straight and Narrow", price: 25.0, image: "static/straight-and-narrow.jpg", description: "Revitalize your living room with this durable and stain hiding carpet." }, ... ] } } export default Index; |
Вам также необходимо импортировать CSS и JavaScript файлы Snipcart, как описано в нашей документации. Так как Next.js не позволяет редактировать файл index.html, как это обычно можно сделать с помощью «ванильного» React, вы можете импортировать их служебный компонент Head и в него поместить все соответствующие HTML-теги.
Кроме того, используя Next.js, мы можем использовать метод жизненного цикла getInitalProps для любого компонента страницы для извлечения данных. Эти данные извлекаются, когда приложение предварительно отрисовывается или обрабатывается на стороне сервера, и передаются в качестве свойства компоненту страницы. Там вы обычно получаете данные из API или CMS. Однако для простоты мы вернем простой объект JavaScript.
4. SEO-оптимизация приложения Next.js
Теперь основное блюдо. Обеспечение соответствия SPA рекомендациям SEO иногда может показаться падением в кроличью нору. К счастью, Next.js выполняет большую часть тяжелой работы за вас. Однако, если это все еще новая для вас тема, я снова приглашаю вас ознакомиться с нашим руководством по оптимизации SPA для Google. Это может дать вам лучшее представление о том, чего мы пытаемся достичь.
4.1 Обеспечение сканирования сайта
Чтобы предложить контент для поисковых систем, Next.js предоставляет вам два варианта: предварительный рендеринг или рендеринг на стороне сервера.
В этом руководстве я покажу вам, как выполнить пререндеринг сайта. Если вы хотите выполнить рендеринг приложения на стороне сервера, вы можете ознакомиться с этим руководством.
Чтобы обновить приложение, обновите файл next.config.js следующим образом и выполните команду npm run export.
1 2 3 4 5 6 7 8 |
const withSass = require('@zeit/next-sass') module.exports = withSass({ exportPathMap: function () { return { '/': { page: '/' }, } } }); |
Это создаст в корне проекта новый каталог с именем out, который содержит все статические страницы.
4.2 Создание карты сайта
Наличие карты сайта — это всегда хорошая практика для SEO, поскольку она помогает поисковым системам соответствующим образом проиндексировать сайт. К сожалению, создание карты сайта может быть довольно утомительным процессом. Поэтому я буду использовать пакет nextjs-sitemap-generate, чтобы максимально автоматизировать задачу.
Это может быть немного излишним в данный момент, когда у вас есть только одна страница; тем не менее, вы будете готовы идти дальше, если когда-нибудь решите расширить свое SPA.
1 |
npm i nextjs-sitemap-generator |
После установки пакета добавьте следующий код в файл конфигурации:
1 2 3 4 5 6 |
const sitemap = require('nextjs-sitemap-generator'); sitemap({ baseUrl: '<your_website_base_url>', pagesDirectory: __dirname + "/pages", targetDirectory : 'static/' }); |
Он генерирует файл sitemap.xml внутри каталога out. Иметь ввиду; вам нужно будет вручную указать карту сайта в консоли поиска Google.
4.3 Добавление метаданных
Обычно хорошей идеей является добавление метаданных, поскольку это помогает сканерам понять содержание ваших страниц. Next.js автоматически добавляет большинство из них, включая viewport и content. Однако вам нужно определить мета-тег описания, отредактировав компонент Head в файле index.js следующим образом:
1 2 3 4 5 |
<Head> <meta name="description" content="Buy beautiful, high quality carpets for your home."/> <title>Beautiful, high quality carpets | CarpetCity</title> <link rel="stylesheet" href="//cdn.snipcart.com/themes/v3.0.0-beta.3/default/snipcart.css" /> </Head> |
После того, как все эти действия выполнены, Google Lighthouse должен оценить ваше SPA:
Неплохо, а?
5. Хостинг проекта с использованием Netlify
На этом этапе вы, вероятно, захотите разместить свое SPA для других пользователей. К счастью, в настоящее время этот шаг значительно упрощен.
Примечание. Netlify размещает весь веб-сайт под HTTPS, что является обязательным требованием в современной практике SEO!
Предполагая, что ваш проект уже работает в сервисе, подобном GitHub, GitLab или BitBucket, разместить ваш сайт с помощью Netlify почти так же просто, как войти в систему и привязать свой репозиторий. Просто убедитесь, что вы ввели команду npm run export и каталог публикации out следующим образом:
После завершения сборки Netlify ваше SEO-оптимизированное SPA должно быть запущено!
Онлайн демо и GitHub репо
Репозиторий Github вы найдете здесь. Онлайн демо здесь.
Заключение
Это был не первый мой раз работы с Next.js, и мое мнение о нем сильно не изменилось. Это хороший слой поверх React, который помогает сделать вашу жизнь проще во многих ситуациях. Выполнение того же самого с использованием только React потребовало бы гораздо большего времени и усилий.
В общем, я потратил около суток на то, чтобы построить эту демонстрацию и убедиться, что она оптимизирована для SEO.
Чтобы продвинуть эту демонстрацию дальше, было бы интересно создать отдельные страницы для каждого товара. Было бы несправедливо ожидать, что Next.js обнаружит все пути для динамических URL-адресов, поэтому нам потребуется создать функцию, которая динамически определяет путь каждого товара для представления.
Автор: Michael Poirier-Ginter
Источник: //snipcart.com
Редакция: Команда webformyself.