This media is not supported in your browser
VIEW IN TELEGRAM
Кто так же ревью делает?
Вот серьезно, кто может по git diff сделать ревью? Ну максимум там совсем какую то дичь видно. А так без переключения на ветку, без запуска, без понимания в контексте что делает код, ревью сводится к бесполезной трате времени или формальности.
Вот серьезно, кто может по git diff сделать ревью? Ну максимум там совсем какую то дичь видно. А так без переключения на ветку, без запуска, без понимания в контексте что делает код, ревью сводится к бесполезной трате времени или формальности.
😁4👍1😢1🗿1
Turbo v2
Третьего дня(c) решил обновить Turbo до 2 версии. Очень уж глаза мозолило сообщение при запуске билда.
Миграция - мое почтение, всем бы так
Команда бодро отработала с первого раза, не упала, все ок.
Локально все билдилось замечательно, но пошли падать CI\CD билды.
Все указывало на то, что что то случилось с переменными.
Оказалось, что в Turbo 2 появилась (а может и раньше была с другим поведением) фигня, которая ограничивает использование env до указанных в конфигурации, или которые лежат в файле .env. При этом все переменные окружения игорируются!
И чтобы справится с этим, нужно при запуске задач ставить
Вот такая вотохуительная автоматическая миграция
Третьего дня(c) решил обновить Turbo до 2 версии. Очень уж глаза мозолило сообщение при запуске билда.
Миграция - мое почтение, всем бы так
yarn dlx @turbo/codemod migrate
Команда бодро отработала с первого раза, не упала, все ок.
Локально все билдилось замечательно, но пошли падать CI\CD билды.
Все указывало на то, что что то случилось с переменными.
Оказалось, что в Turbo 2 появилась
И чтобы справится с этим, нужно при запуске задач ставить
--env-mode=loose
Вот такая вот
🔥4
Media is too big
VIEW IN TELEGRAM
Хеви металл, который мы заслужили
Теперь ты можешь слушать металл и учить Java.
Итальянцы Nanowar спели код)
Ссылка на ютуб тоже есть
https://www.youtube.com/watch?v=yup8gIXxWDU
P.S. Концовка убила..
Теперь ты можешь слушать металл и учить Java.
Итальянцы Nanowar спели код)
Ссылка на ютуб тоже есть
https://www.youtube.com/watch?v=yup8gIXxWDU
P.S. Концовка убила..
🔥3🤣1
Если вдруг у вас сегодня перестала билдиться призма на alpine, посмотрите эту issue https://github.com/nodejs/docker-node/issues/2175
GitHub
Prisma failing on changed OpenSSL path in Alpine 3.21 · Issue #2175 · nodejs/docker-node
I have a project that uses Prisma. Until few months ago there was no issue with the image but today if I try to build the docker image with following, Prisma fails to build as it does not find open...
👍4
Отрицательные даты
Сегодня была ржакаобоссака у нас в Funlee.
Значит прилетает с утра 3 оплаты за год, мы такие "ура открываем шампанское!"
Тут дизайнер прибегает, "эй, какого х.. вы у меня с карты пытались 27к списать??!!!!1111"
Я такой - "так, подержи мой бокал", начинаю проверять, смотрю аккаунт знакомый, смотрю значит свой телефон, а у меня там успешно списано 27к.
Тут еще бро пишет, "Э брат, вы чо ох..ли там? Почему у меня с карты улетело на ваш сервис 27к?, при том что у меня промокод бессрочный на 99%??!!!".
Ну кароч сделали возвраты, стали разбираться. Поняли, что это вообще оплата за месяц, а не за год :)
Но тесты же, сука, проходят...
Ну я попросил ребят разобраться, но как обычно (был послан на...), пошел разбираться сам.
В итоге оказалось, что расчет применения скидки по промику не учитывал, что у нас могут быть промокоды без срока действия.
В итоге у нас выходило отрицательное количество месяцев и получалась ох.вшая сумма.
Как жаль, богатство было так близко...
Сегодня была ржака
Значит прилетает с утра 3 оплаты за год, мы такие "ура открываем шампанское!"
Тут дизайнер прибегает, "эй, какого х.. вы у меня с карты пытались 27к списать??!!!!1111"
Я такой - "так, подержи мой бокал", начинаю проверять, смотрю аккаунт знакомый, смотрю значит свой телефон, а у меня там успешно списано 27к.
Тут еще бро пишет, "Э брат, вы чо ох..ли там? Почему у меня с карты улетело на ваш сервис 27к?, при том что у меня промокод бессрочный на 99%??!!!".
Ну кароч сделали возвраты, стали разбираться. Поняли, что это вообще оплата за месяц, а не за год :)
Но тесты же, сука, проходят...
Ну я попросил ребят разобраться, но как обычно (
В итоге оказалось, что расчет применения скидки по промику не учитывал, что у нас могут быть промокоды без срока действия.
// Когда заканчивается скидка по промокоду.
const discountEnds = dayjs(promocode.appliedDate)
.add(promocode.durationMonths ?? 0, 'months')
// Добавляем резервный период. Он позволяет менять тарифный план и опции после применения промокода.
// Если пользователь применил промокод и оплатил тариф, а через день хочет поменять тариф на другой,
// то без этого периода промокод применён не будет (хотя в теории ещё есть 29 дней).
.add(promocode.daysLimitForPromoUse ?? 14, 'days');
const monthsLeft = dayjs(discountEnds).diff(dayjs(now), 'months');
В итоге у нас выходило отрицательное количество месяцев и получалась ох.вшая сумма.
Как жаль, богатство было так близко...
😁7👍2
Я вот сегодня заметил, что Codeium стал подсказывать какую то лютую дичь. Ну то есть больше мешать, чем помогать, контекста вообще не понимает железный болванчик. Что посоветуете вместо?
Key в React
Мы привыкли, что key используется только для рендера списков. Но использование key не ограничивается только этим.
Изменение key показывает React что это другой компонент, и необходимо старый размонтировать, а новый замонтировать.
Мы например можем добавить prop key к компоненту формы
Таким образом если userId изменится, то вся форма размонтируется и смонтируется новая форма, и нам не придется обнулять значения формы руками при изменении пользователя.
BEARlogin dev
#react #advices #собеседования
Мы привыкли, что key используется только для рендера списков. Но использование key не ограничивается только этим.
Изменение key показывает React что это другой компонент, и необходимо старый размонтировать, а новый замонтировать.
Мы например можем добавить prop key к компоненту формы
<UserForm key={userId} />Таким образом если userId изменится, то вся форма размонтируется и смонтируется новая форма, и нам не придется обнулять значения формы руками при изменении пользователя.
BEARlogin dev
#react #advices #собеседования
🔥16💯4
Только я решил сузить тему канала до React\JS\TS, но не могу не поделится этим лайфхаком.
Кароче, когда режете лук, в рот воды наберите, и глаза болеть не будут!
Это какая долбаная магия, но работает!
Кароче, когда режете лук, в рот воды наберите, и глаза болеть не будут!
Это какая долбаная магия, но работает!
😁12🔥8
setState функция в React
Допустим у нас есть какой то state.
Так вот, setCount не нужно оборачивать в useCallback (некоторые так делают) при передаче его как пропс в дочерний компонент.
React гарантирует, что функция setState не изменится между рендерами.
Так же не нужно добавлять ее в зависимости useEffect, useMemo и useCallback.
Если не верите, то добавьте
Но если я вдруг ошибаюсь, и кейс мемоизации сетера действительно существует, то напишите в комменты :)
BEARlogin dev
#react #advices #собеседования
Допустим у нас есть какой то state.
const [count, setCount] = useState(0);
return <SomeComponent setCount={setCount} />
Так вот, setCount не нужно оборачивать в useCallback (некоторые так делают) при передаче его как пропс в дочерний компонент.
React гарантирует, что функция setState не изменится между рендерами.
Так же не нужно добавлять ее в зависимости useEffect, useMemo и useCallback.
Если не верите, то добавьте
useEffect(() => {
console.log('It has changed!!!!! AAAAAaaaa!!!!11111')
},[setCount])Но если я вдруг ошибаюсь, и кейс мемоизации сетера действительно существует, то напишите в комменты :)
BEARlogin dev
#react #advices #собеседования
👍4
SRP как много в этом звуке...
Буква S в SOLID вызвала больше холиварови разбитых лиц чем React vs {anyFrontendFramework}.
Что тут имел в виду Дядя Боб, да хер его знает этих гениев, скажем мы и пойдем дальше пилить таски из жиры.
Но к счастью для нас он уточнил потом в Clean Architecture
Тоже нихера непонятно, но уже можно размышлять. Что есть актор?
Актор — это кто-то или что-то, кто требует от твоего модуля выполнения задачи.
Это может быть:
- Пользователь, нажимающий на кнопки в интерфейсе.
- Соседний модуль, который вызывает твою функцию.
- Даже система, которая запускает твой код по расписанию.
Каждый актор — это внешний драйвер, который влияет на твою логику.
И вот что важно: модуль должен обслуживать только одного актора.
Понятней не стало?
Ок, приведем пример:
Представим, что нам нужно для пользователя добавить возможность указать комментарий к заказу.
Мы идём в OrderService и меняем его.
А теперь нужно дать менеджеру возможность перенести доставку на другую дату.
Мы снова идём в OrderService и меняем его.
И вот тут всё встаёт на свои места. Вот она "причина" для изменений. Это вот этот самый актор — драйвер изменений.
Итог: два актора на один класс. На лицо нарушение принципа SRP.
Что делать?
Разделить сервисы, чтобы они работали только с одним актором.
Надеюсь вы теперь понимаете, насколько глубже был этот принцип, относительно упрощенной, ошибочной интерпретации "Один класс решает одну задачу." распространенной на просторах интернета.
Вспоминается анекдот про "Рабинович напел" :)
SRP не про то, что делает класс, а про причину его изменений. Про, если хотите, заказчика, драйвера этих изменений.
P.S. Вы могли заметить, что для соблюдения SRP нам пришлось дублировать методы. А как же DRY??!!
Я мог бы сказать перефразируя цитату классика
Но не буду, и расскрою эту тему в дальнейших постах, так как в архитектуре все зависит от контекста(с).
STAY TUNE)
BEARlogin dev — подпишись!
#архитектура #advices #solid
Буква S в SOLID вызвала больше холиваров
Его классическое определение - Класс должен иметь лишь одну причину для изменений.
Что тут имел в виду Дядя Боб, да хер его знает этих гениев, скажем мы и пойдем дальше пилить таски из жиры.
Но к счастью для нас он уточнил потом в Clean Architecture
Модуль должен отвечать перед одним и только одним актором.
Тоже нихера непонятно, но уже можно размышлять. Что есть актор?
Актор — это кто-то или что-то, кто требует от твоего модуля выполнения задачи.
Это может быть:
- Пользователь, нажимающий на кнопки в интерфейсе.
- Соседний модуль, который вызывает твою функцию.
- Даже система, которая запускает твой код по расписанию.
Каждый актор — это внешний драйвер, который влияет на твою логику.
И вот что важно: модуль должен обслуживать только одного актора.
Понятней не стало?
Ок, приведем пример:
class OrderService {
createOrder(orderData) {
// Покупатель создает заказ
}
getOrderDetails(orderId) {
// Покупатель и менеджер получают информацию о заказе
}
updateOrderStatus(orderId, status) {
// Менеджер меняет статус заказа
}
cancelOrder(orderId) {
// Покупатель отменяет заказ
}
}Представим, что нам нужно для пользователя добавить возможность указать комментарий к заказу.
Мы идём в OrderService и меняем его.
А теперь нужно дать менеджеру возможность перенести доставку на другую дату.
Мы снова идём в OrderService и меняем его.
И вот тут всё встаёт на свои места. Вот она "причина" для изменений. Это вот этот самый актор — драйвер изменений.
Итог: два актора на один класс. На лицо нарушение принципа SRP.
Что делать?
Разделить сервисы, чтобы они работали только с одним актором.
// Модуль для покупателя
class CustomerOrderService {
createOrder(orderData) {
// Логика создания заказа
}
getOrderDetails(orderId) {
// Логика получения деталей заказа для покупателя
}
cancelOrder(orderId) {
// Логика отмены заказа
}
createOrder(orderData) {
// Логика создания заказа для покупателя
}
}
// Модуль для менеджера
class ManagerOrderService {
getOrderDetails(orderId) {
// Логика получения деталей заказа для менеджера
}
updateOrderStatus(orderId, status) {
// Логика изменения статуса заказа
}
changeDeliveryDateTime(orderId, dateTime) {
// Логика изменения доставки
}
cancelOrder(orderId) {
// Логика отмены заказа
}
}
Надеюсь вы теперь понимаете, насколько глубже был этот принцип, относительно упрощенной, ошибочной интерпретации "Один класс решает одну задачу." распространенной на просторах интернета.
Вспоминается анекдот про "Рабинович напел" :)
SRP не про то, что делает класс, а про причину его изменений. Про, если хотите, заказчика, драйвера этих изменений.
P.S. Вы могли заметить, что для соблюдения SRP нам пришлось дублировать методы. А как же DRY??!!
Я мог бы сказать перефразируя цитату классика
Он нам и нах... не нужон DRY ваш!
Но не буду, и расскрою эту тему в дальнейших постах, так как в архитектуре все зависит от контекста(с).
STAY TUNE)
BEARlogin dev — подпишись!
#архитектура #advices #solid
🔥15👍7
Чистые и нечистые компоненты в React
Деление на чистые компоненты и нечистые контейнеры — это одна из best practice в React, которая помогает сделать код чище и проще в поддержке.
Но следование этому подходу требует дисциплины от разработчика.
Чистые компоненты
Чистые компоненты делают только одно: отображают данные. Они получают всё через props и не хранят никакого состояния. Это их главная сила — такие компоненты легко переиспользовать и тестировать.
Пример:
UserCard не знает, откуда взялись name и age. Ему должно быть всё равно, как эти данные попали в props. Его задача — просто показать их.
Чистые компоненты не должны:
1. Иметь своего состояния или использовать чужое (useState, useSelector и т.д.).
3. Работать с useEffect или другими хуками, которые создают сайд-эффекты.
4. Хранить бизнес-логику.
Да, из-за этого приходится писать больше кода. Но код становится чище.
Нечистые контейнеры
Нечистые контейнеры — это такие "оркестраторы", которые работают с данными: загружают их, хранят в состоянии и передают чистым компонентам. Они могут содержать сайд-эффекты, такие как запросы к API, диспатчинг действий в redux и т.д.
Пример:
Контейнер берёт на себя всю грязную работу: он загружает данные и передаёт их в UserCard. А UserCard продолжает оставаться чистым и ничего не знает про состояние или API.
BEARlogin dev — подпишись!
#react #advices #собеседования
Деление на чистые компоненты и нечистые контейнеры — это одна из best practice в React, которая помогает сделать код чище и проще в поддержке.
Но следование этому подходу требует дисциплины от разработчика.
Чистые компоненты
Чистые компоненты делают только одно: отображают данные. Они получают всё через props и не хранят никакого состояния. Это их главная сила — такие компоненты легко переиспользовать и тестировать.
Пример:
function UserCard({ name, age }) {
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
</div>
);
}UserCard не знает, откуда взялись name и age. Ему должно быть всё равно, как эти данные попали в props. Его задача — просто показать их.
Чистые компоненты не должны:
1. Иметь своего состояния или использовать чужое (useState, useSelector и т.д.).
3. Работать с useEffect или другими хуками, которые создают сайд-эффекты.
4. Хранить бизнес-логику.
Да, из-за этого приходится писать больше кода. Но код становится чище.
Нечистые контейнеры
Нечистые контейнеры — это такие "оркестраторы", которые работают с данными: загружают их, хранят в состоянии и передают чистым компонентам. Они могут содержать сайд-эффекты, такие как запросы к API, диспатчинг действий в redux и т.д.
Пример:
function UserContainer() {
const user = useSelector(state => state.currentUser);
return user ? <UserCard name={user.name} age={user.age} /> : <p>Loading...</p>;
}Контейнер берёт на себя всю грязную работу: он загружает данные и передаёт их в UserCard. А UserCard продолжает оставаться чистым и ничего не знает про состояние или API.
BEARlogin dev — подпишись!
#react #advices #собеседования
🔥7👍1👎1
Когда используется значение, переданное в createContext?
Многие считают, что если
Но это не так.
На самом деле значение, переданное в
Пример:
#react #advices #собеседования
Многие считают, что если
value в провайдере не определен, то используется значение по умолчанию. Но это не так.
На самом деле значение, переданное в
createContext, будет использовано только тогда, когда React не найдёт подходящего провайдера в родителях компонента. Пример:
// Создаём контекст с "default value" как значением по умолчанию
const MyContext = React.createContext("default value");
function MyContextProvider() {
// В провайдере используем состояние с изначальным значением undefined
const [contextValue, setContextValue] = useState(undefined);
return (
<MyContext.Provider value={contextValue}>
<ChildComponent />
<button onClick={() => setContextValue("updated value")}>
Update Context
</button>
</MyContext.Provider>
);
}
function ChildComponent() {
// Используем значение из контекста
const value = useContext(MyContext);
return <p>Value from context: {value}</p>;
}
function App() {
return (
<>
<h1>Without Provider</h1>
<ChildComponent /> {/* value: "default value" */}
<h1>With Provider</h1>
<MyContextProvider>
<ChildComponent />
</MyContextProvider>
{/* value: undefined → "updated value" после нажатия кнопки */}
</>
);
}
#react #advices #собеседования
🔥8👍2
Пересчитаемся, кто тут кто?
Anonymous Poll
57%
Front
12%
Back
21%
Fullstack
4%
Devops
0%
Product
1%
Project
2%
C-level
1%
Devops
0%
Mobile
1%
Design
Что происходит в момент, когда мы вызываем setState?
Многие говорят, что обновляется state. Но это не совсем так.
Приведу пример
Работа с функциональными компонентами создаёт иллюзию, будто мы оперируем с императивным подходом: то, что мы видим, — это и есть реальность. Но это лишь фасад. На самом деле React использует декларативный подход.(Я вообще молчу, что у нас count объявлена константой и чисто физически не может изменится)
Что это значит? Это значит, что мы говорим React, какое состояние компонента хотим получить. А дальше начинается магия: React планирует изменения, запускает рендер, и мы не знаем точно, когда состояние действительно обновится и изменения попадут в реальный DOM.
Внутренности процесса
Когда React обновляет дерево компонентов, он делит эту работу на кусочки. Почему? Чтобы уложиться в определённое время — около 16.6 мс на кадр при 60 fps. Если React не успевает, он приостанавливает процесс и продолжает позже.
Но на этом всё не заканчивается. Когда рендер завершён, React сверяет новое дерево с предыдущим (reconciliation). Только после этого, одной синхронной задачей, обновляется реальный DOM — это называется "коммит".
Если интересна такая "внутрянка" React ставьте🔥 и я раскрою глубже, как происходит render, сверка, что такое Fiber и т.д.
BEARlogin dev — подпишись!
#react #advices #собеседования
Многие говорят, что обновляется state. Но это не совсем так.
Приведу пример
const [count, setCount] = useState(0)
function updateCount(value) {
setCount(value);
console.log(count); // в этом месте много людей на собесе говорили мне, что console.log выведет значение value
}
Работа с функциональными компонентами создаёт иллюзию, будто мы оперируем с императивным подходом: то, что мы видим, — это и есть реальность. Но это лишь фасад. На самом деле React использует декларативный подход.
Что это значит? Это значит, что мы говорим React, какое состояние компонента хотим получить. А дальше начинается магия: React планирует изменения, запускает рендер, и мы не знаем точно, когда состояние действительно обновится и изменения попадут в реальный DOM.
Внутренности процесса
Когда React обновляет дерево компонентов, он делит эту работу на кусочки. Почему? Чтобы уложиться в определённое время — около 16.6 мс на кадр при 60 fps. Если React не успевает, он приостанавливает процесс и продолжает позже.
Но на этом всё не заканчивается. Когда рендер завершён, React сверяет новое дерево с предыдущим (reconciliation). Только после этого, одной синхронной задачей, обновляется реальный DOM — это называется "коммит".
Если интересна такая "внутрянка" React ставьте
BEARlogin dev — подпишись!
#react #advices #собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥62👎1
Камрад в коментах упоминул про случай, когда у нас множество обновлений, описанный в доке реакта и который любят спрашивать на собесах.
У нас есть функция которая вызывает последовательно обновления state.
Вопрос: чему в итоге будет равен count и сколько раз будет вызван render?
Чтобы разобраться в этом, нужно понять как вообще планируются обновления.
Такие вызовы — это тоже самое, что написать setCount(0 + 1) три раза.
Очередь обновлений можно упрощенно показать так (подробней эту тему раскрою в постах про Fiber)
И когда React переходит к фазе рендеринга, он проходит по этом списку и применяет count равным 1 все три раза.
В итоге рендер будет вызван 1 раз, а count = 1
Но если мы применим функциональные обновления
То очередь обновлений будет выглядеть так
Во время рендеринга:
Первое обновление: count = 0 + 1 = 1.
Второе обновление: count = 1 + 1 = 2.
Третье обновление: count = 2 + 1 = 3.
В итоге render будет вызван всегда 1 раз в этих случаях, но в функции обновления мы будем всегда получать результат предыдущего обновления в параметры функции и в таком случае инкремент будет работать правильно.
Другой вопрос, что будет если обновлений запланируется, ну скажем 100 000 сразу. Такой случай рассмотрю в следующих постах.
ставьте🔥 если зашло :)
BEARlogin dev — подпишись!
#react #advices #собеседования
У нас есть функция которая вызывает последовательно обновления state.
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};
Вопрос: чему в итоге будет равен count и сколько раз будет вызван render?
Чтобы разобраться в этом, нужно понять как вообще планируются обновления.
Такие вызовы — это тоже самое, что написать setCount(0 + 1) три раза.
Очередь обновлений можно упрощенно показать так (подробней эту тему раскрою в постах про Fiber)
baseQueue = {
action: 1,
next: {
action: 1,
next: {
action: 1
}
}
}И когда React переходит к фазе рендеринга, он проходит по этом списку и применяет count равным 1 все три раза.
В итоге рендер будет вызван 1 раз, а count = 1
Но если мы применим функциональные обновления
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
То очередь обновлений будет выглядеть так
baseQueue = {
action: (prev) => prev + 1,
next: {
action: (prev) => prev + 1,
next: {
action: (prev) => prev + 1
}
}
}Во время рендеринга:
Первое обновление: count = 0 + 1 = 1.
Второе обновление: count = 1 + 1 = 2.
Третье обновление: count = 2 + 1 = 3.
В итоге render будет вызван всегда 1 раз в этих случаях, но в функции обновления мы будем всегда получать результат предыдущего обновления в параметры функции и в таком случае инкремент будет работать правильно.
Другой вопрос, что будет если обновлений запланируется, ну скажем 100 000 сразу. Такой случай рассмотрю в следующих постах.
ставьте
BEARlogin dev — подпишись!
#react #advices #собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥30
FSD: дело было не в бобине...
Часто слышу критику FSD: "Слишком много папок, слишком много правил, это избыточно!".
Но хочу сказать, что FSD — это не про количество папок. Это про направление зависимостей и архитектурные границы.
Ты не обязан сразу строить многоэтажный небоскрёб, если у тебя пока маленький проект. Начать можно просто.
С чего начинать?
На старте достаточно трёх слоёв:
1. app/ — конфигурация приложения: роутинг, провайдеры, глобальные стили.
2. shared/ — переиспользуемые, не связанные с бизнесом компоненты, утилиты, стили и т.д.
3. pages/ — страницы приложения и используемые ими компоненты.
Сначала можно оставить всё в pages, если функциональность используется только там.
Но как только начинаешь дублировать код, либо твой слайс хочет что то импортировать у соседей, то логично вынести его в widgets.
А затем продолжаешь углублять структуру. Например, если два widget используют схожую логику или функциональность, то логично вынести её в features. Дальше это движение продолжается по мере необходимости.
Что касается entities и shared, то здесь есть определённая специфика. Об этом я расскажу в следующих постах.
Вынос в новый сегмент какого то функционала не является самоцелью. Я бы сказал, даже наоборот — если можно не выносить и остаться в рамках одного слайса — оставайтесь.
Таким образом FSD подходят для любых проектов на старте, позволяя сразу закладывать возможности для масштабирования и помогает соблюдать принципы низкой связанности и высокого зацепления.
Ставьте🔥 , если хотите больше практических примеров и советов по FSD.
BEARlogin dev — подпишись!
P.S. советую этот экстеншн для генерации слайсов https://marketplace.visualstudio.com/items?itemName=SbokyZahodi.fsd-slices
#архитектура #frontend #fsd
Подготовлю к собесам, помогу с рабочими задачами и росту хардов/софтов. Уперся в потолок с з/п, ответственностью?
Если необходимо менторство - пишите @bearlogin
Часто слышу критику FSD: "Слишком много папок, слишком много правил, это избыточно!".
Но хочу сказать, что FSD — это не про количество папок. Это про направление зависимостей и архитектурные границы.
Ты не обязан сразу строить многоэтажный небоскрёб, если у тебя пока маленький проект. Начать можно просто.
Кстати, само название FSD (Feature-Sliced Design), на мой взгляд, не совсем корректно. Это не "дизайн, разделенный на фичи". Скорее, это методология, которая помогает структурировать код, организуя его вокруг бизнес-функционала и уровней ответственности, позволяя соблюдать принципы Low coupling и High cohesion.
Можете в комментариях предложить своё название. Лично я бы назвал это Business-Sliced Design — чтобы невозможно было интерпретировать методологию упрощённо и требовалось изучение её сути.
С чего начинать?
На старте достаточно трёх слоёв:
1. app/ — конфигурация приложения: роутинг, провайдеры, глобальные стили.
2. shared/ — переиспользуемые, не связанные с бизнесом компоненты, утилиты, стили и т.д.
3. pages/ — страницы приложения и используемые ими компоненты.
src/
app/
App.tsx
routes.ts
shared/
ui/
Button/
index.tsx
pages/
catalog/
ui/
CatalogPage.tsx
ProductList.tsx //кандидат на вынос
index.ts
recommended/
ui/
RecommendedPage.tsx
ProductList.tsx
index.ts
Сначала можно оставить всё в pages, если функциональность используется только там.
Но как только начинаешь дублировать код, либо твой слайс хочет что то импортировать у соседей, то логично вынести его в widgets.
src/
app/
App.tsx
routes.ts
shared/
ui/
Button/
index.tsx
widgets/
product-list/
ui/
ProductList.tsx
model/
useProducts.ts
index.ts
pages/
catalog/
ui/
CatalogPage.tsx
index.ts
recommended/
ui/
RecommendedPage.tsx
index.ts
А затем продолжаешь углублять структуру. Например, если два widget используют схожую логику или функциональность, то логично вынести её в features. Дальше это движение продолжается по мере необходимости.
Что касается entities и shared, то здесь есть определённая специфика. Об этом я расскажу в следующих постах.
Вынос в новый сегмент какого то функционала не является самоцелью. Я бы сказал, даже наоборот — если можно не выносить и остаться в рамках одного слайса — оставайтесь.
Таким образом FSD подходят для любых проектов на старте, позволяя сразу закладывать возможности для масштабирования и помогает соблюдать принципы низкой связанности и высокого зацепления.
Ставьте
BEARlogin dev — подпишись!
P.S. советую этот экстеншн для генерации слайсов https://marketplace.visualstudio.com/items?itemName=SbokyZahodi.fsd-slices
#архитектура #frontend #fsd
Подготовлю к собесам, помогу с рабочими задачами и росту хардов/софтов. Уперся в потолок с з/п, ответственностью?
Если необходимо менторство - пишите @bearlogin
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥31👎10👍9😱1🗿1