Для тех, кто также как и я каждый раз писал свой обработчик для state-менеджеров, чтобы данные также сохранялись в locale storage и впоследствии не пропадали после перезагрузки страницы: оказывается для этого существуют отдельные библиотеки 😄
Например, для effector это effector-storage, для pinia из vue это pinia-plugin-persistedstate, а для zustand это zustand-persist 💁♂️
Например, для effector это effector-storage, для pinia из vue это pinia-plugin-persistedstate, а для zustand это zustand-persist 💁♂️
Недавно попался очередной удобный сайт для подготовки к Frontend собеседованиям. Понравился тем, что в нём собрано всё вместе: теория и практика, алгоритмы и System Design, JavaScript и React.
bigfrontend.dev
BFE.dev - prepare for Front-End job interviews.
BFE.dev is a place to practice Front-End dev skills, discuss with others, get ready for interviews and get yourdream offer.
⚡1
Выложил статью о библиотеке localForage на habr. Полезная штука, когда размеров localStorage уже не хватает, а работать с нативным API IndexedDB не особо хочется.
Хабр
localForage — Что делать если localStorage уже не хватает?
Как вы уже, наверное, знаете, браузерные хранилища данных, такие как localStorage и sessionStorage , сильно ограничены в своих размерах и для хранения большого количества данных не подходят. В разных...
Если вы до сих пор вручную сравниваете npm пакеты, перебирая различные параметры, то самое время обратить внимание на 2 этих сервиса:
1) Bundlephobia
2) NPM Package Info
Они содержат всю необходимую информацию для того, чтобы вы могли точно понять чем одна библиотека лучше другой и принять правильное решение.
1) Bundlephobia
2) NPM Package Info
Они содержат всю необходимую информацию для того, чтобы вы могли точно понять чем одна библиотека лучше другой и принять правильное решение.
⚡1
Если ваш скрипт должен запускаться в разных средах, то, вероятно, вам будет полезен объект
globalThis. Он предоставляет доступ к глобальному пространству имен в любом окружении. К примеру, в браузере это window, в Node.js это global, а в веб-воркерах это self. С введением globalThis в ECMAScript 2020 (ES11) уже не нужно писать проверку под каждую отдельную среду, т.к. везде он будет работать правильно:globalThis === window
globalThis === global
globalThis === self
Я заметил, что мало кто использует в своих проектах рендер-пропсы. Возможно, это связано с тем, что примеров в Интернете не так много, а те из них которые есть - это больше какая-то теория, не сильно применимая на практике. В общем, постарался исправить эту ситуацию, написав новую статью на habr.
В последнее время в сети много шума по поводу DeepSeek - китайского ChatGPT. Попробовал его сам. Пока что на фронтендерские вопросы отвечает неплохо, но значительно слабее конкурента от OpenAI. Будем наблюдать за ним дальше.
Оказывается let и const работают аж на 10% медленнее var 🤦♂️😄
Относительно недавно разработчики V8 выпустили отчёт о нововведениях, им получилось сократить эту разницу до 6%.
https://docs.google.com/document/d/1klT7-tQpxtYbwhssRDKfUMEgm-NS3iUeMuApuRgZnAw/edit?tab=t.0
https://v8.dev/blog/holiday-season-2023
Но это всё равно слишком большая разница, особенно для крупных и сложных систем. Собственно, поэтому TypeScript уже переехал на var 👍
https://github.com/microsoft/TypeScript/pull/52833
https://github.com/microsoft/TypeScript/pull/52903
Относительно недавно разработчики V8 выпустили отчёт о нововведениях, им получилось сократить эту разницу до 6%.
https://docs.google.com/document/d/1klT7-tQpxtYbwhssRDKfUMEgm-NS3iUeMuApuRgZnAw/edit?tab=t.0
https://v8.dev/blog/holiday-season-2023
Но это всё равно слишком большая разница, особенно для крупных и сложных систем. Собственно, поэтому TypeScript уже переехал на var 👍
https://github.com/microsoft/TypeScript/pull/52833
https://github.com/microsoft/TypeScript/pull/52903
🤯2
Ранее при работе с разными наборами стилей возникали проблемы переопределения. Кто-то использовал костыли ввиде
В CSS Cascading and Inheritance Level 5 в 2021 году появился альтернативный вариант для работы с переопределением стилей - директива
Она позволяет создавать слои с наборами стилей и определять их приоритет самостоятельно.
Например:
Порядок
Вот таким образом можно определять порядок импортируемых стилей:
Этот синтаксис очень удобен при переопределении стилей библиотек:
!important, кто-то пытался добавить отдельным элементам больше специфичности при помощи дополнительных конструкций в селекторе (например: .container .wrapper .content .form .button.button-danger { ... }) и так далее. Все эти варианты были очень неудобными и чаще всего только усложняли стили для восприятия.В CSS Cascading and Inheritance Level 5 в 2021 году появился альтернативный вариант для работы с переопределением стилей - директива
@layer.Она позволяет создавать слои с наборами стилей и определять их приоритет самостоятельно.
Например:
@layer reset, base, utilities;
@layer base {
h1 {
color: blue;
}
}
@layer reset {
h1 {
color: red;
}
}
@layer utilities {
h1 {
color: green;
}
}
/*
По итогу применится color: red, т.к. reset по порядку указан первым и благодаря этому имеет наивысший приоритет:
h1 {
color: red;
}
*/
Порядок
@layer reset, base, utilities; можно было бы вообще не указывать. Тогда чем бы ниже располагался слой, тем бы больше у него была специфичность. В таком случае color был бы равен green, т.к. utilities располагается ниже остальных.Вот таким образом можно определять порядок импортируемых стилей:
@import url("reset.css") layer(reset);
@import url("base.css") layer(base);
@import url("utilities.css") layer(utilities);Этот синтаксис очень удобен при переопределении стилей библиотек:
@import url("tailwind.css") layer(tailwind);
@layer my-styles {
.button {
background: green;
color: white;
}
}This media is not supported in your browser
VIEW IN TELEGRAM
В CSS с недавнего времени появилось свойство
Данного эффекта можно достигнуть, указав данное свойство со значением
Ранее нам для подобной реализации пришлось бы создать массивный блок JS кода в 25+ строк.
Поддержка браузерами пока что не сильно большая, но будем надеяться что скоро Firefox и Safari вслед за Chrome подключатся к этой инициативе.
Ссылки:
Официальная документация
field-sizing. Оно позволяет управлять размерами полей для ввода. А именно: делать так, чтобы размер поля изменялся относительно содержимого (как показано на видео).Данного эффекта можно достигнуть, указав данное свойство со значением
content (по-умолчанию равно fixed). Ранее нам для подобной реализации пришлось бы создать массивный блок JS кода в 25+ строк.
Поддержка браузерами пока что не сильно большая, но будем надеяться что скоро Firefox и Safari вслед за Chrome подключатся к этой инициативе.
Ссылки:
Официальная документация
В ECMAScript 2025 для Set появились новые методы для работы с множествами. Теперь их стало гораздо проще сравнивать друг с другом и находить различия.
union - объединяет 2 множества и создаёт новый Set с уникальными элементами.
intersection - создаёт Set с дубликатами из двух множеств.
difference - создаёт Set с элементами, которые присутствуют во множестве
symmetricDifference - создаёт Set из уникальных элементов, которые содержатся в двух множествах, но без дубликатов.
isSubsetOf - проверяет, содержатся ли все элементы множества
isSupersetOf - проверяет, содержатся ли все элементы множества
isDisjointFrom - проверяет, есть ли общие элементы у множеств. Возвращает true, если их нет.
union - объединяет 2 множества и создаёт новый Set с уникальными элементами.
const a = new Set([1, 2, 3]);
const b = new Set([3, 4, 5]);
console.log(a.union(b)); // Set {1, 2, 3, 4, 5}
intersection - создаёт Set с дубликатами из двух множеств.
const a = new Set([1, 2, 3]);
const b = new Set([3, 4, 5]);
console.log(a.intersection(b)); // Set {3}
difference - создаёт Set с элементами, которые присутствуют во множестве
a, но отсутствуют во множестве b.const a = new Set([1, 2, 3]);
const b = new Set([3, 4, 5]);
console.log(a.difference(b)); // Set {1, 2}
symmetricDifference - создаёт Set из уникальных элементов, которые содержатся в двух множествах, но без дубликатов.
const a = new Set([1, 2, 3]);
const b = new Set([3, 4, 5]);
console.log(a.symmetricDifference(b)); // Set {1, 2, 4, 5}
isSubsetOf - проверяет, содержатся ли все элементы множества
a во множестве b и возвращает boolean.const a = new Set([1, 2]);
const b = new Set([1, 2, 3]);
console.log(a.isSubsetOf(b)); // true
isSupersetOf - проверяет, содержатся ли все элементы множества
b во множестве a и возвращает boolean.const a = new Set([1, 2]);
const b = new Set([1, 2, 3]);
console.log(b.isSupersetOf(a)); // true
isDisjointFrom - проверяет, есть ли общие элементы у множеств. Возвращает true, если их нет.
const a = new Set([1, 2, 3]);
const b = new Set([3, 4, 5]);
console.log(a.isDisjointFrom(b)); // false
Не так давно в CSS появились переменные, но мало кто знает, что их ещё можно и типизировать!
Это стало возможным благодаря директиве
Или вот такому объявлению JS:
1) При помощи свойства
2)
3)
Далее мы можем это использовать таким образом:
Если мы назначим переменную, значение которой будет отличаться от типа, указанного
Это стало возможным благодаря директиве
@property:@property --my-color {
syntax: '<color>';
inherits: false;
initial-value: red;
}Или вот такому объявлению JS:
window.CSS.registerProperty({
name: "--my-color",
syntax: "<color>",
inherits: false,
initialValue: "red",
});1) При помощи свойства
syntax мы указываем какой тип будет присвоен нашей переменной (полный список возможных значений и их комбинаций можно найти в спецификации).2)
inherits указывает, будет ли объявленная позже в коде переменная наследоваться потомками или нет.3)
initialValue задаёт значение по-умолчанию по аналогии со вторым параметром внутри var(--btn-bg, red);Далее мы можем это использовать таким образом:
@property --my-color {
syntax: '<color>';
inherits: false;
initial-value: red;
}
.box {
--my-color: blue;
background-color: var(--my-color); /* Будет использован blue */
}
.box:hover {
--my-color: green; /* Будет использован green */
}
/* Дочерние элементы уже не получат эту переменную, т.к. мы ранее указали inherits: false */
.child {
background-color: var(--my-color); /* Будет использован red, значение по-умолчанию */
}Если мы назначим переменную, значение которой будет отличаться от типа, указанного
@property, то будет взято значение по-умолчанию:.box {
--my-color: 42px; /* Тип не соответствует <color> */
background-color: var(--my-color); /* Будет использован red, значение по-умолчанию */
}Большинство разработчиков скорее всего знает о существовании глобальных значений для CSS свойств, таких как
Расскажу обо всех:
inherit, initial и unset, но существуют и другие. Этот список со временем понемногу разрастается. Расскажу обо всех:
inherit - указывает, что значение должны быть унаследовано от родительского элементаinitial - сбрасывает значение до того, которое установлено по-умолчанию. Например, для display это будет inline даже если элемент до этого был блочным.unset - если свойство является наследуемым, то будет вести себя как inherit, если нет, то как initial.revert - возвращает свойство к значению, которое было бы, если бы никаких стилей не было бы применено вообще. То есть для блочного элемента сбросит display до block, а для строчного до inline.revert-layer - откатывает значение до того, которое было определено в предыдущем каскадном @layer слое.Наконец-то появилась возможность удобного анимирования появления и исчезновения элементов в CSS, используя дискретные свойства, такие как
display. Делается это при помощи свойства transition-behavior со значением allow-discrete и директивы @starting-style.<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<style>
.box {
width: 200px;
height: 100px;
background: coral;
display: block;
opacity: 1;
transition: opacity 1s, display 1s allow-discrete;
}
.box.hidden {
opacity: 0;
display: none;
}
@starting-style {
.box {
opacity: 0;
}
}
</style>
</head>
<body>
<button onclick="document.querySelector('.box').classList.toggle('hidden');">
Переключить
</button>
<div class="box">Элемент с плавным появлением и исчезновением</div>
</body>
</html>
transition-behavior: allow-discrete - откладывает применение display: none до конца перехода. То есть даёт возможность плавного исчезновения. Поддерживается всеми современными браузерами.@starting-style - указывает стили, которые должны быть уже применены на момент переключения display с none на block. То есть даёт возможность плавного появления. Пока что не поддерживается только в Firefox.🔥1