Server Components и Server Actions. Часть 1.
Саму концепцию серверных компонентов нам представили еще несколько лет назад. В том числе, она активно используется в 14 версии Next.js в App Router, который создатели фреймворка теперь предлагают по умолчанию для разработки новых приложений. Однако в React серверные компоненты и экшены были анонсированы только в 19 версии. Я решила посмотреть поподробнее, что это за покемоны.
Server Component - это неинтерактивный компонент, который работает исключительно на стороне сервера.
Server Action - это функция, которая работает на сервере, но может использоваться клиентским компонентом, например как пропс-промис, который передается в этот компонент.
Давайте посмотрим на ещё несколько интересных примеров работы с ними поподробнее. Для них будем использовать все тот же Next.js 15, который поддерживает React 19.
👀 По умолчанию в App Router все страницы и компоненты внутри них являются серверными, до тех пор, пока мы не указали обратное.
В чем особенности серверного компонента в сравнении с клиентским
🔹 Серверный компонент может быть асинхронным.
Пример простого серверного компонента, который получает данные из API другого сервиса и сразу же отображает их:
Здесь нам не нужно дополнительное состояние loading внутри компонента, т.к. мы работаем в едином потоке. Вместо запроса к другому API, мы можем использовать запрос на чтение из файла или базы данных.
🔹 Серверный компонент рендерится только один раз на сервере.
Для компонента выше у нас будет всего лишь один вывод в консоль '[List] Server Component Render' - на сервере. При классическом Server Side Rendering таких выводов будет два - один на сервере, во время формирования HTML, и один на клиенте - во время гидратации. Для серверных же компонентов гидратация не нужна.
🔹 Серверный компонент не может рендерится напрямую в клиентском компоненте, но его можно передавать туда как props.
Рассмотрим пример, у нас есть компонент Switcher, который в зависимости от состояния отрисовывает один или другой компонент:
Дальше как пропсы в этот компонент мы можем передать как клиентский компонент, так и серверный:
🔹 При динамической подгрузке серверные компоненты передаются на клиент не в виде HTML, а в специальном формате
Вот как примерно выглядят пришедшие в браузер данные для новой страницы /about в нашем приложении на Next.js:
Из этой структуры React на клиенте сможет построить DOM-дерево, но при этом не будет производить процесса гидратации, так как серверные компоненты не обладают динамикой.
📂 Подробнее примеры можно посмотреть в нашем репозитории на GitHub.
А в следующей части поговорим про Server Actions.
Саму концепцию серверных компонентов нам представили еще несколько лет назад. В том числе, она активно используется в 14 версии Next.js в App Router, который создатели фреймворка теперь предлагают по умолчанию для разработки новых приложений. Однако в React серверные компоненты и экшены были анонсированы только в 19 версии. Я решила посмотреть поподробнее, что это за покемоны.
Server Component - это неинтерактивный компонент, который работает исключительно на стороне сервера.
Server Action - это функция, которая работает на сервере, но может использоваться клиентским компонентом, например как пропс-промис, который передается в этот компонент.
Давайте посмотрим на ещё несколько интересных примеров работы с ними поподробнее. Для них будем использовать все тот же Next.js 15, который поддерживает React 19.
👀 По умолчанию в App Router все страницы и компоненты внутри них являются серверными, до тех пор, пока мы не указали обратное.
В чем особенности серверного компонента в сравнении с клиентским
🔹 Серверный компонент может быть асинхронным.
Пример простого серверного компонента, который получает данные из API другого сервиса и сразу же отображает их:
export async function List() {
const data = (await fetch('https://dummyjson.com/products/search?limit=10').then((res) => res.json()));
console.log('[List] Server Component Render');
return (
<ul>
{data.products.map((product) => (
<li key={product.id}>
{product.id}: <b>{product.title}</b>
</li>
))}
</ul>
);
}Здесь нам не нужно дополнительное состояние loading внутри компонента, т.к. мы работаем в едином потоке. Вместо запроса к другому API, мы можем использовать запрос на чтение из файла или базы данных.
🔹 Серверный компонент рендерится только один раз на сервере.
Для компонента выше у нас будет всего лишь один вывод в консоль '[List] Server Component Render' - на сервере. При классическом Server Side Rendering таких выводов будет два - один на сервере, во время формирования HTML, и один на клиенте - во время гидратации. Для серверных же компонентов гидратация не нужна.
🔹 Серверный компонент не может рендерится напрямую в клиентском компоненте, но его можно передавать туда как props.
Рассмотрим пример, у нас есть компонент Switcher, который в зависимости от состояния отрисовывает один или другой компонент:
type ComponentType = 'list' | 'searchedList';
export function Switcher({ ListComponent, SearchedListComponent }: Props) {
const [type, setType] = useState<ComponentType>('list');
const handleClick = (newType: ComponentType) => () => setType(newType);
return (
<section>
<div>
<button onClick={handleClick('list')}>List</button>
<button onClick={handleClick('searchedList')}>Searched List</button>
</div>
{type === 'list' ? ListComponent : SearchedListComponent}
</section>
);
}
Дальше как пропсы в этот компонент мы можем передать как клиентский компонент, так и серверный:
<Switcher
// серверный компонент
ListComponent={<List />}
// клиентский компонент
SearchedListComponent={<SearchedList />}
/>
🔹 При динамической подгрузке серверные компоненты передаются на клиент не в виде HTML, а в специальном формате
Вот как примерно выглядят пришедшие в браузер данные для новой страницы /about в нашем приложении на Next.js:
5:I["(app-pages-browser)/./node_modules/next/dist/client/link.js",...
6:I["(app-pages-browser)/...
7:I["(app-pages-browser)/...
2:{"name":"","env":"Server","owner":null}
1:D"$2"
4:{"name":"About","env":"Server","owner":null}
3:D"$4"
3:["$","div",null,{"className":"page_page__bHvK0","children":...
...
Из этой структуры React на клиенте сможет построить DOM-дерево, но при этом не будет производить процесса гидратации, так как серверные компоненты не обладают динамикой.
📂 Подробнее примеры можно посмотреть в нашем репозитории на GitHub.
А в следующей части поговорим про Server Actions.
👍1
Server Components и Server Actions. Часть 2.
В предыдущем посте мы поговорили про Server Components, а сегодня рассмотрим Server Actions.
Ранее, когда мы рассказывали про новые хуки React, мы уже посмотрели на примерах, как можно работать с серверными экшенами в сочетании с хуком useActionForm (вот здесь можно почитать подробнее).
Но на самом деле нам не обязательно использовать новые хуки React или даже серверные компоненты для работы с серверными экшенами.
Посмотрим на пример простого компонента со списком товаров. Он также осуществляет поиск товаров по строке через внешнее API, в которое передается поисковый запрос:
Здесь search выглядит как обычная функция, но на самом деле это серверный экшен. Делает её таким директива 'use server'.
В чем отличия серверного экшена
🔹 Серверный экшен выполняется только на сервере.
В нашем примере вывод в консоль '[SearchedList] Server Action' будет выполнен на сервере. Если бы это была обычная функция, то этот вывод был бы в консоли браузера.
🔹 Общение между клиентом и сервером для серверных экшенов происходит посредством специальных API-зпросов.
При клике на кнопку Search в браузере будет происходить POST-запрос на тот же URL, на котором мы находимся (локально это https://localhost:3000/).
В ответ придут данные в специальном формате:
Таким образом нам не нужно добавлять новый эндпоинт в API, в коде мы получаем эти данные, как если бы мы просто вызвали какую-то функцию. При этом внутри функции search вместо запроса к внешнему API может быть запрос на чтение из файла или напрямую из базы данных.
Кроме этого мы можем передать promise из серверного экшена как пропс в наш клиентский компонент:
И дальше использовать новый метод use для того, чтобы дождаться результат его выполнения и применить как initialValue в хуке useState:
📂 Подробнее примеры можно посмотреть в нашем репозитории на GitHub.
Я считаю, что появление Server Components и Server Actions приближает ту эпоху, когда фронтендеру нужно уметь работать не только в среде браузера, но и быть немного бэкендером. Новые инструменты, с одной стороны, предоставляют много новых возможностей, в том числе и для оптимизации. Но как и со всеми новыми технологиями, нужно знать, как их готовить.
✍️ А как cчитаете вы - поделитесь в комментариях, что думаете о развитии React в сторону серверных компонетов и экшенов!
В предыдущем посте мы поговорили про Server Components, а сегодня рассмотрим Server Actions.
Ранее, когда мы рассказывали про новые хуки React, мы уже посмотрели на примерах, как можно работать с серверными экшенами в сочетании с хуком useActionForm (вот здесь можно почитать подробнее).
Но на самом деле нам не обязательно использовать новые хуки React или даже серверные компоненты для работы с серверными экшенами.
Посмотрим на пример простого компонента со списком товаров. Он также осуществляет поиск товаров по строке через внешнее API, в которое передается поисковый запрос:
'use client';
import { useState } from 'react';
import { search } from './searchAction';
export function SearchedList({ fetchInitialData }: Props) {
const [searchText, setSearchText] = useState('');
const [data, setData] = useState<SearchResponce | null>(null);
const handleChangeSearch = (event) => setSearchText(event.target.value);
const handleClick = async () => {
const result = await search(searchText);
setData(result);
};
return (
<section>
<div>
<input name="search" onChange={handleChangeSearch} value={searchText} />
<button type="submit" onClick={handleClick}>Search</button>
</div>
{data && (
<ul>
{data.products.map((product) => (
...
))}
</ul>
)}
</section>
);
}
Здесь search выглядит как обычная функция, но на самом деле это серверный экшен. Делает её таким директива 'use server'.
'use server';
export const search = async (query: string) => {
console.log('[SearchedList] Server Action');
const data = (await fetch(`https://dummyjson.com/products/search?limit=10&q=${query}`).then((res) => res.json()));
return data;
};
В чем отличия серверного экшена
🔹 Серверный экшен выполняется только на сервере.
В нашем примере вывод в консоль '[SearchedList] Server Action' будет выполнен на сервере. Если бы это была обычная функция, то этот вывод был бы в консоли браузера.
🔹 Общение между клиентом и сервером для серверных экшенов происходит посредством специальных API-зпросов.
При клике на кнопку Search в браузере будет происходить POST-запрос на тот же URL, на котором мы находимся (локально это https://localhost:3000/).
В ответ придут данные в специальном формате:
0:["$@1",["development",null]]
1:{"products":[{"id":101,"title":"Apple AirPods Max Silver","description":"The...
Таким образом нам не нужно добавлять новый эндпоинт в API, в коде мы получаем эти данные, как если бы мы просто вызвали какую-то функцию. При этом внутри функции search вместо запроса к внешнему API может быть запрос на чтение из файла или напрямую из базы данных.
Кроме этого мы можем передать promise из серверного экшена как пропс в наш клиентский компонент:
import { search } from './searchAction';
export function SearchedList() {
const fetchInitialData = search('');
return (
<Suspense fallback="Loading...">
<SearchedListBase fetchInitialData={fetchInitialData} />
</Suspense>
);
}
И дальше использовать новый метод use для того, чтобы дождаться результат его выполнения и применить как initialValue в хуке useState:
type Props = {
fetchInitialData: Promise<SearchResponce>;
};
export function SearchedList({ fetchInitialData }: Props) {
const initialData = use(fetchInitialData);
const [data, setData] = useState<SearchResponce>(initialData);
...
}
📂 Подробнее примеры можно посмотреть в нашем репозитории на GitHub.
Я считаю, что появление Server Components и Server Actions приближает ту эпоху, когда фронтендеру нужно уметь работать не только в среде браузера, но и быть немного бэкендером. Новые инструменты, с одной стороны, предоставляют много новых возможностей, в том числе и для оптимизации. Но как и со всеми новыми технологиями, нужно знать, как их готовить.
✍️ А как cчитаете вы - поделитесь в комментариях, что думаете о развитии React в сторону серверных компонетов и экшенов!
🤝🏻 Двусторонняя клиент-серверная связь, часть 3: Server-Sent Events
Недавно я уже рассказывала о двух методах для обеспечения двусторонней связи между клиентом и сервером – Long Polling и WebSockets. Сегодня хочется рассмотреть ещё одну технологию, которая может помочь в организации такой связи - механизм Server-Sent Events (SSE).
👉🏻 SSE — это технология, позволяющая серверам инициировать отправку данных клиентам, подписанным на эти уведомления. Основное применение SSE – отправка обновлений в режиме реального времени от сервера к клиенту через стандартный HTTP-протокол. Как можно заметить, это не совсем двусторонняя, а скорее односторонняя связь, но она в том числе позволяет обмениваться данными между разными клиентами в реальном времени.
Как это работает:
Клиент создаёт объект
Сервер обрабатывает запрос, устанавливает необходимые заголовки ответа (самый важный из которых –
Клиент в это время подписывается на события и обрабатывает их привычным способом:
⚡️ Вот и всё! Снова всё предельно просто. Пример реализации этого подхода для уже знакомого нам чата можно найти в нашем репозитрии. Здесь как раз используется подход SSE для обеспечения двусторонней связи, так как сервер инициирует отправку данных клиентам через SSE в ответ на получение сообщения от клиентов. А также можно потрогать Live Demo, которое мы сделали и для этой технологии.
Итого, это достаточно несложная в реализации технология, которая работает поверх знакомого всем HTTP, поддерживается во многих браузерах, имеет встроенный механизм переподключения и свой специфичный, но при этом достаточно простой, формат передачи данных.
Из минусов, это все-таки односторонняя коммуникация с ограниченным форматом данных. Но для многих несложных задач этот механизм может прекрасно подойти. Подробнее о нём и о некоторых нюансах как всегда можно почитать на MDN.
Недавно я уже рассказывала о двух методах для обеспечения двусторонней связи между клиентом и сервером – Long Polling и WebSockets. Сегодня хочется рассмотреть ещё одну технологию, которая может помочь в организации такой связи - механизм Server-Sent Events (SSE).
👉🏻 SSE — это технология, позволяющая серверам инициировать отправку данных клиентам, подписанным на эти уведомления. Основное применение SSE – отправка обновлений в режиме реального времени от сервера к клиенту через стандартный HTTP-протокол. Как можно заметить, это не совсем двусторонняя, а скорее односторонняя связь, но она в том числе позволяет обмениваться данными между разными клиентами в реальном времени.
Как это работает:
Клиент создаёт объект
EventSource, указывая URL сервера, от которого будет получать обновления:
const eventSource = new EventSource('https://example.com/sse');
Сервер обрабатывает запрос, устанавливает необходимые заголовки ответа (самый важный из которых –
Content-Type: text/event-stream), и начинает передавать сообщения в формате, специфичном для SSE. Примеры:
data: Сообщение №1
retry: 2000
--
data: Сообщение №2
id: 2
--
event: specificevent
data: Сообщение с пользовательским типом события
Клиент в это время подписывается на события и обрабатывает их привычным способом:
eventSource.onopen = function(event) {
console.log('Соединение установлено');
};
eventSource.onmessage = function(event) {
console.log('Новое сообщение:', event.data);
};
eventSource.addEventListener('specificevent', function(event) {
console.log('Сообщение с пользовательским типом:', event.data);
});
⚡️ Вот и всё! Снова всё предельно просто. Пример реализации этого подхода для уже знакомого нам чата можно найти в нашем репозитрии. Здесь как раз используется подход SSE для обеспечения двусторонней связи, так как сервер инициирует отправку данных клиентам через SSE в ответ на получение сообщения от клиентов. А также можно потрогать Live Demo, которое мы сделали и для этой технологии.
Итого, это достаточно несложная в реализации технология, которая работает поверх знакомого всем HTTP, поддерживается во многих браузерах, имеет встроенный механизм переподключения и свой специфичный, но при этом достаточно простой, формат передачи данных.
Из минусов, это все-таки односторонняя коммуникация с ограниченным форматом данных. Но для многих несложных задач этот механизм может прекрасно подойти. Подробнее о нём и о некоторых нюансах как всегда можно почитать на MDN.
👍1
1️⃣ Социальная сеть (2010)
Фильм рассказывает об истории создания Facebook Марком Цукербергом. В нём показано, как идея, начатая в студенческом общежитии, может изменить мир, а также эта история подчеркивает важность инноваций и предпринимательской смекалки.
2️⃣ Джобс: Империя соблазна (2013)
Этот фильм сосредоточен на восходящем пути Стива Джобса, от студента, который сбросил обучение, до одного из самых известных предпринимателей в области технологий. Фильм также подчеркивает, как визионерское мышление и инновации могут изменять технологии и культуру.
3️⃣ Игра в имитацию (2014)
Основанный на реальных событиях, фильм рассказывает о жизни Алана Тьюринга, который во время Второй мировой войны внес существенный вклад в разработку компьютерных технологий, расшифровав шифры немецких машин Enigma. Фильм показывает, как технологические достижения могут иметь значительное историческое значение.
4️⃣ Хакеры (1995)
Фильм о группе молодых хакеров, сталкивающихся с корпоративным заговором. Он показывает, как молодые, умные и креативные люди могут использовать свои навыки для борьбы за справедливость.
5️⃣ Стартап (сериал, 2016-2018)
Хотя это и сериал, а не фильм, он заслуживает упоминания за изображение тяжелых испытаний, через которые проходят стартапы. Это напоминает о значении упорства и инноваций в индустрии стартапов, которая славится своей конкуренцией.
А есть ли у вас любимый фильм про IT? Делитесь в комментариях 👇
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
🖇 IntersectionObserver – что он пересекает и кого обозревает?
IntersectionObserver в JavaScript – это API, с помощью которого можно подписаться на изменение видимости определённых элементов страницы относительно их родительских элементов или глобальной области просмотра (viewport). Таким образом, можно асинхронно отслеживать появление или исчезновение тех или иных элементов документа.
💡 Для чего он может быть полезен?
1. Ленивая загрузка (lazy loading) изображений и видео: загрузка медиа-контента только тогда, когда пользователь прокручивает страницу, и контент должен скоро появиться в области видимости.
2. “Бесконечный” скролл: динамическая подгрузка данных при достижении конца страницы, чтобы улучшить производительность при работе с большими объёмами данных.
3. Отслеживание взаимодействия с рекламой: определение, просматривал ли пользователь рекламные блоки достаточное время для учета показов.
4. Анимации: активация анимации только тогда, когда элемент становится видимым на экране.
📝 Рассмотрим пример применения IntersectionObserver для реализации бесконечного скролла. Пусть на странице есть 2 элемента:
И мы хотим загружать новые данные, когда пользователь промотает страницу до конца контейнера. Тогда JavaScript-код будет выглядеть следующим образом:
Таким образом, мы подписываемся на невидимый элемент, который находится в самом низу нашего списка данных. Как только этот элемент появится в области видимости (то есть выполнится условие
🔗 В итоге мы имеем, что IntersectionObserver – это мощный инструмент для оптимизации производительности и улучшения пользовательского интерфейса на веб-страницах. Подробнее о нём и его возможностях можно почитать в официальной документации на сайте MDN.
IntersectionObserver в JavaScript – это API, с помощью которого можно подписаться на изменение видимости определённых элементов страницы относительно их родительских элементов или глобальной области просмотра (viewport). Таким образом, можно асинхронно отслеживать появление или исчезновение тех или иных элементов документа.
💡 Для чего он может быть полезен?
1. Ленивая загрузка (lazy loading) изображений и видео: загрузка медиа-контента только тогда, когда пользователь прокручивает страницу, и контент должен скоро появиться в области видимости.
2. “Бесконечный” скролл: динамическая подгрузка данных при достижении конца страницы, чтобы улучшить производительность при работе с большими объёмами данных.
3. Отслеживание взаимодействия с рекламой: определение, просматривал ли пользователь рекламные блоки достаточное время для учета показов.
4. Анимации: активация анимации только тогда, когда элемент становится видимым на экране.
📝 Рассмотрим пример применения IntersectionObserver для реализации бесконечного скролла. Пусть на странице есть 2 элемента:
<div id="container">
<!-- Сюда динамически добавляем данные -->
</div>
<div id="sentinel"></div> <!-- Элемент, за которым мы наблюдаем -->
И мы хотим загружать новые данные, когда пользователь промотает страницу до конца контейнера. Тогда JavaScript-код будет выглядеть следующим образом:
document.addEventListener("DOMContentLoaded", function() {
const container = document.getElementById('container');
const sentinel = document.getElementById('sentinel');
// Обработчик загрузки и добавления новых данных
const loadItems = () => { /* ... */ };
// Обработчик измненения видимости элемента
const handler = (entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
loadItems();
}
});
}
// Создаем объект IntersectionObserver с колбэком
const observer = new IntersectionObserver(handler);
// Подписываемся на наш элемент
observer.observe(sentinel);
// Загружаем первую порцию данных
loadItems();
});
Таким образом, мы подписываемся на невидимый элемент, который находится в самом низу нашего списка данных. Как только этот элемент появится в области видимости (то есть выполнится условие
entry.isIntersecting), будет инициирована загрузка новых данных, после чего элемент снова окажется внизу страницы. Также в реализации в реальной жизни стоит учесть, что элементы могут закончиться, и не инициировать лишние загрузки при каждом появлении отслеживаемого элемента в области видимости.🔗 В итоге мы имеем, что IntersectionObserver – это мощный инструмент для оптимизации производительности и улучшения пользовательского интерфейса на веб-страницах. Подробнее о нём и его возможностях можно почитать в официальной документации на сайте MDN.
📏 Prettier, ESLint и Stylelint: в чем разница?
Если вы фронтенд-разработчик, то, скорее всего, сталкивались с инструментами Prettier и ESLint. Оба они широко используются в мире JavaScript для улучшения качества кода, часто встречаются вместе на одном проекте, однако выполняют разные функции. И сегодня хочется разобраться, чем они отличаются и как каждый из них может быть полезен. А также обсудим еще один важный инструмент, который часто игнорируют в этой теме — Stylelint.
👉 Prettier — это инструмент для автоматического форматирования кода. Его основная задача — обеспечить консистентный стиль кода по всему проекту. Вы можете настроить Prettier так, чтобы он автоматически форматировал ваш код при сохранении файла или при коммите, что позволяет избежать разношерстности стиля в проекте и сосредоточиться на функциональности.
👉 ESLint — это анализатор кода (линтер), который проверяет ваш код на наличие потенциальных ошибок и плохих практик. ESLint позволяет настроить множество правил на проекте, чтобы обеспечить соблюдение различных стандартов кода и предотвращать ошибки.
👉 Stylelint — это инструмент для линтинга стилей, который проверяет ваш CSS (а также Sass, Less и другие варианты CSS-препроцессоров), чтобы обеспечить соблюдение заданных вами правил и предотвратить ошибки. Stylelint очень полезен для поддержания консистентности и качества ваших стилей.
В чем разница?
- Цель:
- Prettier фокусируется на автоматическом форматировании кода.
- ESLint ориентирован на проверку качества кода и обнаружение ошибок в JavaScript и TypeScript.
- Stylelint занимается линтингом и проверкой CSS-стилей.
- Форматирование против линтинга:
- Prettier просто форматирует код.
- ESLint более глубоко анализирует код и сообщает о проблемах, которые нужно исправить вручную.
- Настройка и правила:
- Prettier практически не требует настроек, он просто работает "из коробки".
- ESLint и Stylelint требуют бОльшей настройки для определения, какие ошибки и правила должны быть проверены, однако позволяют расширять свой функционал через множество плагинов. Например, один из таких интересных плагинов — это eslint-plugin-react-compiler, плагин для React, который помогает улучшить качество кода, показывая анализ нового компилятора React Compiler прямо в IDE (подробнее писали тут).
Prettier, ESLint и Stylelint не являются взаимозаменяемыми инструментами, но они дополняют друг друга. Используя все три инструмента в вашем проекте, вы можете гарантировать, что ваш код будет не только правильно отформатирован, но и лишен потенциальных ошибок, анти-паттернов, а также будет содержать качественно написанные стили.
👍 Ставьте реакции, если интересно узнать подробнее о настройке Prettier, ESLint и Stylelint в проекте с нуля!
Если вы фронтенд-разработчик, то, скорее всего, сталкивались с инструментами Prettier и ESLint. Оба они широко используются в мире JavaScript для улучшения качества кода, часто встречаются вместе на одном проекте, однако выполняют разные функции. И сегодня хочется разобраться, чем они отличаются и как каждый из них может быть полезен. А также обсудим еще один важный инструмент, который часто игнорируют в этой теме — Stylelint.
👉 Prettier — это инструмент для автоматического форматирования кода. Его основная задача — обеспечить консистентный стиль кода по всему проекту. Вы можете настроить Prettier так, чтобы он автоматически форматировал ваш код при сохранении файла или при коммите, что позволяет избежать разношерстности стиля в проекте и сосредоточиться на функциональности.
👉 ESLint — это анализатор кода (линтер), который проверяет ваш код на наличие потенциальных ошибок и плохих практик. ESLint позволяет настроить множество правил на проекте, чтобы обеспечить соблюдение различных стандартов кода и предотвращать ошибки.
👉 Stylelint — это инструмент для линтинга стилей, который проверяет ваш CSS (а также Sass, Less и другие варианты CSS-препроцессоров), чтобы обеспечить соблюдение заданных вами правил и предотвратить ошибки. Stylelint очень полезен для поддержания консистентности и качества ваших стилей.
В чем разница?
- Цель:
- Prettier фокусируется на автоматическом форматировании кода.
- ESLint ориентирован на проверку качества кода и обнаружение ошибок в JavaScript и TypeScript.
- Stylelint занимается линтингом и проверкой CSS-стилей.
- Форматирование против линтинга:
- Prettier просто форматирует код.
- ESLint более глубоко анализирует код и сообщает о проблемах, которые нужно исправить вручную.
- Настройка и правила:
- Prettier практически не требует настроек, он просто работает "из коробки".
- ESLint и Stylelint требуют бОльшей настройки для определения, какие ошибки и правила должны быть проверены, однако позволяют расширять свой функционал через множество плагинов. Например, один из таких интересных плагинов — это eslint-plugin-react-compiler, плагин для React, который помогает улучшить качество кода, показывая анализ нового компилятора React Compiler прямо в IDE (подробнее писали тут).
Prettier, ESLint и Stylelint не являются взаимозаменяемыми инструментами, но они дополняют друг друга. Используя все три инструмента в вашем проекте, вы можете гарантировать, что ваш код будет не только правильно отформатирован, но и лишен потенциальных ошибок, анти-паттернов, а также будет содержать качественно написанные стили.
👍 Ставьте реакции, если интересно узнать подробнее о настройке Prettier, ESLint и Stylelint в проекте с нуля!
👍4
📢 Сегодня обсудим одну из опасных веб-атак - CSRF (Cross-Site Request Forgery).
CSRF, или Cross-Site Request Forgery, это вид атаки на веб-приложения, при котором злоумышленник обманывает пользователя и заставляет его выполнить нежелательные действия на сайте, на котором он уже аутентифицирован (например, совершить покупку, изменить настройки аккаунта и т.д.).
Как это работает?
1. Пользователь аутентифицируется на доверенном сайте (например, на сайте банка).
2. Затем он попадает на вредоносный сайт, созданный злоумышленником.
3. Вредоносный сайт отправляет скрытый запрос к доверенному сайту, используя аутентификационные данные (куки, сессионные данные и т.д.).
4. Доверенный сайт выполняет этот запрос, считая его легитимным.
Эта атака возможна благодаря тому, что браузерные запросы автоматически включают в себя все куки, включая сессионные.
Примеры атак:
- Перевод денег: Пользователь заходит на фальшивый сайт с вредоносным кодом, который делает запрос на перевод денег со счета пользователя на счет злоумышленника.
- Смена электронной почты: Вредоносный сайт может отправить запрос на изменение контактного адреса электронной почты пользователя на сервере легитимного сайта.
Для защиты от CSRF-атак разработчику следует:
1. Использовать встроенную защиту от CSRF в вашем фреймворке, если она есть.
2. Добавлять CSRF-токены ко всем запросам, изменяющим состояние, и проверять их на сервере.
3. Использовать атрибут SameSite Cookie для сессионных куки.
4. Проверять происхождение запроса с использованием стандартных заголовков: origin и referer.
5. НЕ использовать GET-запросы для операций, изменяющих состояние. Если используете, защитите эти ресурсы от CSRF.
⚠️ Важно помнить, что XSS-уязвимости могут обойти все методы защиты от CSRF!
Подробнее про методы защиты можно почитать здесь
CSRF, или Cross-Site Request Forgery, это вид атаки на веб-приложения, при котором злоумышленник обманывает пользователя и заставляет его выполнить нежелательные действия на сайте, на котором он уже аутентифицирован (например, совершить покупку, изменить настройки аккаунта и т.д.).
Как это работает?
1. Пользователь аутентифицируется на доверенном сайте (например, на сайте банка).
2. Затем он попадает на вредоносный сайт, созданный злоумышленником.
3. Вредоносный сайт отправляет скрытый запрос к доверенному сайту, используя аутентификационные данные (куки, сессионные данные и т.д.).
4. Доверенный сайт выполняет этот запрос, считая его легитимным.
Эта атака возможна благодаря тому, что браузерные запросы автоматически включают в себя все куки, включая сессионные.
Примеры атак:
- Перевод денег: Пользователь заходит на фальшивый сайт с вредоносным кодом, который делает запрос на перевод денег со счета пользователя на счет злоумышленника.
- Смена электронной почты: Вредоносный сайт может отправить запрос на изменение контактного адреса электронной почты пользователя на сервере легитимного сайта.
Для защиты от CSRF-атак разработчику следует:
1. Использовать встроенную защиту от CSRF в вашем фреймворке, если она есть.
2. Добавлять CSRF-токены ко всем запросам, изменяющим состояние, и проверять их на сервере.
3. Использовать атрибут SameSite Cookie для сессионных куки.
4. Проверять происхождение запроса с использованием стандартных заголовков: origin и referer.
5. НЕ использовать GET-запросы для операций, изменяющих состояние. Если используете, защитите эти ресурсы от CSRF.
⚠️ Важно помнить, что XSS-уязвимости могут обойти все методы защиты от CSRF!
Подробнее про методы защиты можно почитать здесь
🌟 Простой способ сделать красивый скролл!
Вы можете использовать два CSS-свойства - scrollbar-width и scrollbar-color, которые поддерживаются всеми браузерами, кроме Safari. А для того, чтобы поддержать стилизацию и в нём, можно использовать псевдоклассы с вендорным префиксом ::-webkit-scrollbar.
Вот так быстро можно сделать скролл красивым, используя лишь чистый CSS!
Вы можете использовать два CSS-свойства - scrollbar-width и scrollbar-color, которые поддерживаются всеми браузерами, кроме Safari. А для того, чтобы поддержать стилизацию и в нём, можно использовать псевдоклассы с вендорным префиксом ::-webkit-scrollbar.
Вот так быстро можно сделать скролл красивым, используя лишь чистый CSS!
Как и обещали, возвращаемся к вам с разбором задачи с LeetCode!)
Ставьте лайки этому видео и пишите в комментариях, какие еще задачи разобрать 💻
https://youtu.be/c44ISTawL1c
Ставьте лайки этому видео и пишите в комментариях, какие еще задачи разобрать 💻
https://youtu.be/c44ISTawL1c
YouTube
1 LeetCode: Two Sum - подробный разбор на javascript
1. Two Sum - Разбор задач для собеседований
📌 https://leetcode.com/problems/two-sum
Всем привет! В этом видео мы разберем популярную задачу с LeetCode под названием "Two Sum". Эта задача часто встречается на собеседованиях по программированию, и понимание…
📌 https://leetcode.com/problems/two-sum
Всем привет! В этом видео мы разберем популярную задачу с LeetCode под названием "Two Sum". Эта задача часто встречается на собеседованиях по программированию, и понимание…
📚 Начало рабочей недели - самое время, чтобы продолжить разговор о линтерах!
Сегодня мы рассмотрим, как настроить с нуля в своем проекте ESLint, Prettier, Stylelint, а также Husky и lint-staged.
P.S. Мы пробуем новый формат статей в Telegraph. Если вам он понравится, поддержите этот пост реакциями!)
Сегодня мы рассмотрим, как настроить с нуля в своем проекте ESLint, Prettier, Stylelint, а также Husky и lint-staged.
P.S. Мы пробуем новый формат статей в Telegraph. Если вам он понравится, поддержите этот пост реакциями!)
Telegraph
Как настроить Prettier, ESLint, Stylelint и Husky в проекте с нуля
В одном из прошлых постов мы говорили о таких инструментах, как Prettier, ESLint и Stylelint, и чем они отличаются. А сегодня мы попробуем поэтапно настроить все три библиотеки на нашем проекте, а также настроить прекоммитную проверку с помощью Husky и lint…
👍4
📌 Полезное свойство в JSDoc, особенно при рефакторинге! Помогает отмечать функции и константы как
В комментариях также полезно указывать альтернативу старому решению.
IDE автоматически будет зачеркивать такие функции в коде и отображать специальную подсказку.
deprecated, то есть устаревшими и не рекомендованными к использованию.В комментариях также полезно указывать альтернативу старому решению.
IDE автоматически будет зачеркивать такие функции в коде и отображать специальную подсказку.
Лето - пора отпусков, а как вы проводите свой?)
Anonymous Poll
37%
Все рабочие чаты на мьют и путешествовать! 🏖
16%
Работаю на второй работе 🤓
11%
Сижу дома и смотрю сериальчики 📺
37%
Отпуск? Что такое отпуск? 🤡
0%
Другой вариант (пишите в комментариях) ✍️
Сегодня мы хотели бы поделиться тем, как можно организовать с нуля небольшой проект, для которого кроме клиента необходимо иметь простой сервер, но при этом нет нужды писать сложный бэкенд или использовать специальные большие фреймворки. А также бонусом расскажем, как можно быстро и просто его задеплоить ⬇️
https://telegra.ph/Eshchyo-odin-preset-sozdayom-demo-s-pomoshchyu-Vite-i-Express-08-17
https://telegra.ph/Eshchyo-odin-preset-sozdayom-demo-s-pomoshchyu-Vite-i-Express-08-17
Telegraph
Ещё один пресет: создаём демо с помощью Vite и Express
Какое-то время назад я писала про различные способы способы обеспечить двустороннюю связь между клиентом и сервером: Long Polling, WebSockets и Server-Sent Events. Во всех этих постах были небольшие Live Demo, где можно потрогать реализацию. В этой статье…
Сегодня хотим поделиться с вами отличным ресурсом для изучения и практики CSS Flexbox!
Это бесплатный игровой тренажёр 👉 Flexbox Froggy
Закрепляем на видное место и вперёд оттачивать свои навыки в flexbox-ах!) 🚀
Это бесплатный игровой тренажёр 👉 Flexbox Froggy
Закрепляем на видное место и вперёд оттачивать свои навыки в flexbox-ах!) 🚀
🤔 Вы когда-нибудь задавались вопросом, чем отличаются
https://telegra.ph/CommonJS-i-ECMAScript-Modules-v-JavaScript-v-chyom-raznica-i-kak-s-nimi-zhit-08-24
import и require, и почему где-то используется одно, а где-то другое? Если да, то мы написали подробный разбор систем модулей в JavaScript, чтобы развеять все вопросы. А если вы уже разбираетесь в них, то статья поможет закрепить знания. https://telegra.ph/CommonJS-i-ECMAScript-Modules-v-JavaScript-v-chyom-raznica-i-kak-s-nimi-zhit-08-24
Telegraph
CommonJS и ECMAScript Modules в JavaScript: в чём разница и как с ними жить?
В языке JavaScript существует две основные системы модулей: CommonJS (далее будем называть его просто CJS) и ECMAScript Modules (далее ESM). Основная причина наличия двух различных систем модулей заключается в истории развития JavaScript как языка и его экосистемы.…
Все мы хоть раз пользовались директивой
1️⃣
2️⃣
3️⃣
P.S. Использование этих директиввредит вашему здоровью стоит минимизировать, поскольку они могут скрыть важные предупреждения о возможных ошибках в коде.
@ts-ignore, которая позволяет игнорировать строку кода на наличие ошибок TypeScript. Но, на самом деле, это не единственная директива, позволяющая управлять поведением компилятора. Вот ещё несколько примеров:1️⃣
@ts-expect-error — похожа на @ts-ignore, но ожидает, что следующая строка кода вызовет ошибку компиляции. Если ошибка не возникает, TypeScript выдаст предупреждение.2️⃣
@ts-nocheck — отключает проверку ошибок для всего файла. Полезно, когда нужно быстро включить файл в проект без необходимости исправлять все ошибки типизации. например, при миграции существующего JavaScript-проекта на TypeScript.3️⃣
@ts-check — включает проверку типов в файле JavaScript, когда в TypeScript включён режим allowJs. Полезно, если в вашем проекте используются файлы JavaScript, и вы хотите частично применять возможности TypeScript для повышения надёжности кода.P.S. Использование этих директив
Сегодня я расскажу о том, как работают JWT-токены, а также что такое access и refresh токены, и как с помощью них организовывается процесс аутентификации и авторизации в современных приложениях
Читать статью
Читать статью
Telegraph
JWT - что это такое и с чем его едят
JSON Web Token (JWT) — это открытый стандарт для создания токенов доступа, которые позволяют передавать информацию в самих токенах в закодированном виде. Чаще всего JWT используют для того, чтобы аутентифицировать пользователя в клиент-серверных приложениях.…
👍2❤1