- Що таке Next.js?
- Обробка SEO React.js
- Навчальний посібник Next.js: Обробка SEO на SPA React.js
- 1. Створення структури проекту
- 2. Знущання над архітектурою реального проекту з Redux
- 3. Написання та надання продукції
- 4. Створення статичних файлів для React SEO
- 5. Розгортання статичних активів
- Демонстрація в реальному часі & GitHub repo
- Інші важливі загальні SEO міркування
- Закриття думок
Поспіхом? Перейти до навчальні кроки або демо .
Не так давно мій друг-розробник розповідав мені про новий проект електронної комерції для клієнта.
"Мені б подобалося використовувати додаток React.js, якби це не було для всіх цих питань SEO".
Зітхання
Я думала, що вже переконала його зі своїм раніше на Vue.js (або цей з Angular), що SEO з JS фреймворками було керованим.
Я думаю, що не! Тому я почав з нуля і пояснив моєму другу, як обробляти SEO за допомогою React SPA.
Сьогодні я даю йому відповідь словами, використовуючи Next.js для створення зручного СПГ на електронній комерції.
У цьому підручнику я:
- Створити проект Next.js.
- Використовуйте прив'язки React / Redux.
- Напишіть та зробіть продукти.
- Створення статичних файлів для SEO.
- Розгортайте мої статичні засоби за допомогою Netlify.
Перед тим, як стати практичним, давайте розглянемо трохи теорії.
Що таке Next.js?
У двох словах Next.js - легкий фреймворк для статичних і серверно-рендерируемых програм React.
Не плутайте його з Nuxt, який є основою для Універсальні програми Vue.js - фактично натхненний Next. Вони поділяють дуже подібні цілі.
До теперішнього часу ви повинні принаймні почути про React, але заради ясності ми визначимо його як компонентну бібліотеку JavaScript для побудови інтерфейсів.
А що ми розуміємо під універсальним JavaScript ? Ну, це відноситься до додатків, де JavaScript працює як на клієнті, так і на сервері. Це відмінно як для продуктивності в завантаженні першої сторінки, так і для цілей SEO, як ми побачимо в даний момент.
Далі також є простий набір функцій, включаючи автоматичне розбиття коду, просту маршрутизацію на стороні клієнта, середовище розробки веб-пакунків і будь-яку реалізацію сервера Node.js. Його також можна використовувати як a статичний генератор сайту .
Не дивно, що такі компанії, як Netflix, Ticketmaster і GitHub, вже використовують його.
Обробка SEO React.js
Що з SEO у React SPA? Як і багато фронтендні рамки, візуалізація здійснюється динамічно за допомогою JavaScript. Роботи пошукової системи потім мають важкий час для сканування асинхронного вмісту наших сторінок, що призводить до зниження показників SEO.
Пошукова оптимізація тепер є дуже конкурентним полем і невеликі помилки можуть коштувати вашому інтернет-бізнесу багато трафіку.
Давайте подивимося, як це можна виправити!
Як я можу перевірити правильність сканування мого вмісту SPA?
Я пропоную вам запустити Отримати як Google з консолі пошуку Google на кожній ключовій сторінці вашого веб-сайту.
Назва досить зрозуміла, але ви можете скористатися цим інструментом, щоб переконатися, що боти знаходять ваш вміст. Він повідомить вам, чи дійсно він може отримати доступ до сторінки, як він надає її, і чи заблоковано будь-який з ресурсів сторінки (зображення або скрипти) для Googlebot.
Якщо ви виявите, що динамічне відображення JS викликає будь-які перешкоди для сканувань пошукових систем, ви можете швидко діяти.
Як переконатися, що мій вміст сканується?
Як я вже дізнався з Vue.js, є кілька рішень цієї проблеми. У цьому випадку відповідь буде надходити з Next.js.
Все, що потрібно визначити, - це правильний підхід до ваших потреб:
→ Відображення на стороні сервера . Під час налаштування SSR вивантажуєте процес рендерінгу на сервер. Потім повертається клієнту повністю переглянуті HTML-перегляди, що полегшує логіку інтерфейсу. З цієї причини цей підхід відмінно підходить для чутливих до часу програм.
→ Генерація статичних файлів . Цей легкий процес виконує дію завантаження всіх ваших активів у статичний HTML, щоб сканери могли насолоджуватися. Він виконується тільки для сторінок, які запитуються ботами, тому вони не блокуються всіма JavaScript, інакше (для звичайних користувачів) все завантажується як завжди.
→ Такі інструменти третіх сторін Плагін Prerender SPA & Prerender.io також роблять той самий процес, що й останній, з чудовими результатами.
Для цієї демонстрації, я вирішив піти зі створенням статичних файлів, оскільки він не вимагає сервера, який безпосередньо підходить до Логіка JAMstack .
Щоб дізнатися більше про ці підходи до рендерингу, перегляньте це ретельне відео-підручник . Це було зроблено для Vue.js, але поняття застосовні до React.js.
Навчальний посібник Next.js: Обробка SEO на SPA React.js
Передумова
1. Створення структури проекту
Почнемо з нуля тут. Створіть нову папку, в якій ви бажаєте, і виконайте такі команди:
npm інсталяція - зберегти наступну установку npm --save react npm install --save react-dom npm install - зберегти redux npm install --save react-reduxТепер, коли у мене є необхідні залежності, давайте напишемо власну структуру файлу.
корінь ├───компоненти ────lib └───сторінки2. Знущання над архітектурою реального проекту з Redux
Я хочу зробити цю демонстрацію якомога більш реальною. Таким чином, навіть якщо він буде відчувати себе трохи надуманим для нашого випадку використання, я вирішив використовувати Redux з Реакція / зменшення прив'язки.
Пізніше я продемонструю магазин з продуктами як початковий стан, але не будь-які дії та редуктори. Це робиться тільки для того, щоб ви максимально наблизилися до реальної архітектури.
Перейдіть у папку "Сторінки" та створіть файл _app.js, який є новим доповненням до пункту Next - він працюватиме, лише якщо ви використовуєте версію 6 і вище.
Вона дозволяє переходити сторінки, межі помилок тощо. У моєму випадку я використовую його для написання нового формату App, який використовує постачальника React / Redux, щоб він ін'єктував магазин Redux в мої компоненти.
Відмова від відповідальності: ця архітектура дуже натхнена Це наступне з демо-Redux .
Ось вміст мого файлу:
import App, {Container} з імпорту 'next / app' Реагуйте з імпорту 'реакції' withReduxStore з '../lib/with-redux-store' імпортувати {Provider} з класу 'react-redux' MyApp extends App {render ( ) {const {Component, pageProps, reduxStore} = this.props return (<Container> <Постачальник магазину = {reduxStore}> <div id = "main"> <h1 className = "title"> Магазин Peaky Blinders '</ h1 > <Компонент {... pageProps} /> <div> <p> Додаток Next.js для SEO з <a href="https://snipcart.com/"> Snipcart </a>. a href = "https://github.com/snipcart/next-snipcart"> [Див. код] </a> <a href = "https://snipcart.com/blog/react-seo-nextjs-tutorial "> [Прочитати повний посібник] </a> </p> </div> </div> </Provider> </Container>)}} експортувати за промовчанням ізReduxStore (MyApp)Як ви бачите, я надаю магазин своєму провайдеру і передаю поточні реквізити сторінки до поточного компонента.
Я не експортую компонент безпосередньо, але закликаю withReduxStore з MyApp як параметр. Ви повинні розробити цю функцію, оскільки вона не існує на даний момент.
Це, безумовно, найскладніша функція. З цією статтею я не буду детально пояснювати її, оскільки він трохи більш просунутий, а складний розділ служить лише в тому випадку, якщо ви використовуєте рендеринг на стороні сервера. Як я буду генерувати статичні активи, все це повинно бути нормально.
Отже, перейдіть до папки / lib і створіть файл with-redux-store.js із таким вмістом:
імпортувати App з 'next / app' import {initializeStore} з '../store' const isServer = typeof вікно === 'undefined' const __NEXT_REDUX_STORE__ = '__NEXT_REDUX_STORE__' функція getOrCreateStore (initialState) {// Завжди створюйте новий магазин, якщо сервер, інакше стан поділяється між запитами, якщо (isServer) {return initializeStore (initialState)} // Зберігається в глобальній змінної, якщо клієнт if (! window [__ NEXT_REDUX_STORE__]) {window [__ NEXT_REDUX_STORE__] = ініціалізація (початковогостану)} вікно повернення [__ NEXT_REDUX_STORE__ ]} default default (App) => {клас повернення Redux розширює React.Component {статичний async getInitialProps (appContext) {const reduxStore = getOrCreateStore () // Вкажіть сховище getInitialProps сторінок appContext.ctx.reduxStore = reduxStore let appProps = {} if (App.getInitialProps) {appProps = await App.getInitialProps (appContext)} повернути {... appProps, initialReduxState: reduxStore.getState ()}} конструктор (реквізит) {super (props) this.reduxStore = getOrCreateStore ( реквізит. initialReduxState)} render () {return <App {... this.props} reduxStore = {this.reduxStore} />}}}В основному, це перевіряє, чи додаток працює на сервері або в браузері, а потім вирішує, чи подавати новий екземпляр магазину Redux чи поточний. Після того, як вона буде визначена, я надаю її компоненту App як опору.
Це дасть вам доступ до магазину в кожному компоненті верхнього рівня.
Імпортуйте initializeStore, яка є останньою частиною '' управління даними '', необхідної перед переходом у продукти. Зробіть файл store.js безпосередньо в кореневій теці.
import {createStore} з експорту "redux" const actionTypes = {} const initialState = {products: [{name: 'Мій перший продукт', ціна: 50, опис: 'Мені подобаються черепахи', зображення: 'url', id: 1}, {name: 'Мій другий продукт', ціна: 100, опис: 'Мені подобається zonks', зображення: 'url', id: 2}, {name: 'Мій третій продукт', ціна: 150, опис: "Мені подобаються дракони", зображення: 'url', id: 3}]} // REDUCERS export const редуктор = (state = initialState, action) => {switch (action.type) {default: return state}} функція експорту initializeStore (initialState = initialState) {return createStore (редуктор, вихіднийстатус)}Як згадувалося раніше, в магазині є голі кістки. Це дійсно просто примірники з початковим станом, але не дає нічого іншого. Ви все одно розміщуватимете там продукти, оскільки вони дають реалістичний вигляд способу доступу до даних у компонентах, які я визначу на наступному кроці.
3. Написання та надання продукції
Для цієї демонстрації, я хочу два різних компонентів, products.js, які будуть надавати посилання на кожен продукт, і product.js, який покаже кожну інформацію про продукт.
Запишіть кожну з них в папку компонентів / папок.
Продукція буде трохи складнішою, оскільки вона потребує доступу до магазину Redux, але обидва вони залишаються простими, оскільки вони є функціональними компонентами. Вони роблять лише те, що їм дають, як реквізит, таким чином, вони можуть бути виключно представлені як функція, не розширюючи нічого.
Ось компонент продуктів:
імпортувати посилання з "next / link" const ProductLink = (реквізити) => (<div className = "product"> <посилання як = {`/ product / $ {props.id}`} href = {`/ product? id = $ {props.id} `}> <a> <img src = {props.image} alt = {props.name} висота = '250' className =" ескіз "/> <p> {props.description} < / p> <p> {props.name} </p> </a> </Link> </div>) var Products = ({products}) => (<div> <div className = "products") {products.map (props => (<ProductLink ключ = {props.id} {... props} />))} </div> </div>) експортувати продукти за замовчуваннямА тепер ось product.js:
експортувати за замовчуванням (props) => (f <div className = "product"> <a className="product" href={props.url }> <img src = {props.image} alt = {props.name} className = "thumbnail" /> <p> {props.name} </p> </a> <button className = "snipcart-add-item" data-item-name = {props.name} data-item-id = { props.id} data-item-image = {props.image} data-item-url = '/' data-item-price = {props.price}> Купити для {props.price} $ </button> < / div>)Тепер, коли у вас є ці два компоненти, потрібно використовувати їх у маршрутах, щоб вони могли відтворювати дані.
Для цього створіть два нових файли в папці pages, index.js і product.js.
Перша така:
import Відреагувати на імпортувати {connect} з імпорту 'react-redux' Продукти з імпорту '../components/products' з класу 'next / head' Index extends React.Component {render () {return (<div > <Head> <link href = "/ static / main.css" rel = "stylesheet" /> <meta name = "title" content = "електронна комерція Peaky Blinder" /> <meta name = "description" content = "Знайти найкращі продукти Peaky Blinders онлайн." /> </Head> <Продукти {... this.props} /> </div>)}} const mapStateToProps = (state) => ({products: state.products }) експортувати за умовчанням (mapStateToProps) (індекс)Те, що робить React / Redux, замість того, щоб ви могли безпосередньо звертатися до магазину Redux, це дає вам функцію підключення, яка дає вам змогу зіставити частину штату з опорою. Хоча тут і не зроблено, він також може надати вам спосіб відображення функції відправлення на опору.
Це повністю ізолює логіку від рівня презентації. Це дійсно цікавий спосіб виконання речей і сильний вплив функціонального програмування, оскільки ви можете легко розділити всі залежності компонента безпосередньо в його реквізитах.
Якщо ви хочете прочитати більше про це, є акуратна стаття тут що вводить ці поняття.
Зважаючи на цей принцип, визначте другий файл як:
import React from 'react' import {connect} з імпорту 'реакція-redux' ProductComp з імпорту '../components/product' Голова з класу 'next / head' Продукт розширює React.Component {static getInitialProps = ({query}) => ({id: query.id}) getProduct = () => (this.props.products.filter (x => x.id == this.props.id) [0]) render = () => (<div> <Head> <script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"> </script> <script src = "https: //cdn.snipcart.com/scripts/2.0/snipcart.js "data-api-key =" YjdiNWIyOTUtZTIyMy00MWMwLTkwNDUtMzI1M2M2NTgxYjE0 "id =" snipcart "> </script> <link href =" https://cdn.snipcart.com/ themes / 2.0 / base / snipcart.min.css "rel =" stylesheet "type =" text / css "/> <посилання href =" / static / main.css "rel =" stylesheet "/> <meta name =" title "content = {" "Peaky Blinder" + this.getProduct (). name} /> <meta name = "description" content = {this.getProduct (). description} /> </Head> <a href = "/ "> повернутися додому </a> <ProductComp {... (this.getProduct ())} /> </div>); } const mapStateToProps = (state) => ({products: state.products}) експортувати за замовчуванням (mapStateToProps) (Product)Таким чином, компоненти залишаються "чистими", що означає, що вони не обробляють логіку фільтрації, ані логіку вибірки. Вони просто отримують дані і показують її.
Я також додав необхідні сценарії Snipcart. Компонент головки Next.js - це проста обгортка. Отже, все, що міститься в ньому, буде розміщено в голові тега наданої сторінки.
Я також включив деякі мета-теги тут. У цьому випадку я використовував "title" і "description", які ви повинні заповнити дослідженими ключовими словами. Навіть якщо вони не відображатимуться на сторінці, вони допоможуть сканерам зрозуміти вміст вашої сторінки.
Для SEO також важливо знати про meta name = "robots" . Ви будете використовувати його у великих проектах, де є внутрішні сторінки, доступні після входу в систему або будь-яку іншу сторінку, яку ви не хочете індексувати. Прочитай це вивчити всі його атрибути.
4. Створення статичних файлів для React SEO
Оскільки сторінки створюються динамічно за допомогою даних магазину Redux, вам потрібно надати деякі шляхи до Next, щоб знати, які маршрути генерувати при створенні статичних файлів.
Для цього створіть файл next.config.js безпосередньо у папці маршруту:
module.exports = {exportPathMap: function () {return {'/': {page: '/'}, '/ product / 1': {сторінка: '/ product', запит: {id: "1"}} , '/ product / 2': {сторінка: '/ product', запит: {id: "2"}}, '/ product / 3': {сторінка: '/ product', запит: {id: "3" }}}}}Мені дуже подобається, як це просто виконується. Немає необхідності підключатися до процесу збирання; простий файл JS дозволяє вам це робити.
Звичайно, це було тільки три продукти з легкими ідентифікаторами для жорсткого коду тут. Але створити повернутий об'єкт динамічно з певним заданим форматом не важко, оскільки це файл JavaScript, де можна використовувати будь-яку логіку.
Перш ніж розгортати цю програму для будь-якої третьої сторони, спробуємо її спочатку на місцевому рівні.
Додайте наступний розділ сценаріїв у ваш файл package.json:
"scripts": {"build": "next build", "export": "next export", "deploy": "next build && next export", "start": "next"}Тепер запустіть програму npm у кореневій теці вашого проекту. Це почнеться Next в якості сервера, і ви зможете отримати доступ до всього з http: // localhost: 3000.
Якщо ви хочете генерувати статичні файли, ви можете зробити це за допомогою npm run export. Це створить папку, де ви знайдете їх. Якщо ви хочете розмістити їх локально для тестування виводу, ви можете зробити це швидко з пакетом npm, таким як службу.
5. Розгортання статичних активів
Тепер ви готові розгорнути веб-сайт. Використовуємо Netlify.
По-перше, вам доведеться підштовхнути код до репо Git, а потім перейти в Netlify панель приладів .
Тут можна створити новий сайт із такою конфігурацією:
Варто зауважити, що автори програми Next мають назву продукту для розгортання Тепер . Вона дозволяє розгортати статичні активи після збирання безпосередньо з вашого терміналу, за допомогою однієї команди. Це дійсно акуратно, однак, оскільки я вже використовую Git repo, щоб показати мій код, я вирішив дотримуватися Netlify.
Демонстрація в реальному часі & GitHub repo
Дивіться демо-версію тут .
Див. Репо GitHub тут .
Інші важливі загальні SEO міркування
- Індексація для мобільних пристроїв в даний час є одним з основних факторів ранжирування. Настільки, що ви повинні піклуватися про свій мобільний досвід стільки ж, скільки робочий стіл, якщо не більше!
- Якщо ви все ще не знаєте про важливість з'єднання HTTPS, вам слід негайно розглянути її. Я розміщую цю демонстрацію Netlify , яка надає безкоштовні SSL сертифікати з усіма планами.
- Щоб зробити вашу гру SEO, ви хочете, щоб ремесло великий вміст . Ви також можете легко редагувати та оптимізувати його. Для цілей редагування вмісту розгляньте можливість викидання одного з них CMS без голови в суміш!
- Не забудьте додати відповідні мета-теги, як ми бачили раніше. Карта сайту ваших сторінок також дуже актуальна. Ви можете знайти чудовий приклад того, як створити карту сайту для проектів Next.js тут .
Закриття думок
Гра з обома Next.js і React була дійсно веселою. Я не зіткнувся з будь-якими серйозними проблемами, тому що в їхніх документах на все було досить просто відповісти, що є справді ретельним. Мені подобається підхід "вікторини", оригінал!
Мені знадобилося близько двох годин, щоб побудувати все це. Ми взяли трохи більше часу, використовуючи прив'язку до реакції: я блукав деякий час у їхніх прикладах, щоб чітко зрозуміти, що відбувається.
Щоб просунути все це далі, було б цікаво зібрати магазин з більшою кількістю продуктів, щоб генерувати pathMap динамічно. Я також дивуюся, до якого моменту процес збірки стає роздутою, якщо у вас занадто багато маршрутів для експорту. Якщо у вас є відповідь на це, дайте мені знати в коментарях!
З креативністю, відмінним кодуванням і продуманим доглядом за SEO не варто стояти на шляху ваших наступних проектів!
Якщо ви користуєтеся цією публікацією, будь ласка, візьміть секунду поділіться ним у Twitter . Є коментарі, запитання? Натисніть розділ нижче!
Js?Js?
Як я можу перевірити правильність сканування мого вмісту SPA?
Як переконатися, що мій вміст сканується?
Id}`} href = {`/ product?
Є коментарі, запитання?