Всем привет!
Сегодня хотел бы рассказать об одном решении самой частой проблемы в командной разработке, которое в итоге вылилось в целый npm пакет.
И как вы поняли, речь пойдёт о SEO анализаторе, инструменте, который поможет отлавливать SEO дефекты на разных стадиях разработки (и, конечно же, сохранить хорошие отношения с SEO специалистами ????).
Введение
Как раз таки разработка этого инструмента и началась с того, что мы всё чаще и чаще начали натыкаться на проблемы с SEO. При каждом новом релизе на продакшн, появлялись новые, но всё те же проблемы. Отношения с SEOшниками начали портиться, появилась ругань, оры на созвонах и прочие неприятные моменты.
В конце концов мы решили разобраться с этим и в итоге получили удобный и полезный инструмент, о котором поговорим ниже.
Зачем нужен SEO Анализатор?
Основная задача — анализ DOM дерева с целью обнаружения SEO дефектов.
Многие могут задать вопрос: “а чем Lighthouse не угодил?”
Lighthouse — это многофункциональный и порой избыточный инструмент, который не всегда хочется тянуть в маленький проект.
SEO Analyzer же — это легковесный плагин, нацеленный на конкретную задачу — держать ваш проект валидным и дружелюбным к поисковым роботам, путём обнаружения дефектов на страницах вашего сайта.
Если вам важно отлавливать распространенные ошибки SEO заранее, то этот инструмент станет отличным помощником.
Преимущества
Простая настройка.
Запуск Анализатора для SPA-приложений.
Запуск Анализатора для SSG и SSR приложений.
Запуск Анализатора в пайплайнах github, gitlab, pre-push или в любом, другом месте.
9 готовых и самых популярных правил.
Добавление собственных правил.
Несколько вариантов вывода результата.
Установка пакета
Перейдем по ссылке, которая перенаправит нас на страницу анализатора на сайте npm.
Справа, над мета информацией, можно скопировать команду для установки пакета.
Перейдем в проект и установим там библиотеку.
npm i seo-analyzer
Он довольно легкий, поэтому установка пройдёт мгновенно.
Настройка
Далее перейдем к настройки пакета.
Первым делом, нужно определить, где в проекте будет располагаться скрипт для запуска анализатора. Я в своём проекте расположил файл в корне и назвал его seo-analyzer.js
. Вы можете сделать так же.
Откроем файл и добавим туда нужный функционал.
Например, мы разрабатываем сайт как SPA (single page application), где верстку рендерит JavaScript. Как мы знаем, это создаёт некоторые проблемы при парсинге, а именно с тем, что DOM дерево рендерится только после того, как JavaScript код будет готов. В этом случае настройки должны быть такими:
const SeoAnalyzer = require('seo-analyzer');
new SeoAnalyzer()
.ignoreUrls(['/404'])
.inputSpaFolder('/dist', 3000)
.addRule('noMoreThanOneH1TagRule')
.outputConsole();
Начнём по порядку.
В начале файла само собой импортируем скрипт анализатора. Далее создаём новый экземпляр и начинаем настраивать:
.ignoreUrls(['/404'])
— список урлов, которые нужно игнорировать при анализе страниц. Можно указать любое кол-во страниц..inputSpaFolder('/dist', 3000)
— указываем папку, куда будут собраны финальные html страницы и указываем порт, на котором поднимется сервер для парсинга и дальнейшей обработки этих страниц..addRule('noMoreThanOneH1TagRule')
— выбираем из списка девяти готовых правил нужные и добавляем для обработки..outputConsole()
— если мы ни как не будем в дальнейшем обрабатывать репорт ошибок, то вывод в консоль будет самым простым вариантом.
Этих настроек достаточно, SEO Анализатор готов к валидации ваших страниц.
Для запуска нужно выполнить следующую команду в терминале:
node seo-analyzer.js
В результате должен быть примерно такой репорт:
Доступные методы
Разделю список методов на несколько частей, чтобы был понятен их порядок в цепочке. Первые на очереди — методы для игнорирования файлов, папок и ссылок.
Их нужно использовать в зависимости от входных данных (о них ниже).
ignoreFiles(['/dist/404.html'])
: принимает список файлов, которые нужно игнорировать при анализе.ignoreFolders(['/dist/test'])
: принимает список папок, которые нужно игнорировать при анализе.ignoreUrls(['/404', '/login'])
: принимает список ссылок, которые нужно игнорировать при анализе.
Следующие в цепочке — это входные данные. Они должны быть расположены ниже методов игнорирования.
inputFiles(['/dist/index.html'])
: принимает список файлов, которые нужно обработать.inputFolders(['/dist'])
: принимает список папок, в которых будут найдены все html файлы и проанализированы.inputSpaFolder('/dist', 3000)
: принимает два параметра: первый — папка, в которой будут финальные файлы для продакшна, второй: порт, на котором запустится сервер для парсинга html.
Далее метод для добавления готовых правил либо собственных.
addRule('titleLengthRule', { ... })
: принимает два параметра: первый — название готового правила в виде строки или имя функции кастомного правила в виде названия функции, второй: параметры для готовых правил.
Ну и последний список — это методы для вывода результата:
outputJson(json => {})
: принимает колбэк функцию, в которую передается результат в виде JSON данных.outputObject(obj => {})
: тоже принимает колбэк функцию, в которую передается результат в виде JS объекта.outputConsole()
: не принимает никаких параметров, всего лишь выводит результат в консоле. И если в результате будут ошибки, этот метод завершит процесс в терминале.
Метод
outputConsole()
нужно использовать с самом конце, так как если он завершит процесс, оборвется дальнейшая цепочка и методы за ним не будут запущены.
Список готовых правил
Для быстрого старта анализатора я подготовил девять самых популярных правил, которых должно хватить для базовой проверки. Давайте расскажу о них поподробнее.
Для добавления правила в цепочку нам нужен метод addRule()
. Он принимает два параметра:
Название готового правила или имя функции кастомного правила.
Параметры. Они нужны только для готовых правил, так как другого пути их настроить нет.
После выбора нужного правила нам достаточно добавить его в цепочку, между входными параметрами и выходными, то есть вот так:
.inputSpaFolder(...)
.addRule('titleLengthRule', { ... }) <----
.outputConsole(...)
Чтобы не нарушалась цепочка обработчиков, нужно соблюдать порядок при добавлении методов.
Теперь давайте глянем на весь список готовых правил.
Title Length Rule
.addRule('titleLengthRule', { min: 10, max: 50 })
Проверяет длину тега <title>. Принимает два параметра:
min: минимальная длина заготовка.
max: максимальная длина заголовка.
H Tags Rule
.addRule('hTagsRule')
Проверяет правильность расстановки h заголовков на странице.
Например, вот вариант с невалидной расстановкой
<h1>
- <h3>
- - <h4>
- <h2>
По правилам заголовок h3 должен располагаться за тегом h2. Вот так
<h1>
- <h2>
- - <h3>
- <h2>
В этом случаем проблем не должно быть.
No More Than One H1 Tag Rule
.addRule('noMoreThanOneH1TagRule')
Проверяет количество тегов <h1> на странице. Должен быть всего один тег h1.
Img Tag With Alt Attritube Rule
.addRule('imgTagWithAltAttritubeRule')
Проверяет, все ли теги <img> имеют атрибут alt=”…”.
Tag “a” With Rel Attritube Rule
.addRule('aTagWithRelAttritubeRule')
Проверяет, все ли теги <a> имеют атрибут rel=”…”.
No Too Many Strong Tags Rule
.addRule('noTooManyStrongTagsRule', { threshold: 2 })
Проверяет количество тегов <strong> на странице. Принимает один параметр:
threshold: максимальное количество тегов на странице
Meta Base Rule
.addRule('metaBaseRule', { list: ['description', 'viewport'] })
Проверяет, присутствуют ли на странице указанные базовые мета теги. Принимает один параметр:
list: список обязательных мета тегов на странице
Meta Social Rule
.addRule('metaSocialRule', {
properties: [
'og:url',
'og:type',
'og:site_name',
'og:title',
'og:description',
'og:image',
'og:image:width',
'og:image:height',
'twitter:card',
'twitter:text:title',
'twitter:description',
'twitter:image:src',
'twitter:url'
],
})
Проверяет, присутствуют ли на странице указанные социальные мета теги. Принимает один параметр:
properties: список обязательных мета тегов на странице
Canonical Link Rule
.addRule('canonicalLinkRule')
Проверяет, существует ли на странице каноническая ссылка.
Добавление кастомного правила
Если вдруг вам не хватило готовых правил для базовой валидации, вы с легкостью можете добавить своё.
По сути, кастомное правило — это всего лишь функция, которая принимает DOM дерево. С ним мы и будем работать.
Правило должно быть промисом, чтобы остальные дожидались его завершения.
Давайте напишем своё правило. Оно будет простым и проверит всего лишь наличие параграфов на странице. Добавим такой код:
function customRule(dom) {
return new Promise(async (resolve, reject) => {
const paragraph = dom.window.document.querySelector('p');
if (paragraph) {
resolve('');
} else {
reject('Not found <p> tags');
}
});
}
В аргументах передаётся dom, с которым мы можем проводить те же манипуляции, что и в браузере. То есть нам доступен объект window.
После того, как ваше правило готово, его можно добавлять в цепочку и проверять.
.addRule(customRule)
В итоге, если на странице не окажется параграфов, мы получим ошибку в консоле “Not found <p> tags”
Запуск в CI/CD
Запуск SEO Анализатора в CI/CD нужен лишь для того, чтобы отлавливать SEO дефекты на стадии подготовки новых изменений для стейджинга или продакшна. При сборке Pull реквеста, если будут найдены проблемы с SEO, pipeline упадёт. Тем самым сообщив вам, что с изменениями что-то не так и они требуют правок.
Для примера будем запускать анализатор в github actions. Это делается очень просто. Давайте убедимся в этом, посмотрев на код ниже
name: Seo Analyzer CI
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm run build
env:
CI: true
- run: node ./seo-analyzer.js
Как и сказал, ничего сложного нет. Нам всего лишь нужно настроить команду сборки проекта и после запустить файл со скриптом анализатора, который мы настраивали выше.
В корне проекта создайте папку .github
и в ней папку workflows
. В папке workflows
создайте файл seo-analyzer.yml
, в который поместите код выше. После того, как изменения будут отправлены в github, запустится action и SEO Анализатор.
Запуск в pre-push или pre-commit
Чтобы не допускать отправку невалидных изменений на сервер, предлагаю настроить запуск анализатора на хук pre-push.
Это позволит проверять изменения на валидность при каждой отправке на сервер, и, если ошибок не будет, только в этом случает изменения будут отправлены.
Для настройки нам понадобится пакет husky.
Установим его:
npm install husky --save-dev
Настройки для этого плагина нужно добавить в файл package.json. Можно и отдельный файл создать, но не суть.
В конце файла package.json добавьте следующий код:
{
...
"husky": {
"hooks": {
"pre-push": "npm run build && npm run seo-analyzer.js"
}
}
...
}
Теперь до того, как изменения улетят на сервер, будет запущен анализатор и ваши изменения буду провалидированы.
Теперь до того, как изменения улетят на сервер, будет запущен анализатор, и ваши изменения буду провалидированы.
Заключение
Очень важно иметь высокие показатели SEO, от этого зависит трафик на вашем сайте и соответственно доход. Такие инструменты как SEO Analyzer помогут сохранить эти показатели в проекте. Не пренебрегайте, пользуйтесь и будьте счастливы!
Надеюсь, SEO Анализатор окажется для вас полезным инструментом.
Ссылка на github. Ссылка на npm пакет.
Cпасибо.