WebDev+ | Веб-разработка
8.32K subscribers
505 photos
241 videos
10 files
700 links
Присоединяйтесь к нашему каналу и погрузитесь в мир веб-разработки

Связь: @devmangx
Download Telegram
Ecommerce-сайт с фильтрами это SEO-кошмар.

Каждая комбинация фильтров создает новый URL:

- /shoes/
- /shoes/?color=red
- /shoes/?color=red&size=10
- /shoes/?color=red&size=10&brand=nike

50 фильтров = 1+ млн возможных URL.

Crawl budget у Google раздувается.
Штрафы за дублирующийся контент.

Вот как исправить faceted navigation и не убить фильтры:

1/ Проблема faceted navigation

Удобные для пользователя фильтры создают SEO-бардак:

10 категорий × 20 цветов × 15 размеров × 10 брендов
= 30 000 возможных URL

И все они показывают похожие товары.
Google тратит crawl budget впустую.
Ни один из них нормально не ранжируется.

У клиента было 127 000 индексируемых комбинаций фильтров.
Ценных было только 200.
Google не понимал, что именно ранжировать.

2/ Решение 1: обработка параметров в GSC

Google Search Console → Settings → Crawling → URL Parameters

Настройте каждый параметр:

No URLs:

- Параметры, которые не меняют контент
- Трекинговые коды (utm_source)
- Session ID

Representative URL:

- Параметры, которые меняют контент
- Дайте Google самому решить, что индексировать

Every URL:

- Параметры, создающие уникальные ценные страницы

Клиент настроил 15 параметров.
Индекс сократился с 127K до 3K страниц.
Позиции выросли.

3/ Решение 2: стратегия с robots meta tag

Используйте noindex на отфильтрованных страницах:

<?php if (isset($_GET['color']) || isset($_GET['size'])) { ?>
<meta name="robots" content="noindex, follow">
<?php } ?>


Позволяет:
Пользователи могут фильтровать
Google может обходить ссылки
Link equity передается
Google не будет индексировать страницы с фильтрами

Индексируйте только основные страницы категорий.


4/ Решение 3: Canonical на версию без фильтров

Все комбинации фильтров → canonical на основную категорию:

<!-- On /shoes/?color=red&size=10 -->
<link rel="canonical" href="https://example.com/shoes/" />


Это консолидирует сигналы в один URL.

Но: теряется возможность ранжироваться по запросу вроде red shoes size 10

Используйте, если:

- У комбинаций фильтров нет search volume
- Вам не нужно, чтобы страницы фильтров ранжировались

5/ Решение 4: стратегическая индексация (лучший вариант для большинства)

Индексируйте только ценные комбинации фильтров.

Индексировать:

/shoes/ (основная категория)
/shoes/red/ (цвет с высоким спросом)
/shoes/nike/ (популярный бренд)
/shoes/running/ (подкатегория)

Noindex для:

/shoes/?color=red&size=10&brand=nike&sort=price
Любой комбинации с 2+ фильтрами
Фильтров без search volume

Как реализовать:

$params = count($_GET);
if ($params > 1) {
echo '<meta name="robots" content="noindex, follow">';
}


6/ Решение 5: чистые URL для ценных фильтров

Перепишите URL фильтров так, чтобы они выглядели как категории:

Вместо: /shoes/?color=red
Сделайте: /shoes/red/

Плюсы:

- Выглядит как страница категории
- Лучше для SEO
- Можно отдельно оптимизировать title/meta
- Проще внутренняя перелинковка

У клиента было 20 ценных комбинаций фильтров.
Их перевели на clean URLs.
Все начали ранжироваться в течение 6 недель.

7/ Стратегия "View All"

Для небольших наборов товаров (<200 позиций):

Уберите пагинацию и фильтры полностью.
Покажите все товары на одной странице.

Пример:

- В категории 47 товаров
- Показываем все 47 на /category/
- Пользователь фильтрует через CTRL+F
- Или JavaScript-фильтрация (без изменения URL)

Просто. Без дублей.
Все товары на одной индексируемой странице.

8/ Мониторинг faceted navigation

Проверяйте каждый месяц:

□ Google Search Console → Coverage
□ Сколько URL в индексе?
□ Должно быть: категории + только ценные фильтры

□ Site: http://example.com
□ Сколько URL с параметрами в индексе?

□ Crawl через Screaming Frog
□ Сколько уникальных комбинаций параметров?

У клиента количество индексируемых страниц фильтров упало с 89K до 200.
Трафик ВЫРОС на 67%.

