React как view устарел) Его подход с ререндером компонентов даже с Mobx вызывает всю цепочку сравнений VDOM. В целом он очень неоптимизирован. React is ecosystem пока остается актуальным.
В вашем контексте "разработка навынос", то есть заказная, сроки - сжатые, команда - минимальная и низкой квалификации, статья и аргументы годные для "песочницы". Но Хабру это пользы не несет, поэтому поставил минус за низкое качество материала. После 20 таких проектов - сами увидите, насколько плох был подход и подобранные библиотеки.
"возьми почитал" мобильный Сафари 17.2. Интересно, на какие страны вы делаете приложения - в Америке валом старых айфонов, в России - тем более, в Азии 17 еще не видели.
В контексте "еще в 2021 css убил scss" ну сами посмотрите
Ну Mobx не то чтобы сложен. Пишем в обычном стиле где сторы и ViewModel - это классы, добавляем makeAutoObservable - получаем автоматический точечный ререндер компонентов при изменении только тех свойств, которые используются в компоненте.
Но тут согласен, от команды многое зависит - если совсем никто не пользовался, то обучение будет дольше, а если хоть один - то очень быстро других обучит.
А вот чем CSS Modules и scss не угодили?
Модули позволяют исключить пересечение стилей между компонентами, дают быстрый переход на место объявления, позволяют настраивать именование класса (например включать путь src-components-layouts-layoutWrapper), что создает ясный идентификатор для компонентов. Для e2e тестов не подойдет, но для дебага - прекрасно, сразу видно кнопку в каком из 100 компонентов, использующих кнопки, нажал пользователь и получил ошибку. Также при желании можно настроить генерацию d.ts файлов из стилей, чтобы найти все неиспользуемые классы (на постоянной основе - нежелательно, но в качестве плановой оптимизации раз в 3 месяца - отлично).
Scss - это миксины, nesting (вложение одних классов в другие), математика и циклы, удобные импорты. Не обязательно использовать именно препроцессоры - можно использовать сразу постпроцессоры (PostCSS) с соответствующим интерпретатором. Во многих проектах постпроцессор и так используется (для автопрефикса и оптимизации например), и добавление scss не сильно ухудшит перфоманс сборки, но добавит удобный DX.
Ну, про FSD, TanStack Router, TanStack Query и Effector я согласен с предыдущим комментатором, что сейчас это самое неэффективное, и это никак не связано с годом их выпуска. Но популярных альтернатив лучше и правда мало, и если сжатые сроки - то можно и затянуть в проект, особенно если команда хорошо с ними знакома.
Спасибо, перешел в одном проекте с Prettier на него - скорость полного линтинга сократилась с 8.5с до 7с. Порадовало количество настроек и их гибкость, однако для совпадения с предыдущим форматированием через Prettier пришлось детально понастраивать - только лишь stylistic.configs.customize не дало нужного результата.
В Реакте действительно особое поведение для контролируемых инпутов, я привел в статье ссылку на issue, где обсуждается этот вопрос и приводятся десятки вариантов решения. Там довольно подробно описывали сложности реализации, например здесь
У Реакта другая система реактивности - изменения Preact signals не будут вызывать ререндер компонента, а если с адаптером - то все равно не будет точечных апдейтов без ручной оптимизации. То есть на мой взгляд привязка к Preact будет достаточно сильная.
Для осуществления глубокой реактивности (не только примитивов), как вы правильно заметили, тоже будет необходима дополнительная библиотека, и по размеру код думаю приблизится к Preact+MobX, учитывая все нюансы.
Не спорю, что если использовать только 1 фреймворк, то можно оптимизировать код, однако мне было интересно именно side-to-side сравнение, поэтому взял MobX для связки с Preact.
Да, есть немало библиотек, в том числе для Solid, которые решают эту проблему. Но если в приложении пара инпутов и не хочется раздувать размер бандла, то в контролируемых инпутах Реакта все решается намного проще, чем в неконтролируемых Солида.
Для Реакта я мог использовать простые regexp для запрета ввода некорректных символов, теперь же приходится все делать через сторонние библиотеки. Не то, чтобы это вызывало серьезные неудобства, но отсутствие привычного функционала портит впечатление от фреймворка.
Да, меня тоже смущает, что Painting отличается на 50%. Думаю, тут дело в ререндерах и отсутствии оптимизации для Реакта (если бы выносил больше компонентов и они точечно обновлялись - то меньше бы было), об этом написал в статье.
Page1 - Page 2 не реактивные, а прод-приложение, из которого приводил метрики - реактивные, там есть изменения в структуре разметки, динамические элементы, показы по условию, изменения стилей и т.п. Делать что-то сложное в Реактосолиде я не стал - просто сгенерировал статику через AI и убрал 80% архитектуры прод-приложения. Можно самостоятельно для интереса сделать что-то более сложное - думаю, различия в перфомансе будут более явными.
Preact+Signals, к сожалению, совсем не поддерживает реактивные классы и завязывается на написание логики внутри компонента - этот подход не адаптировать под ViewModel и MobX. Перфоманс, уверен, будет лучше, но и ограничения явные - сильная привязка к Preact и невозможность быстрого переключения на React/Solid. Для меня же Solid был новым опытом, и оставить себе "путь отступления" было крайне важным на старте - хотя после написания проекта это оказалось избыточным, экосистемы и возможностей Solid хватило с лихвой.
Некст вне контекста статьи, как и мегабайты картинок. Контролируемые инпуты нужны для фильтрации того, что вводит пользователь. Попробуйте на нативном инпуте нативно обработать oninput, onchange, onpaste, onkeypress, onkeydown c учетом мобильных браузеров и всех версий операционки и разрешить скажем ввод "a-b". Это очень нетривиальная задача, если у вас в наличии десятки устройств.
Добавьте обработку маски и позицию каретки для удобного редактирования.
Мне была важна возможность перехода на React/Preact+MobX если не хватит экосистемы, поэтому детали реактивности были не важны - главное, чтобы была возможность делать реактивные инстансы классов по аналогии с MobX. Что под капотом - геттеры-сеттеры, прокси или сигналы не так важно, если они дают достаточный перфоманс и не налагают серьезных ограничений.
Конечно, есть фреймворки, предлагающие менее 5.78 kb на старте, но не с jsx синтаксисом и без возможности практически безболезненно переключаться на другие фреймворки.
Если вы это серьезно, то крайне недооцениваете классическую структуру.
Несколько "связанных модалок" - это несколько "независимых модалок, вызываемых колбеками при закрытии со статусом успех". Эти модалки лежат в components/modal/lib и могут вызывать друг друга. Если они вызываются только с одной страницы - то будут лежать в папке страницы.
Что за modules (модули) в замену семантичным pages не понимаю. Звучит как заменим "страницу" на "модуль" - как это можно вообще придумать?
Показ баннера - компонент лежит в components/banner, вызывается параметром в глобальном сторе showBanner: boolean. Этот компонент смотрит в глобальный стор и при изменении значения отображается. Он не зависит от страниц.
"кнопка которая меняет дизайн в зависимости от наличия подписки" - интересный кейс, то есть если передал onClick то один вид, если не передал - то другой. Решается маппером в компоненте components/button. Если ей нужен значок - он передается через проп <Button leftIcon={''} rightIcon={''} />, никакой необходимости делать дубляжи компонентов на каждый проп нет.
Функции форматирования строк складываются в utils/formatString, которая экспортирует объект с 100 разными видами форматирования, если это нужно проекту. Это по факту исключает дубляж - глазами пробежаться по методам куда проще, чем искать в море widgets, entity, app, feature и т.п. разнородных файлов с форматированиями.
Нападки в целом "из пальца", попробуйте сами в классике писать - там нет перечисленных проблем)
хорошо структурированный и понятный проект позволет лучше его понимать, и соотвественно его и рефакторить проще снижая техдол, и от дублирования кода избавлятся, и переосмысливать связи между компонентами. Все эти шаги проще делать при разбиении по доменам
Вы про это? Ну, я не поддерживаю Клерика в плане, что микрофронты - хорошее решение, но в остальном согласен с его позицией.
И, к сожалению, вашу позицию про FSD как способ "хорошо структурировать проект по доменным областям", который решает описанные в цитате проблемы - не могу поддержать.
В классике есть домены - это страницы src/pages/somePage. Это понятная и хорошо структурированная система, синхронизированная с роутингом. Рефакторить очень просто, риск дубляжа сведен к минимуму за счет глобальных слоев, связи между слоями достаточно четкие.
Проблема "свалки в коде" существует в классике, это верно, но она возникает только когда проект перерастает продвинуто-средний размер (30+ страниц, 50+ компонентов, 70+ вызовов апи). И для решения этой проблемы масштабируемости есть ряд способов - микрофронты это один вариант, как описано выше, монорепа с выделением ряда страниц - другой вариант, здесь все зависит от архитектора. Возможен и вариант развития классики "в глубину" - сгруппировать страницы по папкам, выделив слои внутри них.
Но с такими большими проектами редко сталкиваешься, а если да - то там достаточно опыта для наиболее грамотного выбора структуры, подходящей проекту.
Проблема наименований в роутере и в проекте - в проекте 200 страниц, из них нужно сгруппировать 10, и это не ложится в термин "страница". Здесь ключевое - "нужно сгруппировать", то есть пришла некая задача от бизнеса или архитектора - эти страницы нужно куда-то выделить. Очевидное решение - в новый app, то есть приложение, содержащее эти страницы + всю необходимую для них логику. Термин "приложение" не противоречит классической структуре, и верно, что "страницей" его называть не правильно. Но в контексте роутера это - набор страниц, роутер не должен знать о структуре и фреймворках, используемых в отдельных "приложениях", из которых формируется единое "приложение". Роутер существует в едином контексте - это вкладка браузера и URL, а откуда берутся компоненты для страниц - это детали реализации. Поэтому я не вижу здесь логических ошибок - роутинг и структура проекта это разные вещи.
Да, есть проекты из 1 страницы - лендинги или "виджеты", которые встраиваются в сторонние сайты и например отображают погоду. Они тоже хорошо ложатся на классическую структуру - будет 0 страниц (только корневой App) и набор компонентов, которые там отображаются, и не будет слоя роутинга.
Про микрофронтенды я написал в контексте треда. Я согласен, что они по большей части неэффективны и избыточны, а для работы разных команд над одним проектом часто достаточно монорепы и организационных ограничений. По крайней мере до 5 команд на моем опыте комфортно уживались без существенных блоков для других команд в монорепе. А вот аналогичный опыт с разделением по микрофронтам был очень негативным, так что я тоже использовал бы их только в крайнем случае. Написал пример для микрофронтов в комменте выше только для того, чтобы показать, что классическая структура не мешает их выделить.
В целом вы видимо хотите перевести тред в тему "нужны ли микрофронты", но для этого есть куча статей о них, я по крайней мере там выступаю как противник данного подхода. Здесь же обсуждается структура папок и взаимосвязей, немного другой контекст
Но это будет немного не то, что в классике, думаю. Там глобальный слой апи могут вызывать все, кто хочет получить эти данные, они будут сложены в глобальный стор. Компонент всегда лежит в src/components, не нужно его искать по entity/ui, widgets/ui/ui/ui. features/ui/ui/ui/ui. Условно, классика - это все shared (components), пока не потребуется положить в page. Один из нас думает локальностью и изолированностью, другой - глобальностью и что нужно класть в модуль только при необходимости) У обоих разные проблемы, но в целом одинаковые
Ключевое - роутинг. У вас в проекте за него отвечает отдельный фреймворк, но это ключевая часть - синхронизировать урл и отображение. Второе - автоматизация, это хоть и невидимая часть в вашем проекте, но играет существенную роль (от сборщика до скрытой логики). Третье - организация стилей, которая подчиняется своим правилам каскадности и CSSOM и строится по отдельному дереву. Четвертое - очевидное - иерархия взаимодействия, чего нет в FSD, насколько знаю, там в основном все через хаки. Ну есть еще несколько моментов)
Как разработчика меня интересуют только метрики профайлера + структура в дев тулз + легкий поиск из html конкретного компонента + достаточно емкие логи в Sentry, чтобы найти все баги за "поиск по проекту". Не столь важно различие, как мы кладем папки и файлы и их связываем.
Но я же не об этом говорил в комменте, а указал, что вы в ряде утверждений ввели в заблуждение относительно содержания статьи, триггернули человека, захейтили и унизили за то, что показал на это - возможно, немного грубым способом. Но это же ваша статья и ваша аудитория разработчиков, причем опытных. Я тоже так в своих статьях поначалу поступал, за что даже себе минус в карму пытался поставить) Затем, как и вы, старался вывести на конструктивный диалог - а если не получалось, то не оскорблял.
У меня есть старый бойлерплейт https://github.com/dkazakov8/dk-boilerplate , в нем классическая структура является основой слоистой архитектуры. Боюсь, разговор об архитектурах не впишется в формат комментов, это слишком большая тема)
И вам спасибо за качественный ответ по всем пунктам)
Я бы тоже перевел ваш проект на классику и показал преимущества, однако для ближайшей статьи запланировал библиотеку роутинга, лишенную всех проблем React Router и Tanstack. Лет 8 ей занимался, но для вашего проекта она не будет полезна - стек уже выбран)
Значит, существенную дискуссию переведем под следующую вашу статью. К слову, не путайте архитектуру и структуру, FSD - это лишь структура папок и их взаимосвязей, маленькая часть архитектуры)
React как view устарел) Его подход с ререндером компонентов даже с Mobx вызывает всю цепочку сравнений VDOM. В целом он очень неоптимизирован. React is ecosystem пока остается актуальным.
В вашем контексте "разработка навынос", то есть заказная, сроки - сжатые, команда - минимальная и низкой квалификации, статья и аргументы годные для "песочницы". Но Хабру это пользы не несет, поэтому поставил минус за низкое качество материала. После 20 таких проектов - сами увидите, насколько плох был подход и подобранные библиотеки.
"возьми почитал" мобильный Сафари 17.2. Интересно, на какие страны вы делаете приложения - в Америке валом старых айфонов, в России - тем более, в Азии 17 еще не видели.
В контексте "еще в 2021 css убил scss" ну сами посмотрите
Троллинг? Напишите валидный нестинг на css, опишите поддерживаемые браузеры. Никому не нужен такой бесполезный коммент
Ну Mobx не то чтобы сложен. Пишем в обычном стиле где сторы и ViewModel - это классы, добавляем makeAutoObservable - получаем автоматический точечный ререндер компонентов при изменении только тех свойств, которые используются в компоненте.
Но тут согласен, от команды многое зависит - если совсем никто не пользовался, то обучение будет дольше, а если хоть один - то очень быстро других обучит.
А вот чем CSS Modules и scss не угодили?
Модули позволяют исключить пересечение стилей между компонентами, дают быстрый переход на место объявления, позволяют настраивать именование класса (например включать путь
src-components-layouts-layoutWrapper
), что создает ясный идентификатор для компонентов. Для e2e тестов не подойдет, но для дебага - прекрасно, сразу видно кнопку в каком из 100 компонентов, использующих кнопки, нажал пользователь и получил ошибку. Также при желании можно настроить генерацию d.ts файлов из стилей, чтобы найти все неиспользуемые классы (на постоянной основе - нежелательно, но в качестве плановой оптимизации раз в 3 месяца - отлично).Scss - это миксины, nesting (вложение одних классов в другие), математика и циклы, удобные импорты. Не обязательно использовать именно препроцессоры - можно использовать сразу постпроцессоры (PostCSS) с соответствующим интерпретатором. Во многих проектах постпроцессор и так используется (для автопрефикса и оптимизации например), и добавление scss не сильно ухудшит перфоманс сборки, но добавит удобный DX.
Ну, про FSD, TanStack Router, TanStack Query и Effector я согласен с предыдущим комментатором, что сейчас это самое неэффективное, и это никак не связано с годом их выпуска. Но популярных альтернатив лучше и правда мало, и если сжатые сроки - то можно и затянуть в проект, особенно если команда хорошо с ними знакома.
Спасибо, перешел в одном проекте с Prettier на него - скорость полного линтинга сократилась с 8.5с до 7с. Порадовало количество настроек и их гибкость, однако для совпадения с предыдущим форматированием через Prettier пришлось детально понастраивать - только лишь
stylistic.configs.customize
не дало нужного результата.В Реакте действительно особое поведение для контролируемых инпутов, я привел в статье ссылку на issue, где обсуждается этот вопрос и приводятся десятки вариантов решения. Там довольно подробно описывали сложности реализации, например здесь
У Реакта другая система реактивности - изменения Preact signals не будут вызывать ререндер компонента, а если с адаптером - то все равно не будет точечных апдейтов без ручной оптимизации. То есть на мой взгляд привязка к Preact будет достаточно сильная.
Для осуществления глубокой реактивности (не только примитивов), как вы правильно заметили, тоже будет необходима дополнительная библиотека, и по размеру код думаю приблизится к Preact+MobX, учитывая все нюансы.
Не спорю, что если использовать только 1 фреймворк, то можно оптимизировать код, однако мне было интересно именно side-to-side сравнение, поэтому взял MobX для связки с Preact.
Да, есть немало библиотек, в том числе для Solid, которые решают эту проблему. Но если в приложении пара инпутов и не хочется раздувать размер бандла, то в контролируемых инпутах Реакта все решается намного проще, чем в неконтролируемых Солида.
Для Реакта я мог использовать простые regexp для запрета ввода некорректных символов, теперь же приходится все делать через сторонние библиотеки. Не то, чтобы это вызывало серьезные неудобства, но отсутствие привычного функционала портит впечатление от фреймворка.
Да, меня тоже смущает, что Painting отличается на 50%. Думаю, тут дело в ререндерах и отсутствии оптимизации для Реакта (если бы выносил больше компонентов и они точечно обновлялись - то меньше бы было), об этом написал в статье.
Page1 - Page 2 не реактивные, а прод-приложение, из которого приводил метрики - реактивные, там есть изменения в структуре разметки, динамические элементы, показы по условию, изменения стилей и т.п. Делать что-то сложное в Реактосолиде я не стал - просто сгенерировал статику через AI и убрал 80% архитектуры прод-приложения. Можно самостоятельно для интереса сделать что-то более сложное - думаю, различия в перфомансе будут более явными.
Preact+Signals, к сожалению, совсем не поддерживает реактивные классы и завязывается на написание логики внутри компонента - этот подход не адаптировать под ViewModel и MobX. Перфоманс, уверен, будет лучше, но и ограничения явные - сильная привязка к Preact и невозможность быстрого переключения на React/Solid. Для меня же Solid был новым опытом, и оставить себе "путь отступления" было крайне важным на старте - хотя после написания проекта это оказалось избыточным, экосистемы и возможностей Solid хватило с лихвой.
Некст вне контекста статьи, как и мегабайты картинок. Контролируемые инпуты нужны для фильтрации того, что вводит пользователь. Попробуйте на нативном инпуте нативно обработать oninput, onchange, onpaste, onkeypress, onkeydown c учетом мобильных браузеров и всех версий операционки и разрешить скажем ввод "a-b". Это очень нетривиальная задача, если у вас в наличии десятки устройств.
Добавьте обработку маски и позицию каретки для удобного редактирования.
Другая экосистема, другой хаб для дискуссии)
Мне была важна возможность перехода на React/Preact+MobX если не хватит экосистемы, поэтому детали реактивности были не важны - главное, чтобы была возможность делать реактивные инстансы классов по аналогии с MobX. Что под капотом - геттеры-сеттеры, прокси или сигналы не так важно, если они дают достаточный перфоманс и не налагают серьезных ограничений.
Конечно, есть фреймворки, предлагающие менее 5.78 kb на старте, но не с jsx синтаксисом и без возможности практически безболезненно переключаться на другие фреймворки.
Если вы это серьезно, то крайне недооцениваете классическую структуру.
Несколько "связанных модалок" - это несколько "независимых модалок, вызываемых колбеками при закрытии со статусом успех". Эти модалки лежат в components/modal/lib и могут вызывать друг друга. Если они вызываются только с одной страницы - то будут лежать в папке страницы.
Что за modules (модули) в замену семантичным pages не понимаю. Звучит как заменим "страницу" на "модуль" - как это можно вообще придумать?
Показ баннера - компонент лежит в components/banner, вызывается параметром в глобальном сторе showBanner: boolean. Этот компонент смотрит в глобальный стор и при изменении значения отображается. Он не зависит от страниц.
"кнопка которая меняет дизайн в зависимости от наличия подписки" - интересный кейс, то есть если передал onClick то один вид, если не передал - то другой. Решается маппером в компоненте components/button. Если ей нужен значок - он передается через проп <Button leftIcon={''} rightIcon={''} />, никакой необходимости делать дубляжи компонентов на каждый проп нет.
Функции форматирования строк складываются в utils/formatString, которая экспортирует объект с 100 разными видами форматирования, если это нужно проекту. Это по факту исключает дубляж - глазами пробежаться по методам куда проще, чем искать в море widgets, entity, app, feature и т.п. разнородных файлов с форматированиями.
Нападки в целом "из пальца", попробуйте сами в классике писать - там нет перечисленных проблем)
Вы про это? Ну, я не поддерживаю Клерика в плане, что микрофронты - хорошее решение, но в остальном согласен с его позицией.
И, к сожалению, вашу позицию про FSD как способ "хорошо структурировать проект по доменным областям", который решает описанные в цитате проблемы - не могу поддержать.
В классике есть домены - это страницы src/pages/somePage. Это понятная и хорошо структурированная система, синхронизированная с роутингом. Рефакторить очень просто, риск дубляжа сведен к минимуму за счет глобальных слоев, связи между слоями достаточно четкие.
Проблема "свалки в коде" существует в классике, это верно, но она возникает только когда проект перерастает продвинуто-средний размер (30+ страниц, 50+ компонентов, 70+ вызовов апи). И для решения этой проблемы масштабируемости есть ряд способов - микрофронты это один вариант, как описано выше, монорепа с выделением ряда страниц - другой вариант, здесь все зависит от архитектора. Возможен и вариант развития классики "в глубину" - сгруппировать страницы по папкам, выделив слои внутри них.
Но с такими большими проектами редко сталкиваешься, а если да - то там достаточно опыта для наиболее грамотного выбора структуры, подходящей проекту.
Я попытаюсь разложить для себя и ответить.
Проблема наименований в роутере и в проекте - в проекте 200 страниц, из них нужно сгруппировать 10, и это не ложится в термин "страница". Здесь ключевое - "нужно сгруппировать", то есть пришла некая задача от бизнеса или архитектора - эти страницы нужно куда-то выделить. Очевидное решение - в новый app, то есть приложение, содержащее эти страницы + всю необходимую для них логику. Термин "приложение" не противоречит классической структуре, и верно, что "страницей" его называть не правильно. Но в контексте роутера это - набор страниц, роутер не должен знать о структуре и фреймворках, используемых в отдельных "приложениях", из которых формируется единое "приложение". Роутер существует в едином контексте - это вкладка браузера и URL, а откуда берутся компоненты для страниц - это детали реализации. Поэтому я не вижу здесь логических ошибок - роутинг и структура проекта это разные вещи.
Да, есть проекты из 1 страницы - лендинги или "виджеты", которые встраиваются в сторонние сайты и например отображают погоду. Они тоже хорошо ложатся на классическую структуру - будет 0 страниц (только корневой App) и набор компонентов, которые там отображаются, и не будет слоя роутинга.
Про микрофронтенды я написал в контексте треда. Я согласен, что они по большей части неэффективны и избыточны, а для работы разных команд над одним проектом часто достаточно монорепы и организационных ограничений. По крайней мере до 5 команд на моем опыте комфортно уживались без существенных блоков для других команд в монорепе. А вот аналогичный опыт с разделением по микрофронтам был очень негативным, так что я тоже использовал бы их только в крайнем случае. Написал пример для микрофронтов в комменте выше только для того, чтобы показать, что классическая структура не мешает их выделить.
В целом вы видимо хотите перевести тред в тему "нужны ли микрофронты", но для этого есть куча статей о них, я по крайней мере там выступаю как противник данного подхода. Здесь же обсуждается структура папок и взаимосвязей, немного другой контекст
Но это будет немного не то, что в классике, думаю. Там глобальный слой апи могут вызывать все, кто хочет получить эти данные, они будут сложены в глобальный стор. Компонент всегда лежит в src/components, не нужно его искать по entity/ui, widgets/ui/ui/ui. features/ui/ui/ui/ui. Условно, классика - это все shared (components), пока не потребуется положить в page. Один из нас думает локальностью и изолированностью, другой - глобальностью и что нужно класть в модуль только при необходимости) У обоих разные проблемы, но в целом одинаковые
Ключевое - роутинг. У вас в проекте за него отвечает отдельный фреймворк, но это ключевая часть - синхронизировать урл и отображение. Второе - автоматизация, это хоть и невидимая часть в вашем проекте, но играет существенную роль (от сборщика до скрытой логики). Третье - организация стилей, которая подчиняется своим правилам каскадности и CSSOM и строится по отдельному дереву. Четвертое - очевидное - иерархия взаимодействия, чего нет в FSD, насколько знаю, там в основном все через хаки. Ну есть еще несколько моментов)
Как разработчика меня интересуют только метрики профайлера + структура в дев тулз + легкий поиск из html конкретного компонента + достаточно емкие логи в Sentry, чтобы найти все баги за "поиск по проекту". Не столь важно различие, как мы кладем папки и файлы и их связываем.
Но я же не об этом говорил в комменте, а указал, что вы в ряде утверждений ввели в заблуждение относительно содержания статьи, триггернули человека, захейтили и унизили за то, что показал на это - возможно, немного грубым способом. Но это же ваша статья и ваша аудитория разработчиков, причем опытных. Я тоже так в своих статьях поначалу поступал, за что даже себе минус в карму пытался поставить) Затем, как и вы, старался вывести на конструктивный диалог - а если не получалось, то не оскорблял.
У меня есть старый бойлерплейт https://github.com/dkazakov8/dk-boilerplate , в нем классическая структура является основой слоистой архитектуры. Боюсь, разговор об архитектурах не впишется в формат комментов, это слишком большая тема)
И вам спасибо за качественный ответ по всем пунктам)
Я бы тоже перевел ваш проект на классику и показал преимущества, однако для ближайшей статьи запланировал библиотеку роутинга, лишенную всех проблем React Router и Tanstack. Лет 8 ей занимался, но для вашего проекта она не будет полезна - стек уже выбран)
Значит, существенную дискуссию переведем под следующую вашу статью. К слову, не путайте архитектуру и структуру, FSD - это лишь структура папок и их взаимосвязей, маленькая часть архитектуры)