схема полей для фасетного поиска, фильтра в интернет-магазине / Хабр | Веб-студия Nat.od.ua
схема полей для фасетного поиска, фильтра в интернет-магазине / Хабр
В этой статье я опущу такие подробности работы с Elasticsearch (далее по тексту просто ES), таких как:
Как установить
Как подключаться
Раскрывать полную схему mapping для товара интернет-магазина
Подробное описание всей структуры и всех запросов для получения страницы товаров с результатами поиска и фильтром.
И что-либо еще.
Здесь, как и написано в заголовке, лишь постараюсь описать схему только для полей характеристик товара и как для них делать запросы агрегации и фильтрации.
Предисловие
К написанию статьи пришел после неудачного опыта разработки интернет-магазина на фреймворке и MySQL с десятками тысяч товаров, которые в свою очередь имели несколько десятков характеристик и множество значений для них. Из-за множества запросов для получения значений фильтра товаров и, возможно, абсолютно неправильного структурирования таблиц или по какой-либо другой причине, сайт ужасно тормозил и долго загружался. Дошло до того, что в вебмастере яндекса получал подобную ошибку:
Скрин из интернета.
Сайт разрабатывал не я. Разбираться с ним в дальнейшем не было ни знаний, ни желания. Решил, что впоследствии буду самостоятельно разрабатывать интернет-магазин, но используя другое и нереляционное хранилище данных, а не Mysql. Выбор пал на ES и при изучении понимание структурирования характеристик товаров и получение для них значений, которые впоследствии безболезненно и не затрагивая код можно было бы менять, отняло много времени. Лично мне очень не хватало в русскоязычном интернете абсолютно простых примеров, какие есть, например, для PHP+Mysql.
Все описанное, лишь основано на моем личном опыте и понимании схемы и структуры документов, ориентированной на использовании для построения фасетного поиска в интернет-магазине к которому я пришел при изучении и разработке. Т.е статья рассчитана больше на новичков, которые начали изучать ES.
По сути дела
Elasticsearch – это распределенный поисковый и аналитический движок на базе Apache Lucene. Полностью с описанием можно ознакомиться на официальном сайте.
Фасетный поиск (фасетная навигация) – поиск товара в разделе, категории или же на странице полнотекстового поиска по характеристикам: цвет, материал, цена, производитель и т.д. Для конечного пользователя – набор фильтров. Каждый фильтр – характеристика. Значения этого фильтра – все возможные значения характеристики. Для интернет-магазина это основная функция поиска, и пользователи ожидают, что она будет работать достаточно быстро.
В приведенном ниже примере пользователь находится в категории “люстры” и отфильтровал дополнительно товары в диапазоне цен от 1394 до 42207 руб. и с цветом черный. Было найдено 198 товаров, а на панели фильтров слева перечислены те характеристики, которые содержатся в результатах поиска, а также количество доступных значений, имеющих этот атрибут (количество фасетов):
Для создания фасетного поиска в ES достаточно мощный инструмент агрегирования. Одной из приятных особенностей агрегации является то, что они могут быть вложенными — другими словами, можно определить агрегации верхнего уровня, которые создают «корзины» (buckets) документов и другие агрегации, которые выполняются внутри этих корзин. Для упрощения понимания, это в целом похоже на команду SQL GROUP_BY. На основе фильтров обобщаются, группируются документы по какому-то определенному признаку.
Индексирование значений фасета
Перед созданием агрегатов атрибуты документа, которые могут служить фасетами, необходимо проиндексировать в ES. Один из способов индексировать их — перечислить все атрибуты и их значения в одном поле, как в следующем примере:
“facets”: {
“color”: “Черный”,
“style”: “Лофт”,
“room”: “Гостиная”,
}
Mapping ES при этом должен выглядеть так:
“facets”: {
“type”: “nested”,
“properties”: {
“color”: {
“type”: “keyword”,
},
“style”: {
“type”: “keyword”,
}
“room”: {
“type”: “keyword”,
}
}
}
Такой подход может подойти, но для фасетирования в таком случае в запросах придется явно перечислять все имена полей, для которых мы хотим создать агрегацию.
“aggs”: {
“facets”: {
“nested”: {
“path”: “facets”
},
“aggs”: {
“color”: {
“terms”: {
“field”: “facets.color”
}
},
“style”: {
“terms”: {
“field”: “facets.style”
}
},
“room”: {
“terms”: {
“field”: “facets.room”
}
},
}
}
}
Очевидно, что это не очень практично и эффективно при большом количестве характеристик товаров, которые со временем могут изменяться, дополняться. И, например, при удалении, изменении или добавлении новой характеристики товара придется вручную изменить mapping, переиндексировать и изменить запрос, добавив в него новое имя поля.
Вместо этого я пришел к следующему
Разделил имена и значения фасетов, отправляемых в индекс эластика, следующим образом:
“string_facets”: {
{
“name”: “color”,
“value”: “Черный”
},
{
“name”: “color”,
“value”: “Белый”
},
{
“name”: “style”,
“value”: “Лофт”
},
{
“name”: “style”,
“value”: “Техно”
},
{
“name”: “room”,
“value”: “Гостиная”
},
{
“name”: “room”,
“value”: “Спальня”
}
}
Mapping:
“string_facets”: {
“type”: “nested”,
“properties”: {
“name”: {
“type”: “keyword”,
},
“value”: {
“type”: “keyword”,
}
}
Для фильтрации и агрегирования такой структуры требуются вложенные фильтры и вложенные агрегации в запросах.
Агрегация:
“aggs”: {
“aggs_text_facets”: {
“nested”: {
“path”: “string_facets”
},
“aggs”: {
“name”: {
“terms”: {
“field”: “string_facets.name”
},
“aggs”: {
“value”: {
“terms”: {
“field”: “string_facets.value”
}
}
}
}
}
}
}
Фильтрация:
“filter”: {
“nested”: {
“path”: “string_facets”,
“filter”: {
“bool”: {
“must”: {
{
“term”: {
“string_facets.name”: “color”
}
},
{
“terms”: {
“string_facets.value”: {
“Черный”
}
}
}
}
}
}
}
}
Это касается характеристик, у которых значения текстовые. Характеристики с числовыми значениями необходимо хранить и анализировать отдельно. Это связано с тем, что числовые характеристики (например, размеры: ширина, длина) иногда имеют огромное количество различных значений. И вместо того, чтобы перечислять все возможные значения, достаточно просто получить минимальное и максимальное значения и отобразить их в виде селектора диапазона или ползунка. Это возможно, только если значения хранятся в виде чисел.
В mapping это будет выглядеть следующим образом:
“number_facets”: {
“type”: “nested”,
“properties”: {
“name”: {
“type”: “keyword”,
},
“value”: {
“type”: “double”,
}
}
Агрегация:
“aggs_number_facet”: {
“nested”: {
“path”: “number_facets”
},
“aggs”: {
“name”: {
“terms”: {
“field”: “number_facets.name”
},
“aggs”: {
“value”: {
“stats”: {
“field”: “number_facets.value”
}
}
}
}
}
}
При таком подходе отпадает необходимость знать список доступных характеристик во время запроса. Также в любой момент можно просто изменить данные в индексе, удалив или изменив нужные характеристики, не затрагивая маппинг и запросы.
P.S. Организовав таким образом схему документов и прописав все необходимые запросы, я столкнулся с еще одной проблемой. При фильтрации оставлялись только товары с выбранным значением в фильтре товаров, соответственно нельзя было выбрать несколько значений одного и того же фильтра, что в моем случае влияло на удобство для пользователей. Для описания решения проблемы требуется отдельная статья.
8 инструментов, которые помогли увеличить конверсию сайта на 147% и получать заявки на протезирование зубов по 157 руб | Веб-студия Nat.od.ua
8 инструментов, которые помогли увеличить конверсию сайта на 147% и получать заявки на протезирование зубов по 157 руб
Сайт по стоматологии с конверсией 7,4% и заявками по 157 руб.
Для разработки сайта по стоматологии использовали методику с упором на маркетинг: конверсия выросла на 147%, стоимость заявки снизилась на 55%. Рассказываю, какие 9 базовых инструментов помогают нам достигать таких результатов регулярно.
Кратко о проекте и задаче
Задача: разработать сайт для услуг «Протезирование зубов»
Конверсия старого сайта – 3%. Стоимость заявки – 328 руб.
Результаты запуска
Новый лендинг показал конверсию 7,4% (+147%), стоимость заявки – 157 руб. (-55%)
Конверсия сайта увеличилась на 147%, стоимость заявки снизилась на 55%
8 базовых инструментов, чтобы увеличить конверсию на 147% и получать заявки по 157 руб.
Достичь такого результата помогли:
Первый экран
Смысловые заголовки
Маркетинговое исследование
Поп-ап окна
Картинки + текст – единый смысл
Грамотные акценты
Лид-формы, квиз
Кейсы, примеры работ
Ниже подробнее про каждый из инструментов.
1. Первый экран
Мы всегда уделяем проработке первого экрана тщательное внимание. Если не удастся зацепить внимание пользователя в первые секунды, то в 80% случаев он уйдет искать решение к конкурентам.
На первый экран выносим:
конкурентные преимущества;
яркие выгоды;
критерии, на основе которых ЦА выбирает стоматологию;
в подзаголовке можно показать, что мы понимаем потребности ЦА и готовы их решить.
На первом экране показали яркие выгоды и конкурентные преимущества
После маркетингового анализа выяснили, что предложение нашего клиента – одно из лучших в регионе. Кроме того, цена – один их главных критериев выбора. Об этом и рассказали на первом экране.
2. Смысловые заголовки
При разработке сайтов никогда не используем стандартные заголовки «О нас», «5 причин обратиться к нам», «О компании» и т.д. Вместо этого через заголовки:
раскрываем выгоды;
закрываем страхи и возражения;
отвечаем на распространенные вопросы ЦА;
вызываем доверие к компании;
доказываем экспертность врачей.
Вместо стандартного «Этапы работ» говорим через заголовок, что восстановим зубы за 2-3 визита
О том, как сильно заголовки влияют на конверсию, рассказывала в видео.
Для чего это нужно? Когда посетитель скроллит сайт, он выхватывает взглядом заголовки, иллюстрации и другие яркие, крупные элементы. И уже тогда через смысловые заголовки понимает, почему надо купить здесь. Это увеличивает вероятность, что пользователь заинтересуется услугой, останется изучать сайт дальше и совершит целевое действие.
Шаблонные заголовки не несут смысловой нагрузки. Они не рассказывают о конкурентных преимуществах, не доказывают экспертность врачей. А значит, сайт с меньшей вероятностью заинтересует читателя.
3. Маркетинговое исследование
На этапе маркетингового исследования провели анализ ЦА, конкурентов и рынка. Выяснили:
ожидание ЦА;
страхи и возражения ЦА;
на основании каких параметров выбирают стоматологию для протезирования;
как можно превзойти ожидания ЦА;
какие вопросы задают пациенты по телефону и на первой консультации у врача;
в чем стоматология нашего клиента лучше и хуже других клиник в своем регионе и т.д.
Кусочек анализа ЦА
Уже на этом этапе прописываем маркетинговые смыслы: как закрывать страхи и возражения клиентов, отвечать на распространенные вопросы и пр. Их можно и нужно использовать не только на сайте, но и в других каналах, где происходит общение с ЦА (скрипты продаж, социальные сети, видео и пр.). Маркетинговые смыслы помогают «прогревать» пользователей и получать «теплых» клиентов.
Рассказываем ЦА: помощью трехмерного моделирования получаем протезы, которые внешне и по ощущениям, как свои настоящие зубы
Чтобы собрать объективную картину про ЦА, исследуем порядка 12-15 источников информации.
В ходе маркетингового анализа изучаем 12-15 источников информации
Приглашаем на первый созвон сотрудников разного звена. В этом проекте на брифе были опрошены:
4. Поп-ап (pop-up) окна
Мы используем два вида pop-up окон для увеличения конверсии:
На входе и выходе
Exit pop-up окно – один из инструментов для получения мощного конверсионного слоя
2. Информационные поп-ап окна. На сайт заходят клиенты, которые в разной степени осведомлены о протезировании зубов. Кто-то уже хорошо изучил эту тему, а кто-то еще только начинает. Для второй категории читателей мы через поп-ап окна отвечаем на информационные запросы: например, как часто менять протезы; для чего нужна КТ-диагностика и пр.
Если этой информации не будет на нашем сайте, пользователь пойдет искать ее в других источниках – вполне возможно, на сайты конкурентов. А если он закроет наш сайт, то вряд ли вернется снова. Поэтому мы стараемся давать ответы на самые распространенные вопросы в виде поп-ап окон. Информация на сайте есть, но страница не перегружена текстом.
5. Картинки + текст – единый смысл
Подбираем иллюстрации, чтобы они:
вызывали интерес и обращали внимание на текст;
усиливали текст;
несли единый маркетинговый смысл с текстом.
Заголовок «Форма и размер идеально подходят» – доказываем слова соответствующим изображением
6. Грамотные акценты
С помощью визуального слоя и дизайна расставляем акценты:
направляем внимание читателя на конкурентные преимущества, выгоды, закрытие страхов и возражений;
сокращаем количество текста, доносим информацию с помощью инфографики и мокапов. Никто не будет читать полотно текста
Мокап показывает, из чего складывается стоимость лечения
Закрываем страх клиента (протезирование – это больно) и визуально выделяем эту информацию
7. Квиз и лид-формы
Чтобы зацепить внимание посетителей сайта использовали разные лид-формы:
стандартные;
интерактивные (со схемой, на которой можно выбрать больные или отсутствующие зубы)
викторину с бонусами «Угадайте, где настоящие зубы, а где протезы»
квиз.
8. Кейсы и примеры работ
Выбрали самые яркие кейсы. Показали на сайте разные виды работ – сложные, уникальные и стандартные, чтобы каждый смог найти свой случай и понять, что в этой стоматологии действительно могут решить его проблему.
Показали, как решили сложный случай
Еще больше подробностей о создании этого сайта в видео
JavaScript. Работа с буфером, Ctrl+C Ctrl+V / Хабр | Веб-студия Nat.od.ua
JavaScript. Работа с буфером, Ctrl+C Ctrl+V / Хабр
Как копировать в буфер картинки. Какие типы данных можно класть в буфер. Поддержка кастомных типов. Как сделать свои кнопки копировать/вставить.
Рис 1. Копирование между вкладками редактора блок-схем и Google Docs
Задача
Сделать копирование для редактора блок-схем dgrm.net.
Копировать можно между вкладками.
Можно копировать в Word/Google docs, тогда схема вставляется как картинка.
Должны работать горячие клавиши Ctrl+C, Ctrl+V, Ctrl+X.
Свои кнопки копировать/вставить, чтобы можно было копировать мышкой.
Поддержка мобильных.
Варианты API работы с буферомdocument.execCommand(‘copy’) не работает
Это API устарело и не работает. Не пытайтесь с его помощью обойти ограничения других API.
Работа с буфером в обработчиках событий ‘copy’, ‘paste’, ‘cut’ document.addEventListener(‘copy’, evt => {
evt.preventDefault();
evt.clipboardData.setData(‘text/plain’, ‘text to clipboard’);
});
Листинг 1. Пишем в буфер на событии “вставить”
В этом варианте нет возможности сделать свою кнопку “копировать”, пользователь должен нажать Ctrl+C.
navigator.clipboard.read/wrightbtn.addEventListener(‘click’, async _ =>
await navigator.clipboard.writeText(‘text to clipboard’)
);
Листинг 2. Пишем в буфер по клику на кнопке
Можно сделать свою кнопку “копировать”. Работает во всех браузерах и на мобильных.
В Safari есть ограничение: нельзя использовать в callback-ах. Так в Safari не работает:
btn.addEventListener(‘click’, async _ =>
// create png from svg
svgToPng(
svg,
// callback
async png => await navigator.clipboard.write(…))
);
Листинг 3. Не работает в Safari. Нельзя использовать navigator.clipboard в callback-ах. Как писать картинку в буфер в следующем разделе.
Это ограничение безопасности: когда придет callback не понятно, пользователь может уже и передумал копировать.
Можно сделать так: строку гарантированно пишем в буфер, если браузер разрешит запишем картинку.
// guaranteed clipboard write
await navigator.clipboard.writeText(‘text to clipboard’);
// try to write img
// if ok -> clipboard will be overwritten
try {
// create png from svg
svgToPng(
svg,
// callback
async png => await navigator.clipboard.write(…));
} catch { }
Листинг 4. Запись текста в буфер гарантирована, если браузер разрешит запишем картинку
Как записать картинку в буферawait navigator.clipboard.write(, { type: ‘text/plain’ }))
})]);
Листинг 5. Запись картинки и альтернативного текста в буфер.
В буфер можно записать одновременно несколько типов данных. Например, картинку и текст. Если вставить в Word – вставится картинка, если в блокнот – текст.
Можно записывать такие типы:
text/plain
text/html
image/png
Некоторые браузеры поддерживают больше типов. Эти три работают везде.
Копировать в буфер можно только png. Другие форматы картинок не поддерживаются.
При копировании браузер “очищает” png. Для безопасности браузер удаляет из png метаданные.
Неприятность для dgrm.net. Dgrm.net хранит в метаданных описание схемы. Благодаря метаданным можно открыть картинку на редактирование – рис 2.
Рис 2. dgrm.net умеет открывать схемы из PNG картинок
Кастомные типы данных в буфере
‘text/plain’ из буфера можно вставить куда угодно. Хорошо использовать свой тип данных, который читает только ваше приложение. Например ‘text/dgrm’.
Для безопасности браузер связывает самодельный тип с доменом. Таким образом посторонний сайт не прочитает из буфера ваш тип данных.
Не все браузеры поддерживают самодельные типы. В Chrome можно использовать кастомные типы, они обязательно должны иметь префикс ‘web ’ -> ‘web text/dgrm’.
Не все браузеры позволяют записать не ‘text/plain’ в буфер с помощью navigator.clipboard.write. Разрешают только в обработчиках событий ‘copy’, ‘cut’. Т.е. свою кнопку “копировать” нельзя сделать.
В итоге остановился на navigator.clipboard.writeText который везде работает.
Чтение из буфера
Чтение буфера еще опаснее чем запись. Еще больше ограничений. В FireFox читать можно только в обработчике события ‘paste’. Свою кнопку “вставить” сделать нельзя, нужно чтобы пользователь нажал Ctrl V.
document.addEventListener(‘paste’, evt => {
const txt = evt.clipboardData.getData(‘text/plain’);
});
Листинг 6. Чтение из буфера на событии ‘paste’
В других браузерах можно использовать navigator.clipboard API.
btn.addEventListener(‘click’, async _ =>
await navigator.clipboard.readText()
);
Листинг 7. Чтение из буфера по кнопке
Браузер запросит разрешение пользователя. iOS Safari будет спрашивать при каждом вызове navigator.clipboard.readText.
О редакторе dgrm.net
Dgrm.net – быстрый редактор без лишних кнопок.
Развиваю редактор. Анонсы обновлений начал писать в телеграм.
Попробуйте, напишите что нравится/не нравится. Все читаю, веду список предложений.
Как быстро увеличить конверсию сайта в 7 раз. Изменили заголовки и удалили клише – количество заявок выросло на 518% | Веб-студия Nat.od.ua
Как быстро увеличить конверсию сайта в 7 раз. Изменили заголовки и удалили клише – количество заявок выросло на 518%
Изменили в лендинге шаблонные фразы, клише и воду на цифры, примеры, доказательства. Конверсия лендинга выросла на 518%.
Привет! Меня зовут Евгения Корюкова. Я руководитель студии MuscleLend. Мы провели эксперимент и доказали, что продающая структура лендинга – это не только последовательность блоков, но и грамотно выбранные заголовки. Через заголовки и подзаголовки, не читая другой текст, посетитель должен понять «Что здесь продают? Почему это надо купить здесь и сейчас?»
Задачи эксперимента, что сделано
Мы решили проверить, влияет ли на конверсию подача заголовков и остального текста, а также последовательность экранов.
Наша гипотеза заключалась в следующем. Когда человек заходит на сайт, он не читает его внимательно. Он скроллит его взглядом и выхватывает только то, что выделено крупным, полужирным или цветным шрифтом. А это заголовки. Почему бы через них не рассказать о выгодах товара, не закрыть страхи и возражения клиента? Тогда, возможно, мы сможем заинтересовать посетителя в первые секунды, и он останется изучать сайт дальше. А в дальнейшем оставит заявку и купит товар
Для проверки гипотез мы разработали три лендинга для некого инструктора тренажерного зала. На сайте клинты могли оставить заявку и получить бесплатную программу тренировок и питания – одну из четырех в зависимости от целей:
для избавления от лишнего веса;
для роста мышечной массы;
для улучшения выносливости;
для улучшения растяжки.
На лендинг №2 и №3 были внесены такие изменения, которые позволяли проверить, насколько верны гипотезы:
Смысловая составляющая и текст на сайте – одни из главных элементов, которые значительно влияют на конверсию сайта.
Посетители изучают содержимое, в первую очередь, по заголовкам и подзаголовкам. Поэтому в них нужно вынести не общие фразы, а смыслы, выгоды, особенности.
Последовательность расположения информации влияет на эффективность сайта.
Над дизайном не запаривались и взяли стандартный шаблон Tilda. Все фотографии на сайте были стоковые. Наша задача была проверить влияние маркетинговой составляющей на конверсию.
Чем лендинги отличаются друг от друга
В лендинги мы вносили изменения с учетом тех гипотез, которые хотели проверить. Отличия были в смысловой составляющей и в последовательности блоков.
Лендинг №1
За основу взяли шаблон Tilda. Основные особенности:
«Пустые» заголовки и подзаголовки («Обо мне», «Результаты подопечных» и т.п.).
Много воды и общих фраз, которые не несут конкретной информации.
Стандартная структура на основе шаблона.
Посмотрите видео – там подробно рассказала и показала, как выглядит первый лендинг. Это займет не больше 1 мин.
Таких лендингов в интернете встречается 80-90%. Их создают владельцы бизнеса самостоятельно на основе шаблона Tilda или находят универсальных специалистов, которые делают сайт «под ключ» за 5-10 тыс. руб.
Лендинг №2
Изменения коснулись заголовка и текста:
Заголовки со смыслами, которые должны зацепить внимание посетителей сайта
Выделены выгоды – другим цветом или полужирным шрифтом
Добавлено больше конкретики – цифры, факты, доказательства
Посмотрите видео – там подробно рассказала и показала, какие изменения внесли на второй лендинг. Это займет не больше 2 мин.
Лендинг №3
Изменения внесены в заголовки, текст и последовательность расположения экранов:
На первом экране появилось больше выгод, расставлены акценты
В призыв к действию добавлен элемент срочности «Успейте бесплатно получить программу до 8 августа»
Добавлена вторая полная форма заявки – сразу после второго экрана с отзывами
Последовательность блоков изменилась – на первом экране обозначены основные выгоды и преимущества, а на втором – результаты клиентов. Это то, что интересует целевую аудиторию в первую очередь.
Посмотрите видео – там подробно рассказала и показала, какие изменения внесли на лендинг №3. Это займет не больше 1 мин.
Запустили рекламу в Яндексе
На каждый лендинг запустили рекламную кампанию. Чтобы погрешность в результатах была минимальной, во всех трех компаниях одинаково настроены:
параметры ЦА (целевой аудитории, потенциальных клиентов);
время и регион показов;
изображения;
заголовок и текст объявления.
Один из трех вариантов рекламного объявления
Реклама крутилась неделю. Все посетители сайта, которые оставили заявку, получили письмо, что стали участниками эксперимента и небольшой чек-лист с рекомендациями по питанию и тренировкам в качестве благодарности и компенсации за потерянное время.
Результаты эксперимента
Конверсия лендинга №1 – 3,45% (менее 4 человек из 100 посетителей оставили заявку)
Конверсия лендинга №2 – 20,73% (20 человек из 100 посетителей оставили заявку)
Конверсия лендинга №3 – 21,35% (21 человек из 100 посетителей оставил заявку)
Конверсия лендинга №2 выросла на 500%, лендинга №3 на 518%
Заключение
Наша гипотеза подтвердилась: клише и шаблонные фразы существенно снижают конверсию. Если у вас на сайте встречаются такие заголовки, как «О нас», «Наши преимущества», «Кейсы/портфолио/отзывы», «Почему надо купить у нас», «Команда профессионалов / богатый опыт» и др., подумайте над тем, чтобы заменить их на конкретику – цифры, факты, доказательства.
Формат имён в коде / Хабр | Веб-студия Nat.od.ua
Формат имён в коде / Хабр
Здравствуйте, меня зовут Дмитрий Карловский и я.. изобрёл $mol только для того, чтобы ваши глаза кровоточили, глядя в его код. Во всяком случае, такое ощущение может сложиться, если почитать разного рода околоJSНые чаты, но не обращаться к первоисточникам, где все технические решения вытекают из чисто прагматических рассуждений. Один из таких анализов позвольте представить вашему вниманию.
Способы записи camelCase
Традиционно используются в именах переменных и полей во многих современных языках.
❌ Требуется много нажатий шифта вовремя.
❌ слипшиесяСловаТрудноЧитать.
❌ Проблемы с аббревиатурами: sdpFmtpLine, encodeURICoponent.
❌ Имеет проблемы с наложением стилей в CSS (в зависимости от типа элемента и типа селектора стиль может не примениться).
PascalCase
Традиционно используются для имён классов и глобальных неймспейсов.
❌ Требуется много нажатий шифта вовремя.
❌ СлипшиесяСловаТрудноЧитать.
❌ Проблемы с аббревиатурами: XMLHttpRequest, HTMLBRElement, IDBOpenDBRequest, RTCDTMFSender.
❌ Одноимённые имена файлов могут вызвать проблемы в не чувствительных к регистру файловых системах.
❌ Проблемы с наложением стилей в CSS (в зависимости от типа элемента и типа селектора стиль может не примениться).
lowercase
Традиционно используется для имён нативных событий в браузере.
❌ слипшиесясловатрудночитать.
❌ проблемы с аббревиатурами: onicegatheringstatechange.
UPPERCASE
Традиционно используется для cтандартных элементов в некоторых DOM-API (tagName, например)..
❌ СЛИПШИЕСЯСЛОВАТРУДНОЧИТАТЬ.
❌ Требует временного включения caps lock при вводе или зажатия шифта.
❌ проблемы с аббревиатурами: BGSOUND.
❌ Текст с малым числом выносных элементов сложно воспринимать: FIGCAPTION.
❌ Одноимённые имена файлов могут вызвать проблемы не чувствительных к регистру файловых системах.
❌ Имеет проблемы с наложением стилей в CSS (в зависимости от типа элемента и типа селектора стиль может не примениться).
kebab-case
Традиционно используются для имён в HTML, CSS, Lisp, а также в именах файлов.
❌ Редакторы не считают эти имена единым именем (выделение даблкликом, ctrl+стрелка и тп).
❌ Не допустимо в большинстве языков программирования.
❌ Имя получается на несколько символов длиннее.
❌ Лишние символы ломают Fuzzy Search в IDE/DevTools, так как они не встречаются в пути.
SHAWERMA-CASE
Традиционно используются для имён нестандартных элементов в некоторых DOM-API (tagName, например).
❌ Редакторы не считают эти имена единым именем (выделение даблкликом, ctrl+стрелка и тп).
❌ Не допустимо в большинстве языков программирования.
❌ Требует временного включения caps lock при вводе.
❌ Имя получается на несколько символов длиннее.
❌ Текст с малым числом выносных элементов сложно воспринимать: ACME-TOOLBAR-DROPDOWN.
❌ Лишние символы ломают Fuzzy Search в IDE/DevTools, так как они не встречаются в пути.
❌ Одноимённые имена файлов могут вызвать проблемы не чувствительных к регистру файловых системах.
❌ Имеет проблемы с наложением стилей в CSS (в зависимости от типа элемента и типа селектора стиль может не примениться).
snake_case
Традиционно используются в “олдскульных” языках (C, C++, Rust, Erlang, OCaml) и языках с упором на читаемость (Ruby, Python) для локальных имён и имён полей.
❌ требуется_много_нажатий_шифта.
❌ Имя получается на несколько символов длиннее.
❌ Лишние символы ломают Fuzzy Search в IDE/DevTools, так как они не встречаются в пути.
Cobra_case
❌ Требуется_много_нажатий_шифта.
❌ Имя получается на несколько символов длиннее.
❌ Лишние символы ломают Fuzzy Search в IDE/DevTools, так как они не встречаются в пути.
❌ Одноимённые имена файлов могут вызвать проблемы не чувствительных к регистру файловых системах.
❌ Имеет проблемы с наложением стилей в CSS (в зависимости от типа элемента и типа селектора стиль может не примениться).
SCREAM_CASE
Традиционно используется для констант.
❌ Требует зажатия шифта при вводе.
❌ Имя получается на несколько символов длиннее.
❌ Текст с малым числом выносных элементов сложно воспринимать: SVG_MORPHOLOGY_OPERATOR_UNKNOWN.
❌ Лишние символы ломают Fuzzy Search в IDE/DevTools, так как они не встречаются в пути.
❌ Одноимённые имена файлов могут вызвать проблемы не чувствительных к регистру файловых системах.
❌ Имеет проблемы с наложением стилей в CSS (в зависимости от типа элемента и типа селектора стиль может не примениться).
Смешение стилей
Традиционно проявляется при попытке использовать традиционное именование для каждого языка по отдельности. В разных местах одна и та же сущность имеет разное форматирование имени.
❌ Требуется дополнительное ментальное напряжение на ассоциацию и конвертацию разных форматов одного имени.
❌ Тут и там необходимы конвертации между стилями написания.
❌ Не везде возможна автоконвертация. Например в TypeScript на уровне типов такое затруднительно.
❌ Поиск всех вхождений одного имени в проекте приходится повторять для каждой формы написания.
❌ Суммирует недостатки всех употребляемых стилей.
Нативные API
Web API развивались стихийно, так что не стоит удивляться необоснованному разнообразию форматов имён в разных местах:
Отдельно стоит отметить смешение стилей, ведь одна и та же сущность может именоваться по разному в разных языках:
Имена стандартных элементов:
Имена нестандартных элементов:
Имена атрибутов:
JS: camelCase, lowercase
HTML: kebab‑case, lowercase
CSS: kebab‑case, lowercase
Имена CSS‑классов:
JS: camelCase
HTML: kebab‑case
CSS: kebab‑case
Особняком стоит химерное именование констант типа SVG_MARKERUNITS_USERSPACEONUSE.
Рекомендации
✅ Оптимальный выбор – snake_case, как наиболее удобочитаемый и наименее проблемный.
Соглашения в $mol
snake_case — любые имена в XHTML и CSS, локальные имена в JS
Cobra_case — имена локальных фабрик в JS
$nake_case — глобальные имена в JS, соответствующие FQN.
Послесловие
Надеюсь этот разбор будет для вас полезным, даже если выводы окажутся совсем иными.
Актуальный оригинал на $hyoo_page.
Представляю универсальный responsive header для React.js / Хабр | Веб-студия Nat.od.ua
Представляю универсальный responsive header для React.js / Хабр
Вы когда-нибудь думали о том, чтобы создать свой стартап? Почти каждому стартапу (да и +/- любой компании) нужен лендинг/сайт. А у каждого сайта вверху есть хедер с меню навигации. При чем в наше время он обязательно должно быть адаптивным, чтобы одинаково хорошо работать как на компьютерах, так и на мобильных телефонах и планшетах.
Зачем каждый раз тысячи фронтендеров разрабатывают этот хедер тратя множество часов опять и опять, когда почти все хедеры имеют один и тот же функционал и вид? Почему для этого до сих порт нет вменяемой библиотеки, позволяющей решить проблему подключением одного лишь компонента не тратя уйму времени? Подумала я и создала npm-пакет для React.js, представляющий собой универсальный хедер. Я реализовала большинство фич, которые вам могут потребоваться, это:
Поддержка десктопов
Поддержка телефонов
Поддержка планшетов
Поддержка вложенных списков меню
Поддержка оверлапинга (можно отображать прозрачный хедер поверх контента)
Поддержка кастомного компонента ссылки
Поддержка Server-Side Rendering (для Next.js и других фреймворков)
Использование react-header-responsive на реальном проекте можно увидеть здесь*, а ниже посмотреть скриншоты.
*Десктопная версия с включенным overlap
*Десктопная версия с включенным overlap и открытым submenu
*Мобильная версия
Подключение библиотеки я пыталась реализовать максимально просто, поэтому, чтобы создать ссылки (можно со вложенностью) достаточно просто передать JSON. Минимальный сетап выглядит так:
const pages = ,
},
{
name: ‘Pricing’,
link: ‘/pricing’,
},
];
access={
/>
Где:
pages – массив объектов страниц, содержащих свойства “name” и “link” для ссылки, и “name” и “children” для вложенного меню / списка.
home – логотип / ссылка домой.
access – компонент со ссылками на авторизацию/регистрацию.
Более расширенный вариант включает кастомный компонент ссылки и свойство “overlap” для отображения прозрачного хедера поверх контента (потенциально картинки):
pages={pages}
anchor={(link, name, className) => (
{name}
)}
access={
overlap
/>
Кастомный компонент ссылки передается в функции, поэтому неважно какие у него пропсы и его можно донастроить в самой функции.
Для установки компонента достаточно выполнить команду:
npm install react-header-responsive
Полный код с подключением библиотеки выглядит так:
import Header from ‘react-header-responsive’;
import logo from ‘./rhr-logo.png’;
function App() {
const pages = ,
},
{
name: ‘Pricing’,
link: ‘/pricing’,
},
];
const Access = () => {
return (
);
};
return (
<>
pages={pages}
anchor={(link, name, className) => (
{name}
)}
access={
overlap
/>
);
}
В целом, библиотека закрывает большинство требований к хедерам и легко раскрашивается/подправляется стилями.
Тут находится сама библиотека
Буду благодарна, если поставите звездочку 🙂
Надеюсь, что моя библиотека поможет сделать вашу работу чуточку комфортней и приятней, а гипотезы по стартапам будут протестированы быстрее 🙂
* Организация Meta, а также её продукты Instagram и Facebook признаны экстремистскими на территории РФ.
Как выбрать библиотеку стайлинга и заменить несколько дизайн-систем на одну. Часть 1 | Веб-студия Nat.od.ua
Как выбрать библиотеку стайлинга и заменить несколько дизайн-систем на одну. Часть 1
Привет! Меня зовут Вадим Казаченко, я лид фронта дизайн-системы ВТБ. Год назад устроился в банк и получил командную задачу — построить единую библиотеку компонентов, настолько универсальную, чтобы ее можно было использовать в любом продукте дизайн-системы банка, и при этом она не должна становиться «узким горлышком», как это обычно происходит с UI-китами в крупных компаниях. Дело в том, что в ВТБ существует множество дизайн-систем, над которыми работают десятки дизайнеров.
Непростая задача требовала проработки архитектуры дизайн-системы и сильно зависела от выбора решения для стайлинга. В этой статье подробно расскажу, от чего мы отталкивались и на чем остановили свой выбор.
К истории стилей
Первую версию CSS мы получили в далеком 1996 году, и с тех пор концептуально ничего не менялось: схема Selector { Property: Value } и полная статичность. Плюсом было только то, что грузятся стили из файла параллельно с загрузкой JS-кода. Если вы, конечно, не произвели весь стайлинг внутри HTML-страницы, что замедлило бы ее загрузку.
Работать со стилями стало приятнее с появлением препроцессоров. Некоторые из них добавляли улучшенный синтаксис, переменные и функции для генерации CSS, другие же, как postCSS, дали возможность совершать манипуляции со стилями.
Популярные расширения postCSS позволили автоматически добавлять префиксы для одинакового отображения стилей в браузерах, уменьшали размерность файлов для загрузки пользователями или же помогали проверять разработчикам код на ошибки линтерами.
Схема работы PostCSS
Кроме этого, пришлось еще решать существенную проблему: бесконечное число хаотично названных классов периодически создавали конфликты, что крайне мешало в работе над масштабным проектом.
Решением стало использование CSS-модулей в сочетании с методологией нейминга классов БЭМ (Блок, Элемент, Модификатор).
Пример использования классов в БЭМ:
Заголовок
Текст
Заголовок большой карточки
Текст большой карточки
БЭМ описала правила к наименованию компонентов, его составных частей и модификаций.
CSS-модули позволили безболезненно распиливать стили на разные файлы и ограничивать локальной областью, где к их классам добавился уникальный ключ, исключающий повторы в названиях.
В совокупности с препроцессорами эти решения так хорошо зашли, что до сих пор поставляются из коробки в самых современных фреймворках.
Итак, при использовании этого подхода получаем следующее:
Плюсы
Компоненты стилизуются модульно.
Нет наложения нейминга классов.
Статичный CSS загружается параллельно с JS.
Нет проблем с SSR.
Минусы
Сложно заводить и поддерживать токены для реализации тем.
Отсутствие типизации и подсказок без настройки IDE.
Чтобы соединить стили с компонентами, нужно маппить классы с пропсами.
Актуальный этап развития CSS = > CSS-in-JS
Давайте забьем на CSS и будем генерировать стили прямо из JS. Это легло в основу большинства библиотек, реализующих этот подход. Здесь не нужно прописывать какие-либо классы и разбираться, как компонентам их переключать. Под капот уходят все вопросы добавления префиксов, ключей к названиям и минификации.
Все стало крайне легко: берется функция styled, которая оборачивает HTML-тег, который нужно стилизовать. Стили добавляют через шаблонные строки, и в них же можно получать прямой доступ как к пропсам компонента, так и к общей теме, которую одним движением легко переключить со светлой на темную и так далее.
Пример использования styled-components
Итого, при использовании этого подхода получаем следующее:
Плюсы:
Не нужно думать о соединении стилей с пропсами.
Темы переключаются на лету.
SSR поддерживается, но есть нюансы.
Минусы:
Отсутствие типизации и подсказок.
Рендер стилей происходит только после загрузки JS.
Бесконечная генерация классов с хаотичным неймингом.
А что лучше, чем CSS-in-JS?
Логичным продолжением развития работы с CSS-in-JS стал переход к CSS-in-TS и его реализация в библиотеке stitches.dev с отличной документацией и широкими возможностями. Какие еще важные для нас преимущества можно отметить?
Пример базового добавления стилей в Stitches
Первый плюс — базовый стайлинг. Обертка styled практически такая же, как в styled-components, только стилизация происходит внутри объекта, а не строки. Для каждого CSS-свойства заданы типы, что позволяет без особого труда выставить стили с подсказками редактора кода и заняться более важными делами.
Вариативность стилей в Stitches
Второй плюс. Динамичность в этой библиотеке реализована с помощью вариантов: пропсы, которые передаются в компонент, переключают статичные объекты стилей. Помните, я упоминал БЭМ ранее в статье? Это по сути и есть его реализация, но без лишних движений!
Пример реализации БЭМ библиотекой Stitches
Плюс третий. Способ реализации stitches.dev исключает возможность использования функций и при этом повышает читаемость кода. В своих же бенчмарках (https://stitches.dev/docs/benchmarks) авторы сравнивают подход вариантов против полностью генерируемых стилей. Это не особо показывает реальную производительность, зато подсвечивает, что в других библиотеках достаточно легко можно допустить ошибку и потерять эффективность.
Стайлинг для UI-кита
Если библиотека позволяет стилизовать компоненты, это не значит, что ее будет удобно использовать в UI-ките. В вопросах типового стайлинга stitches.dev в целом понятная и удобная система, но давайте рассмотрим ее в рамках работы UI-кита — это непосредственно относится к нашей задаче.
Создание темы в Stitches
Stitches со стартового гайда предлагает создать файл конфигурации, в котором можно определить тему и общие параметры:
theme: Объявление токенов темы, которые самостоятельно соотносятся с CSS-параметрами.
media: Объявление брейкпоинтов для адаптивной верстки.
utils: Создание уникальных функций-утилит для удобства добавления стилей.
prefix: Добавление префикса для избежания конфликтов.
themeMap: Добавление соотношений кастомных токенов к CSS-параметрам.
Странно, что в других библиотеках темизация спрятана где-то в разделах Advanced, тогда как это уже практически стандарт для сайтов и приложений.
Токены в CSS variables
На этом приятные моменты не закончились. Токены в этой библиотеке — не что-то эфемерное, как переменные в том же SASS, а использование нативных CSS variables!
Достаточно на верхнем уровне передать значения новых токенов, а сами компоненты уже нативным CSS сменят свои стили.
Пропустим разбор брейкпоинтов — с ними создавать адаптивный дизайн здесь очень легко. Лучше перейдем к важнейшей части любой библиотеки компонентов, когда дизайн выходит за рамки готовой реализации и разработчикам приходится создавать кастомы самостоятельно.
Пример обертки компонентов в Stitches
С кастомизацией у stitches также нет проблем — это крайне нативный процесс, происходящий с помощью обертки styled или добавления CSS-пропса. При этом любой вариант кастомизации поддерживает работу токенов.
Добавление темной темы в Stitches
Отдельно стоит отметить простоту использования тем: базовая создается в стартовой конфигурации, а все последующие поверх уже перезаписываются токенами. Нужно лишь на верхнем уровне приложения добавить класс созданной темы. При этом внутри компонентов идет привязка токенов по объекту темы, поэтому при потере каких-либо токенов тайпскрипт сразу укажет на эту проблему.
Соответственно, для продуктовых команд можно предложить кастомизировать токены темы, не опасаясь их потерять. А предоставив доступ к низкоуровневому API компонентов, мы расширяем возможности кастомизации нашего набора компонентов до предела. Но об этом в другой раз 🙂
Итого, при использовании этого подхода получаем следующее:
Плюсы:
Типизация и подсказки.
Вариативность стилей по канонам БЭМ.
Нативный стайлинг внутри JS/TS.
Темы переключаются на лету.
Отличная документация.
SSR поддерживается, но есть нюансы.
Из минусов — рендер стилей только после загрузки JS.
Наш опыт
Более чем за шесть месяцев работы со stitches мы столкнулись только с одной проблемой — случайным порядком вариантов при генерации классов. Например, компонент Input имеет булевые варианты Error и Disabled, и стили первого перекрывали стили второго. А нам нужен как раз обратный эффект.
Решением этой проблемы стало банальное добавление !important или использование compoundVariants. Но в будущем рассчитываем, что ситуацию исправит добавление поддержки CSS layers в библиотеку.
В остальном stitches отлично подошла под требования в рамках дизайн-системы. В следующей статье расскажем о применении библиотеки в нашей архитектуре. До встречи!
Сравниваем структуры хоть и глубоко, но быстро / Хабр | Веб-студия Nat.od.ua
Сравниваем структуры хоть и глубоко, но быстро / Хабр
Здравствуйте, меня зовут Дмитрий Карловский и я.. автор множества микроскопических и самых шустрых в своём классе библиотек. Одна из них — $mol_compare_deep, умеющая сравнивать произвольные структуры, даже содержащие циклические ссылки. И сейчас я вам расскажу, как ей это удаётся.
Cперва, небольшая предыстория, почему эта библиотека вообще нам понадобилась для реализации реактивной системы.
Эквивалентные изменения
Порой значение меняется на эквивалентное. И тут есть разные подходы к отсечению вырожденных вычислений.
👯Every: Реакция на каждое действие
🆔Identity: Сравнение по ссылке
🎭Equality: Структурное сравнение
🔀Reconcile: Структурная сверка
Dupes: 👯Every
В библиотеках типа RxJS каждое значение является уникальным событием, что приводит к ненужному запуску реакций.
777 != 777
Чтобы этого не происходило, нужно писать дополнительный код, который часто забывают, и потом огребают.
Dupes: 🆔Identity
Многие библиотеки всё же умеют сравнивать значения. И если состояние не поменялось, то реакции не срабатывают. А если поменялось, даже на эквивалентное значение, то срабатывают.
777 == 777
!=Если мы нафильтровали новый массив, с тем же содержимым, то скорее всего нам не нужно запускать каскад вычислений. Но вручную уследить за всеми такими местами – мало реалистично.
Dupes: 🎭Equality
Наиболее продвинутые библиотеки, типа $mol_wire, делают глубокое сравнение нового и старого значения. В некоторых других, типа CellX, его можно включить в настройках.
777 == 777
== !=Это позволяет отсекать лишние вычисления как можно раньше — в момент внесения изменений. А не в момент рендеринга заново сгенерированного VDOM в реальный DOM, как это часто происходит в React, чтобы узнать, что в доме‑то менять и нечего.
Глубокое сравнение — это, безусловно, сама по себе более дорогая операция, чем просто сравнение двух ссылок. Однако, рано или поздно, сравнить всё содержимое всё равно придётся. Но гораздо быстрее это сделать пока данные рядом, а не когда они разлетятся по тысяче компонент в процессе рендеринга.
Тем не менее, если данные поменялись, то полетят дальше по приложению и будут глубоко сравниваться снова и снова, что никуда не годится. Поэтому тут важно реализовывать кеширование результата глубокого сравнения для каждой пары сравниваемых объектов.
Dupes: 🔀Reconcile
Наконец, можно пойти ещё дальше, и не просто глубоко сравнивать значения, но и делать их сверку, чтобы сохранить ссылки на старые объекты, когда они эквивалентны новым.
const A = { foo: 1, bar: [] }
const B = { foo: 2, bar: [] }
reconcile( A, B )
assert( B.foo === 2 )
assert( B.bar === A.bar )
Как видите, A и B у нас тут отличаются, но свойство bar осталось таким как было. Это хорошо с точки зрения GC, ведь мы переиспользуем объекты, находящиеся в старом поколении сборщика мусора. А объект из молодого поколения при сверке был выборошен, что очень быстро.
Кроме того, когда вдальнейшем в компоненте, что рендерит bar, будет снова произведена его сверка, то произойдёт это крайне быстро, ведь старое и новое значения будут идентичны. С другой стороны, если объекты всё же будут отличаться, то повторная сверка снова пойдёт по всем внутреннстям объекта. Тут опять же необходимо кеширование. Но..
Изменение полей нового объекта на значения из старого — это не всегда безопасная операция. Например, с DOM‑элементами такие финты проворачивать нельзя. В лучшем случае это не заработает, а в худшем вообще его сломает. В ряде случаев вы будете получать исключение при попытке изменить объект. Порой изменения будут попросту игнорироваться, а порой запускать сеттеры, делающие какие‑нибудь стрёмные дела.
К тому же, если объекты фактически идентичны, нам надо сначала их глубоко сравнить. И если они одинаковы, то вернуть старый, а если нет — начать менять новый. Ну либо сразу начать менять новый, чтобы потом выяснить, что мы поменяли все его свойства, так что вернуть надо старый.
Короче, данный подход не самый шустрый и надёжный, поэтому в $mol мы от него отказались в пользу глубокого сравнения с кешированием.
Когда реактивное состояние принимает новое значение, мы должны уведомить подписчиков об изменении. Но если изменение даёт эквивалентный результат, то можно ничего и не делать. Нам надо лишь понять: является ли изменение эквивалентным, или нет.
Например, если мы получили новый массив, но он поэлементно равен предыдущему, то даже если мы пересчитаем всё, зависящее от него, приложение, то для пользователя ничего не поменяется.
Получается нам надо уметь глубоко сравнивать новые данные и старые. Причём делать это быстро. Но тут на нашем пути может возникнуть ряд трудностей..
Некоторые объекты (например, Value Object) можно сравнивать структурно, другие же (например, DOM элементы или бизнес-сущности) – нельзя. Как их отличать?
Ну, стандартные типы (массивы, структуры, регулярки и тп) можно просто детектировать и сравнивать структурно.
С пользовательскими же чуть сложнее. По умолчанию не будем рисковать, а будем сравнивать их по ссылке. Но если в объекте объявлен метод Symbol.toPrimitive, то считаем, что это сериализуемый объект, а значит такие объекты можно сравнивать через сравнение их сериализованных представлений.
class Moment {
iso8601: string
timestamp: number
native: Date
( mode: ‘number’ | ‘string’ | ‘default’ ) {
switch( mode ) {
case ‘number’: return this.timestamp
case ‘string’: return this.iso8601
case ‘default’: return this.iso8601
}
}
}
Если мы сравнили глубокие структуры и выяснили, что они в целом отличаются, то, когда будем их поддеревья передавать дальше, было бы опрометчиво сравнивать их снова и снова, ведь мы это уже сделали ранее. Поэтому результат глубокого сравнения пар объектов мы будем кешировать в двойных WeakMap, что обеспечит нам автоматическую очистку кеша по мере сборки объектов сборщиком мусора.
После сравнения, один из объектов Left и Right обычно выкидывается. В первом случае это освободит и кеш целиком, и все его данные, а значит при изменении значения, у нас ничего лишнего в памяти не останется. Во втором же случае освободятся только данные, а сам кеш останется для будущих сравнений, что предотвращает лишнюю аллокацию кешей при частом прилёте эквивалентных значений.
Наконец, в данных могут встретится циклические ссылки. Как минимум тут нельзя уходить в бесконечный цикл. А желательно правильно их сравнивать.
Например, следующие два объекта структурно эквивалентны:
const left = { id: ‘leaf’, kids: [] }
left.kids.push({ id: ‘son’, parent: left })
const right = { id: ‘leaf’, kids: [] }
right.kids.push({ id: ‘son’, parent: right })
Оказывается, поддержать циклические ссылки совсем не сложно, когда у нас уже есть кеш. Сперва пишем в него, что объекты эквивалентны, и погружаемся в глубь. Если снова наткнёмся на эту пару объектов, то возьмём значение из кеша и пойдём дальше. Если же где-то найдём отличия, то и в кеше потом поправим, что объекты всё-таки не эквивалентны.
В результате, у нас получилась библиотека $mol_compare_deep, размером в 1 килобайт, которая быстрее любых других, представленных в NPM:
Поиграться с ней можно в нашей JS-песочнице или сразу в своём проекте. Баги и респекты присылайте в тему про $mol на форуме Гипер Дев.
Актуальный оригинал на $hyoo_page
Советы по веб-разработке, которые я дал бы себе 2 года назад / Хабр | Веб-студия Nat.od.ua
Советы по веб-разработке, которые я дал бы себе 2 года назад / Хабр
Веб-разработка — это быстрорастущая область карьеры, и спрос на квалифицированных веб-разработчиков высок. Будучи студентом, вы можете предпринять шаги, чтобы подготовиться к успешной карьере веб-разработчика после школы. Вот несколько советов о том, как стать отличным веб-разработчиком после школы.
Изучите основы
Чтобы стать отличным веб-разработчиком, важно иметь прочную основу в основах. Ознакомьтесь с HTML, CSS, JavaScript и другими широко используемыми языками программирования. Пройдите онлайн-курсы или посетите семинары, чтобы изучить эти языки и другие необходимые инструменты программирования.
Создайте сильное портфолио
Для веб-разработчика важно иметь портфолио своих работ. Подумайте о создании различных проектов, демонстрирующих ваши навыки и способности. Участвуйте в соревнованиях или соревнованиях по программированию, так как они также помогут вам освоить новые приемы и приемы.
Сосредоточьтесь на пользовательском опыте
Пользовательский опыт является неотъемлемой частью веб-разработки. Важно не только сделать сайт привлекательным, но и удобным для пользователя. Помните, что пользователи могут быть демотивированы, если они найдут веб-сайт, который сбивает с толку, непривлекателен или требует времени для загрузки.
Будьте в курсе последних тенденций
Тенденции веб-разработки постоянно меняются, поэтому важно быть в курсе новейших инструментов и технологий, чтобы оставаться конкурентоспособными. Присоединяйтесь к сообществам веб-разработчиков и подписывайтесь на интернет-публикации, чтобы всегда быть в курсе.
Самореклама
Как один из лучших способов выделиться на рынке труда веб-разработки, самореклама имеет решающее значение. Создайте профессиональный профиль на платформе веб-разработки, такой как GitHub или LinkedIn. Делитесь своими проектами и достижениями в социальных сетях, чтобы потенциальные сотрудники могли лучше вас найти.
Практикуйтесь постоянно
Частая практика, даже вне учебных занятий, является неотъемлемой частью того, чтобы стать великим веб-разработчиком. Подумайте о настройке среды разработки, создании экспериментальных веб-страниц или серии проектов, и в конечном итоге вы сможете стать мастером веб-разработчика.
Чтобы стать отличным веб-разработчиком, нужно время и практика, но следование этим советам может увеличить ваши шансы на успех. Помните, что сохранять позитивный настрой, быть открытым для обратной связи и уметь решать проблемы — важные качества отличного веб-разработчика.
Create react app умирает? / Хабр | Веб-студия Nat.od.ua
Create react app умирает? / Хабр
Зайдя на официальный сайт React я не сразу понял, что произошло.
Когда мы заходим на страницу документации React в раздел установки, мы можем увидеть различные предложенные варианты установки фреймворков React, а именно Next.js, Remix, Expo, Gatsby. Но при этом нет варианта установки самого React в чистом виде. Неужели React сдает позиции.
На самом деле это не так. Если присмотреться, то можно найти скрытую сноску с информацией о том, можно ли использовать React в чистом виде. Ниже я представлю перевод части данной сноски.
Вы определенно можете использовать React без фреймворка. Однако, если вы создаете новое приложение или сайт полностью с помощью React, мы рекомендуем использовать платформу.
И вот почему.
Даже если сначала вам не нужна маршрутизация или получение данных (data fetching), вы, скорее всего, потом заходите добавить необходимые для них библиотеки. По мере роста вашего Javascript приложения растет ваш код и вам придется выяснять, как разнести этот код для каждого роута по отдельности. Во время увеличения потребностей в получении данных вероятно придется столкнуться с проблемами водопадом между сервером и клиентом (server-client network waterfalls), что замедлит ваше приложение. Поскольку большинство пользователей из аудитории имеет плохие условия сетевого соединения и недорогие устройства, вам понадобится создать HTML с ранним отображением компонентов – либо на сервере, либо во время сборки. Изменение настроек для выполнения части кода на сервере или во время сборки может быть сложным.
. . . . . . .
Фреймворки React на этой странице решают подобные проблемы по умолчанию, без дополнительной работы с вашей стороны. Они позволяют вам начать очень экономно, а затем масштабировать ваше приложение в соответствии с вашими потребностями.
. . . . . . .
Если вы все еще не уверены, или ваше приложение имеет необычные ограничения, которые плохо обслуживаются этими фреймворками, и вы хотите развернуть свою собственную пользовательскую настройку, мы не можем остановить вас — дерзайте! Берите react и react-dom из npm, настраивайте свой пользовательский процесс сборки с помощью сборщика, такого как Vite или Parcel, и добавляйте другие инструменты по мере необходимости для маршрутизации, статической генерации или рендеринга на стороне сервера и многого другого.
Исходя из данной информации в принципе можно понять, что с React все в порядке. Просто разработчики говорят о том, что React – это библиотека, которая не имеет множества встроенных инструментов и лучше использовать какой-либо фреймворк, но при этом никто не перестает поддерживать и использовать React.
Но есть еще одна вещь, которую необходимо выяснить…
Где рекомендация create-react-app?
На данный момент на странице документации полностью исчезла информация о том, что мы можем использовать create-react-app. Даже в приведенной выше сноске говориться о том, что необходимо брать react, reac-dom, сборщик пакетов и настраивать под себя.
Также, если обратить внимание на репозиторий create-react-app, мы можем увидеть, что последний коммит был сделан 8 сентября.
В issue гитхаба уже начали появляться темы о том, что же происходит.
Пробежавшись по issue, я нашел ссылку на пост Reddit, в котором официальная команда React дала ссылку на более ранний issue с подробным описанием происходящего. Если вы хотите почитать, ссылку прикладываю ниже.
Ссылка
Заменить рекомендацию Создать приложение React на Vite на t3dotgg · Запрос на вытягивание #5487 · reactjs/react.dev (github.com)
Если говорить кратко, о том, что говориться в ответе, то Create React App решал множество проблем, но временем происходила стагнация, многие начали подмечать, что приложения, созданные с использованием Create React App становятся медленнее альтернативных. При всем при этом Create React App сильно отстает в технологиях, например, не поддерживает SSR/SSG, которые, как говорит разработчик, более эффективны и для многих сайтов были бы предпочтительнее. Поэтому к React надо относиться именно как к библиотеке и по возможности использовать фреймворки, которых много и это хорошо.
На данный момент Create React App не соответствует цели быть лучшей утилитой для создания приложения. Поэтому разработчики видят несколько вариантов действий, которые можно предпринять:
1) Создать новый фреймворк с нуля, при этом переквалифицировать Create React App под него. На данный момент не считается целесообразным.
2) Отказаться от Create React App и поддерживать другой сложный шаблон для создания приложения с использованием Vite.
3) Уменьшить использование или вовсе упразднить Create React App и продвигать фреймворки. При этом говориться, что фреймворки будут предпочтительными, но не обязательными. Но при этом возникает проблема в виде отсутствия фирменного CLI шлюза, что будет плохо влиять на бренд.
4) Выбрать какой-либо фреймворк и использовать Create React App для создания приложения уже на основе этого фреймворка. Но тогда у других фреймворков возникнет проблема в плане конкуренции, а также все старые туториалы сразу перестанут работать.
5) Сделать Create React App лаунчером. Create React App будет предлагать список рекомендуемых фреймворков, а также возможность использовать классический подход создания приложения без фреймворка (но, возможно с Vite под капотом)
В настоящее время разработчики склоняются к варианту под номером 5, чтобы пользователи явно понимали, что лучше использовать фреймворки, но при этом не лишать их возможности работы на чистом React.
Заключение
В заключение хочу сказать, что Create React App скорее всего не умрет и им дальше можно будет пользоваться, но нас ждут перемены в использовании данной утилиты.
P.S. Надеюсь, статья была полезна и информативна. Если кто-то имеет более свежую информацию, я буду рад ее почитать.