Меньше = лучше.

@WebDev_Plus
3
This media is not supported in your browser
VIEW IN TELEGRAM
Чувак собрал полноценный эмулятор x86 CPU на CSS (без JavaScript).

Ты можешь писать программы на C, компилировать их в x86-машинный код через GCC и запускать прямо внутри CSS.

https://lyra.horse/x86css/

@WebDev_Plus
🔥1
Я до сих пор считаю, что это одна из лучших фич, которые современный CSS нам дал!

Кто знает, что значит only?

@WebDev_Plus
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Быстрый способ улучшить поведение текста в приложении — использовать text-wrap: balance. Это свойство равномерно распределяет текст по строкам, избегая "висячих" слов

Поддержка ограничена небольшим количеством строк (примерно <6–10 в зависимости от браузера), поэтому лучше всего применять его для заголовков или коротких абзацев

@WebDev_Plus
3
Знакомьтесь: abs() в CSS

Функция abs() возвращает абсолютное значение вычисления, то есть делает число, длину или процент всегда положительными. Полезно для более безопасной вёрстки и предсказуемого визуала.

Подробнее здесь ↓
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/abs

@WebDev_Plus
HTML-совет

Тег <abbr> используют, чтобы пометить аббревиатуру или акроним (сокращение) от фразы или длинного слова.

Он улучшает доступность и понимание: можно дать расшифровку, которая появится при наведении.

Обычно <abbr> используют вместе с атрибутом title. Значение title показывается как подсказка, когда пользователь наводит курсор на содержимое <abbr>.

В этом примере:

WWW это сокращение от World Wide Web.
Когда пользователь наведёт на WWW, появится тултип с полной расшифровкой World Wide Web.

Зачем использовать <abbr>?

Доступность: скринридеры могут озвучивать полную форму, когда пользователь фокусируется на сокращении. Это помогает людям с нарушениями зрения.
Удобство: пользователь быстро видит смысл термина, не уходя со страницы и не ломая поток чтения.

@WebDev_Plus
👍2
Laravel Tip

Найди запросы, которые выполняются слишком долго. Это легко логировать с помощью:

@WebDev_Plus
SSR vs CSR vs SSG

Представь собес по вебу. Тебя спрашивают: в чем разница между SSR, CSR и SSG?

Это три стратегии рендера UI. Если выбрать не ту, можно легко просесть по скорости и SEO.

▪️SSR (Server Side Rendering)

Пользователь запрашивает страницу, сервер подтягивает данные, собирает HTML, подключает стили и отдаёт уже готовую разметку в браузер. Потом на клиенте подгружается JS и “оживляет” страницу, это называется hydration.

Плюсы:

▪️Хорошее SEO
▪️Контент появляется быстрее

Минусы:

▪️Интерактивность не мгновенная, пока hydration не отработает

Лучше всего для:

▪️блоги, новости, e-commerce
▪️всё, где важны SEO и свежие данные

CSR (Client Side Rendering)

Пользователь запрашивает страницу, сервер отдаёт пустой HTML плюс ссылки на JS/CSS. Дальше браузер загружает бандлы, JS строит страницу и накатывает стили.

Плюсы:

▪️После загрузки супер-интерактивно

Минусы:

▪️Плохое SEO (до выполнения JS страница фактически пустая)
▪️Медленный first paint/первый контент, особенно на слабых устройствах

Лучше всего для:

▪️дашборды, SaaS, внутренние панели
▪️всё за логином, где SEO не важно

SSG (Static Site Generation)

HTML генерируется заранее на этапе сборки/деплоя. Когда пользователь запрашивает страницу, сервер просто отдаёт готовый HTML файл. Никаких вычислений “на лету”.

Плюсы:

▪️Самый быстрый рендер
▪️Отличное SEO

Минусы:

▪️Плохо подходит для динамического контента или часто меняющихся данных

Лучше всего для:

▪️портфолио, документация, лендинги
▪️контент, который редко обновляется

В одну строку

▪️SSR: собирается на сервере на каждый запрос
▪️CSR: собирается в браузере после загрузки JS
▪️SSG: собирается при билде и отдается мгновенно

@WebDev_Plus
Please open Telegram to view this post
VIEW IN TELEGRAM
👍82
TypeScript сужает тебе выбор на основе того, что ты уже выбрал, и делает это по группам.

@WebDev_Plus
Как нормально организовать папки в коде?

Не важно, используешь ты React, Vue, Angular или просто TypeScript

3 самые типичные варианты ↓

@WebDev_Plus
This media is not supported in your browser
VIEW IN TELEGRAM
CSS-совет:

Используй логические свойства вроде margin-inline-start и text-align: start, чтобы верстка автоматически подстраивалась под любое направление письма.

@WebDev_Plus
This media is not supported in your browser
VIEW IN TELEGRAM
tabular-nums должно быть дефолтом для любых чисел, которые обновляются (таймеры, счетчики, цены, проценты, счёт, live-данные и т.д.).

Включить OpenType-фичу tnum можно через CSS-свойство font-variant-numeric.

.tabular-nums {
font-variant-numeric: tabular-nums;
}


@WebDev_Plus
👍1
Laravel Tip

Когда нужно обновить запись, но не трогать колонку updated_at, используй updateQuietly().

Без таймстампов. Без событий. Тихое, чистое обновление, когда оно реально нужно.

@WebDev_Plus
Если ты веб-разработчик и используешь ИИ, поставь это!

Agent Skills от Addy Osmani (Google) для:

* Web Performance
* best practices
* доступности (a11y)
* технического SEO

Под React, Vue, Angular или что угодно.

npx add-skill addyosmani/web-quality-skills


Вот какие skills поставятся:

* web-quality-audit - полный аудит в стиле Lighthouse
* performance - загрузка и оптимизация
* core-web-vitals - LCP, INP, CLS
* accessibility - WCAG и навигация с клавиатуры
* seo - meta-теги и структура
* best-practices - безопасность и стандарты

@WebDev_Plus
4
This media is not supported in your browser
VIEW IN TELEGRAM
autofill у инпутов по умолчанию выглядит стремно: эта заливка фона ломает аккуратные дизайн-системы, особенно в темной теме.

Пофиксил чисто CSS-хакам через inset-shadow:

autofill:shadow-[inset_0_0_0px_1000px_var(--color-background)]

Чтобы принудительно поставить нужный фон и убрать нативный синий.

https://micro.bossadizenith.me/writing/taming-chromes-autofill

@WebDev_Plus
👍4
Angular совет дня: твое приложение ходит в несколько API, но интерсепторы не могут понять, к какому из них относится запрос!?

Оберни. Отфильтруй. Готово

@WebDev_Plus
👍1
Это самый простой способ переключаться между режимами Dark, Light и System.

Просто добавьте элемент с выбранным режимом data-theme или удалите его из DOM, чтобы переключиться на System mode.

Может, это и не идеальный вариант, но это самый быстрый и простой способ!

@WebDev_Plus
Модалки бесят.

Хочешь, чтобы они бесили чуть меньше?

Используй overscroll-behavior: contain;

Что это делает:

Ты скроллишь модалку, доходишь до её конца и продолжаешь крутить дальше.

И тут бах, начинает скроллиться страница под ней. Модалка всё ещё открыта, но позиция на странице сзади уже уехала.

Это называется scroll chaining. Это свойство как раз это и останавливает.

Как это работает:

Когда пользователь доходит до конца прокручиваемого элемента, а модалки для этого вообще идеальный кейс, скролл просто останавливается. Он не продолжает передаваться родителю по цепочке.

На мобилках заодно не триггерит pull-to-refresh.

Где использовать:

• модалки и диалоги
• сайдбары и навигационные меню
• фиксированные контейнеры с overflow: scroll
• мобильные карусели

Поддержка браузеров: 95%

Одна строка CSS.

Модалки всё ещё бесят, но уже чуть меньше 😄

@WebDev_Plus
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
JavaScript использует лексическую область видимости.

Но знаешь ли ты, что такое lexical scope?

Лексическая область видимости означает, что область видимости переменной определяется тем, где она написана в коде, а не тем, откуда её вызвали.

Пример:

function outer() {
let x = 10;

function inner() {
console.log(x); // может обратиться к x из outer
}

inner();
}
outer();


Здесь inner() может получить доступ к x, потому что функция была объявлена внутри outer().

Это и есть lexical scope: функция как бы "помнит" окружение, в котором была создана.

Ключевые моменты:

* лексическая область видимости статическая, то есть фиксируется в момент определения кода
* внутренние функции могут обращаться к переменным из внешних областей видимости
* это фундамент, на котором в JavaScript построены closures

@WebDev_Plus
Хватит писать reduce() просто ради того, чтобы сгруппировать массив

Object.groupBy() уже работает во всех основных браузерах и позволяет группировать элементы массива по любому ключу в одну строку.

Чисто, читаемо, без зависимостей.

Подробнее 👇
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy

@WebDev_Plus
3👍2