• Почему мы должны выбросить React и взяться за Angular
    0

    Статическим анализом пользуюсь в виде TS и ESLint, они отлично поддерживают работу с jsx. Конфигураторы форм, хранилище локализаций — это не забота языка описания интерфейса, но преобразование из js-структур в jsx-разметку происходит через удобный js-код, а не встроенные (в лучшем случае) в шаблонизатор кастомные атрибуты и значения. Переопределение стилей в императивном формате style={{ width: 100 }} неизбежно во многих кейсах, и ничего страшного в этом нет. Почему все эти разноплановые темы вы объединили в один пункт "недекларативность" мне не понятно, и какие "декларативные" шаблонизаторы могут все это решить лучше, тоже не знаю.


    Абстрактная мегаморфная фабрика это про дерево, состоящее из React.createElement(type, [props], [...children])? Да, подход с shadow dom не так хорош по перфомансу, но его хватает для 95% SPA, в остальных, где требуется максимальная производительность и минимальное количество итогового кода, подойдут другие инструменты, а не Реакт, но будут значительно сложнее в поддержке. Я бы не стал это записывать в существенный недостаток, так как у других подобных популярных инструментов производительность сопоставима (кроме Svelte).


    В Реакте в целом используется концепт однонаправленного потока данных, это вполне удобно и с помощью mobx максимально оптимизируется: <Button onClick={() => store.counter++}. Соответственно, все компоненты, которые подписаны на store.counter обновятся, и проще вариант придумать сложно. Для сохранения равенства по ссылкам и переиспользуемости этой функции ее действительно можно вынести или в хук, или в экшен, или в метод класса — в зависимости от того, как построена архитектура. Но и инлайновый вариант, опять же с кейсом mobx, крайне не значительно ухудшит перфоманс. Двусторонняя связка между компонентами в данном случае производится через общий контекст — общий объект с источником правды, что позволяет максимально сократить горизонтальные связи, и это в моем понимании безусловный плюс.


    Неконсистентность в передаче параметров решается с помощью ESLint (jsx-curly-brace-presence), так же как и делается запрет на строковые ref ('react/no-string-refs') для того, чтобы "отличать их семантически от key", и проверка установленного key ('react/jsx-key'). В этом плане статический анализ работает прекрасно, и три этих относительно спорных момента регулируются практиками, принятыми в проекте. Волшебный смысл есть только в key, ref это просто получение ссылки на элемент. Тут соглашусь, что наличие key является недостатком. Как и довольно страшные комментарии.


    По поводу мусора в верстке — это не вина jsx как шаблонизатора, а кривизна рук. Многие тащат роутинг (!) в разметку, действительно выстраивают дополнительный иерархичный слой из контекстов, опять же в разметке. Но по большей части результирующий html и jsx совпадают, в отличие от большинства других шаблонизаторов. И в них тоже можно намусорить.


    Ограничения устанавливаются с помощью TS, ESLint и стандартов кодирования, проверяются с помощью pre-commit hooks, CI, code review. Написать лапшу и "срезать угол" можно в любой системе, тут jsx наравне со всеми, и не его это дело — устанавливать практики. То, что в других шаблонизаторах/фреймворках могут присутствовать уже сконфигурированные анализаторы кода и четко описанные стандарты кодирования в общей документации — это можно рассматривать и как плюс, и как минус. Есть мнение, что "ваша демократия и самоуправление — это хаос, а настоящий порядок — когда диктатура и все беспрекословно в страхе подчиняются", но я сторонник баланса, когда ограничения есть, но они задаются контекстуально, меняются со временем и подстраиваются под развитие всей системы.


    Изменение структуры данных в любом случае потребует изменений в рендеринге. Согласен, что обилие js-вставок в разметке это скорее антипаттерн, а итерирование лучше делать через дочерний компонент для оптимизации. К самому jsx это, опять же, не имеет отношения.


    В сухом остатке я согласен с критикой по поводу лишнего key, неудобного комментирования, неидеальной реализации механизма синхронизации dom и jsx (но это не к шаблонизатору). Остальное решается либо стандартными сторонними инструментами, либо есть отличные альтернативы по паттернам, в случае недостающего функционала.

  • о Redux архитектуре во Flutter приложениях
    –1

    Если под "связями между моделями" подразумевается, что используется классовый DI и в один класс хранилища прокидываются еще несколько, а в те, в свою очередь, еще несколько — это действительно предвестник полной запутанности и неподдерживаемости. Такая архитектура крайне специфична и подойдет возможно только определенным браузерным играм, но видел ее применение и в обычных SPA, что действительно расстраивает. Только не из-за mobx, а из-за классового DI и полного размазывания ответственности хранилищ под соусом "изолирования и явного указания зависимостей", что прямо противоположно результату.


    Для выведения значений сразу из нескольких семантических сторов нужен слой getters/selectors с реактивными computed-значениями, для изменения данных сразу в нескольких сторах — слой глобальных action-модификаторов состояния. Только времени разработчикам на то, чтобы продумать это все, как правило, не дают — от фронтендеров бизнес ждет быстрый видимый результат, а не продуманную архитектуру, удобную для разработки и минимизирующую количество ошибок. Вообще часто видел очень запущенный код с громадным количеством функционала, добрая половина из которого не работала и про которую бизнес даже забыл, не удосужившись вести полноценную базу знаний по продукту. И в таком виде приложение существовало долго и приносило доход, что и было целью для руководителей компании, в то время как разработчики удерживались методами, не связанными со "стремлением к саморазвитию, внедрением новых технологий, созданием стабильных архитектур". К чему я это все — к тому, что проект проекту рознь, и там, где достаточно времени уделяется качеству, можно практически на любом инструменте создать грамотную схему работы. Но с mobx получится на порядок лучше, чем на любом другом, и практически без бойлерплейта.

  • Почему мы должны выбросить React и взяться за Angular
    0

    Тоже никогда не понимал нападки на jsx — тот же html, но с компонентами (отличить можно по названию с большой буквы) и возможностью использовать js-переменные и код внутри фигурных скобок. Синтаксис изучается за день после изучения искусства верстки и вопросов/проблем возникает крайне мало, разве что по теме использования околохакового js-синтаксиса типа {isAllowed && <Component />}, так как тут нужно понимание одного из базовых принципов js — возвращаемое значение при использовании подобных операторов не булевое, то есть если isAllowed === 0, то будет выведено 0. Больше каких-то относительно сложных моментов и не припомню, но и это к jsx не особо относится.


    В то время как в angular, svelte, vue продолжается практика придумывания мета-html языка с кастомным синтаксисом и параметрами, мета-js языка для перебора массивов в шаблонах и строковой логики в атрибутах. Я понимаю, что глаза замыливаются, когда работаешь с одной технологией, но я шаблонизаторов понаписал и поиспользовал массу, и jsx это крайне удобный вариант rich-html — быстроизучаемый, минималистичный, с отличной поддержкой в IDE, возможности ограничены только возможностями самого JS, никаких проблем с миграциями на новые версии или ожиданий доработки функционала. А та древовидная структура, в которую он легко может быть сконвертирован, удобна для рендеринга в DOM, так как иерархичность и названия элементов/тегов максимально приближены к нативным.


    Но там комментатор явно пошутил про "ужасность jsx")

  • Почему мы должны выбросить React и взяться за Angular
    0

    Да, mobx позволяет роуты-модули оформлять в отдельные независимые чанки, в то время как redux синглтон и загружает все сторы одновременно.


    Модули лучше не линковать друг с другом и не плодить горизонтальных связей вообще, то есть при удалении каких-то страниц это никак не должно отразиться на остальных. Гардом может послужить автоматическое добавление-убирание модульных сторов в лайфцикле роутера, то есть даже при всем желании разработчик не сможет получить доступ к хранилищу другой страницы. Если уж надо переиспользовать — значит это состояние должно быть глобальным, а не модульным.

  • CSS, JavaScript и блокировка парсинга веб-страниц
    0

    Плюсанул за "регулярную… динамическую… обфускацию… данных и структур"

  • Сравнение производительности CSS и CSS-in-JS в реальном мире
    0

    Пять компонентов с маркером открытости — ок, пусть будут модалка, конферм, поповер, аккордеон и дропдаун. В поповере решили изменить на [data-closed]="true", потом в остальных. Вроде правильно понял условие задачи?


    1. Условие немного нереалистично — компоненты независимые, и если прямо с лупой в каждый не залезать, и не узнаешь, что там есть атрибут data-opened. Может вполне быть и другая реализация, и в целом разработчику все равно на этот "черный ящик"-компонент, если требования не меняются.
    2. Значит, изменились требования, причем ко всем компонентам? Или какой-то внезапный порыв все переписать у недавно пришедшего разработчика? Ок.
    3. Надо, значит надо. Берем поповер, переименовываем атрибут, проверяем в библиотеке компонентов или на реальной страничке — не работает. По одному клику на класс переходим в файл стилей, видим &[data-opened=false], переименовываем — работает. Git commit.
    4. Повторить для оставшихся четырех компонентов. Переименовал и не проверил что не работает? В субботу, джун, у тебя рабочий день, учишься писать e2e тесты и покрываешь эти компоненты автоматизированными тестами.
  • Сравнение производительности CSS и CSS-in-JS в реальном мире
    +1

    Удобное, лаконичное решение. Только забыли еще упомянуть про CSS Modules вида css.popover — то есть не будет никаких пересечений глобальных классов и "думать над названиями классов" тоже надо не больше, чем над названиями любых других сущностей и переменных (обычно исходят из семантики и читабельности). А эти два "недостатка CSS", судя по ссылке, и вынудили человека тащить js-надстройки в код и смешивать логику и представление.

  • Сравнение производительности CSS и CSS-in-JS в реальном мире
    +1

    Спасибо за ссылку, посмотрел и понял, что разговор наш если и состоится, то будет слишком долгим, так как буквально все там, на мой взгляд, неправильно — от обозначения проблем до выводов. Контраргументация потянет на статью, а времени на это сейчас нет, да и не то, чтобы хотелось прямо доказать свою правоту — время и так все по своим местам расставит.

  • Сравнение производительности CSS и CSS-in-JS в реальном мире
    0

    Понимаю, чтобы эффективно чем-то пользоваться, требуется этому сначала обучиться, "выстрадать", придумать десять подходов, прочитать о сотне, найти самое лучшее… В программировании так фактически с каждым инструментом.


    Насчет того, что "типизация работает хорошо" — это вряд ли, для этого нужны другие инструменты (stylelint), которые проверяют корректность и параметров, и значений. За редким исключением в css-in-js такого вообще нет, либо проверяются только названия параметров. Но зато действительно проверяется "используемость стилевых классов" и после рефакторинга можно с помощью ESLint плагина


    'import/no-unused-modules': ['warn', { unusedExports: true }]

    увидеть неиспользуемые экспорты. Что такое cover-тест не знаю, Яндекс утверждает, что "тест на косоглазие", поэтому подтвержденной остается только эта маленькая фича с неиспользуемыми экспортами при рефакторинге. При этом недостатков ну просто море. Стоит ли оно того, и можно ли фичу с простотой удаления ненужного назвать "эффективным решением задач", хотя это вообще не относится к решению основной задачи… Думаю, точно нет.

  • Сравнение производительности CSS и CSS-in-JS в реальном мире
    0

    Да, конечно, у вас больше экспертизы по бывшим коллегам — я видел только маленький кусок кода одного из многих проектов. Может и есть достаточно толковые проекты — сам работал в Домклике, там все очень пристойно было и по коду, и по процессам, и по коллегам. По крайней мере до определенного момента.


    Но выбор SC однозначно делали "на попробовать хайповую штуку" без каких-либо трезвых аргументов, потому что после того, как поработаешь с несколькими реализациями, понимаешь, что этот подход некорректен в корне. Как и redux+saga. Есть намного более простые и эффективные решения.

  • Сравнение производительности CSS и CSS-in-JS в реальном мире
    0

    А еще redux+saga? Собесился туда разок, показали кусок длинной функции с десятком yield put-call-takeLatest-takeEvery и попросили рассказать, что там происходит. Я сказал, что все там свистит-переливается и очень информативно, но мне срочно на другой собес надо) В такие проекты серьезные ребята все-таки не идут, по очень разнообразным причинам, и уверен, что SC внедряли не по трезвой голове.

  • Переход к «Meta GSAP»: поиски «идеальной» бесконечной прокрутки
    0

    Вау-эффект, продажи, маркетинг.

  • Венец эволюции CSS-in-JS уже здесь: полностью типизированные стили без рантайма в vanilla-extract
    0

    По поводу атомарных классов — в препроцессорах можно включить extend, либо просто прогонять результирующие файлы через CSSO — сомневаюсь, что будут отличия в размерах, либо в моем варианте все же будет получше, потому что не руками оптимизируется, а автоматически:


    // source
    .foo { color: #ff0000; }
    .bar { color: rgba(255, 0, 0, 1); }
    .text { display: inline; color: red; }
    .text2 { display: inline; }
    
    // result
    .bar,.foo,.text{color:red}.text,.text2{display:inline}

    По скорости билда если и не будут различий, все равно создается дополнительная нагрузка на IDE и тайпчекинг — IDE включит ваши файлы в индекс и так или иначе часто будет их процессить даже при закрытых вкладках. Тайпчекинг тоже замедлится и в целом непонятно, зачем он — разве что для нахождения несуществующих классов, чтобы было удобней рефакторить. Единственный плюс, пожалуй.


    То, что все эти кастомные структуры будут в автоподсказках не значит, что их не требуется изучать и что они вообще нужны.


    Мы очень сузили в обсуждении темы для сравнения, надо было видимо написать пятисотстрочник с недостатками css-in-js, чтобы было больше материала) А по обсуждаемым пунктам — да, ваш вариант где-то на горизонте видит экосистему CSS и изо всех сил бежит к ней, в чем-то сравниваясь по скорости, в чем-то по удобству. Но чтобы догнать нужны совсем другие усилия и намного более основательные причины, чем "можно тайпчекать наличие классов и писать js-логику прямо в стилях", при этом с кучей недостатков.


    Чуть не забыл сказать про инкапсуляцию:


    .class {
      .class2 {}
    }

    Пожалуйста — nested структура, внутренние классы работают только если заключены в обертку .class. Структура вложенности для удобства должна отражать html-структуру разметки, чтобы при изменении стилей можно было практически не лезть в файлы с разметкой. Добавляем модули = изоляция, инкапсуляция. И ни одного createAtomicStyles, createAtomsFn, export и т.п.

  • Венец эволюции CSS-in-JS уже здесь: полностью типизированные стили без рантайма в vanilla-extract
    +1

    Неожиданный сайд-эффект: по запросу в Яндексе "какашата" данная статья вылезает на 3 позиции. Может, эти лиды ставят звезды на гитхабе и в закладки сохраняют…


    P.S. Извини автор за такие шутки, но видеть в проектах css-in-js это такая боль. Почему-то тысячи стилевых багов мне встречались исключительно в таких проектах.

  • Венец эволюции CSS-in-JS уже здесь: полностью типизированные стили без рантайма в vanilla-extract
    +1

    При единых выходных файлах действительно расплата будет не в рантайме, но в билдтайме. Стилевые TS файлы нагружают парсер IDE и общий лоадер для ts-файлов, что приведет к деградации скорости сборки, поиска по проекту, подсветки типов, линтера. Конечно, работа с CSS тоже не бесплатна, но она параллелится, а тут все в большой куче получается.


    Sprinkles посмотрел — это переизобретенные mixins, в которых давно реализовано то же самое:


    .class { @include paddingX(10px); }
    .class { display: inline; @mobile { display: block; } }
    @mobile { .class { display: block; } } // предпочтительней этот вариант, чем в каждом отдельном классе прописывать адаптивное поведение
    .class { padding: $gap-small; }
    .class { padding: var(--gap-small); }

    Этого инструментария хватает для того, чтобы сделать приложение любой сложности и вполне удобно контролируется.


    "Более удобная композиция класснеймов" — спорно, я не вижу ни одной неудобной строчки в таком варианте:


      get wrapperClassName() {
        const { className, inputConfig } = this.props;
    
        return cn({
          [styles.inputWrapper]: true,
          [styles.focused]: inputConfig.isFocused,
          [styles.disabled]: inputConfig.disabled,
          [styles.hasValue]: inputConfig.value !== '',
          [styles.hasErrors]: inputConfig.errors.length > 0,
          [styles.hasIcon]: Boolean(inputConfig.icon),
          [className]: Boolean(className),
        });
      }

    В CSS файле все удобно разложено и красиво отформатировано. Приоритет стилей определяется порядком их следования в стилевом файле и усиленной специфичностью. В css-in-js в большинстве реализаций описание подобного превратилось бы в ад, как и стилевой файл.


    По поводу вербозности — каким бы ни был лаконичным DSL, он максимум что сможет сделать — приблизиться к композиционному подходу с миксинами, при этом сохранятся все вот эти обертки типа createAtomicStyles, createAtomsFn, экспорты, нетипизированные значения без подсказок от IDE и соответственно с большой вероятностью опечаток, кастомное структурирование типа conditions, defaultCondition, properties. Все это абсолютно лишний бойлерплейт — через устоявшиеся подходы все делается удобней и не нужно никакого дополнительного обучения для разработчиков, достаточно изучить файлы с константами и миксинами при переходе в новый проект.

  • Path aliases in React
    0

    "действия этого скрипта НЕОТВРАТИМЫ" — точно сказано, почти все проекты, которые видел использующими CRA, сделали eject и перешли на кастомные конфиги по мере роста проекта. Он только для маленьких pet-проджектов, так как для проектов чуть больше нужно много дополнительного функционала, а возня с переопределением правил изначально плохая идея.


    По телу статьи — вы забыли упомянуть, что в IDE может потребоваться специальным образом отметить папки, для которых сделаны алиасы — так, WebStorm умеет брать ts-алиасы в ts-файлах, но в стилевых файлах @import 'mixins.scss' не сработает без отметки Resource Root на папке src/components/styles. У вас вижу css-in-js, поэтому могли не столкнуться. Также в кодовых блоках лучше использовать двойной пробел для табуляции и переносить при достижении 80-100 символов — читать легче, не будет прокрутки.


    За лесенку в const ... = require() уважение, выглядит аккуратно. Жаль, не разбито по семантическим группам (built-ins, external, internal etc.), в этом случае скорость восприятия кода еще улучшится.


    По коду еще по неймингу захотелось пройтись. Вот, к примеру, функция


    const slicePath = p => p.slice(0, p.indexOf('*') - 1)

    Как видно из названия, она "нарезает путь". Из реализации не очень понятно, что ожидается на вход и что будет на выходе. Даже если найти пример входных данных в коде ("src/components/*"), все равно не сразу понятно, что будет на выходе — обрежется только звездочка или еще что-то. Только поразбиравшись станет понятно, что на выходе получится "src/components". Почему бы не сделать более читабельно:


    const removeWildcardPart = path => path.replace('/*', '');

    Примерно то же и с .reduce((obj, x) => { ... }). Так как тут не используется TypeScript, то главным оружием в борьбе за понятность структур в коде является семантичность. И вариант с .reduce((acc, path) => { ... }) будет выглядеть лучше, а еще лучше — вынести это в отдельную функцию, чтобы следующий разработчик не тратил время на разбор, если его это не интересует. К тому же эти вездесущие нейминги x — в последнем кодовом блоке возник дубляж названий:


    (obj, x) => {... options.paths[x].map(x => `${slicePath(x)}`) ...}

    а это уже тянет на вопрос юниору на собеседованиях — какие недостатки у подобного подхода) А так норм, добро пожаловать в писательское сообщество.

  • Венец эволюции CSS-in-JS уже здесь: полностью типизированные стили без рантайма в vanilla-extract
    +5

    Должно уйти, потому что многословно, неудобно, низкопроизводительно и приводит к смешению концептуально разных сущностей и языков. Повторюсь, у всех реализаций при применении на практике громадное количество костылей и недостатков.


    Управление стилями при помощи добавления-удаления классов очень эффективно, так как позволяет за раз переключать сразу несколько параметров и переиспользовать эти классы в других компонентах. Схема через template literals ${isActive => isActive ? 'margin: 0; color: red;' : 'margin: 1px; color: green;'} как раз выглядит хаком, а не &.active {margin: 0; color: red;}.


    В целом не могу сказать, что что-то в отдельном CSS меня не устраивает — это долго развивавшийся язык, с отличной поддержкой в IDE, многочисленными инструментами для добавления функционала через пре- и пост-процессинг, линтерами/форматтерами. Часто говорят, что css-in-jss это мощно, потому что можно написать какие угодно инструменты на js — но они и так есть для CSS, и тотальное переписывание, чтобы было так же удобно работать, как и с CSS, приведет к тому, что получится то же самое. Просто файлы не с расширением .scss, а .ts и дополнительным оверхедом по синтаксису, экспортам и торможению основной сборки. Но для этого "светлого будущего" нужно еще написать сотни инструментов, исправить тысячи багов, интегрироваться во все IDE, стандартизировать параметры и значения (а текущий TS этого не позволяет в должной мере, string и все тут). В то время как все давно уже есть, и ради маленькой фичи "не хочу писать cn(styles.class1, isActive && styles.class2), хочу писать class1({ isActive }) и логику внедрять внутрь стилей, потому что так смогу все размазать в единый слой" все эти усилия… Стоит ли оно того, или пора все же в историю?

  • Венец эволюции CSS-in-JS уже здесь: полностью типизированные стили без рантайма в vanilla-extract
    +4

    Скорей бы это смешение стилей и логики ушло в историю. Вот смешение разметки и логики (JSX) - это удобно, так как они очень тесно связаны, а стили - совсем другой слой и программе все равно есть они или нет, без них все будет работать так же, это чисто визуальная составляющая.

    Я уже со счета сбился в перечислении недостатков, которые css-in-js вносит в проект, по сравнению с модулями. И тем не менее иногда встречаются проекты, использующие этот нежизнеспособный концепт, запутываясь в сотнях одинаковых с лица но кардинально разных компонентах Button / StyledButton (в лучшем случае), тоннах omitProps, смешении стилей и компонентов, ужаснейше выглядящих и не поддающихся форматированию template-вставках, постоянных "> * {}" для переписывания стилей любых чайлдов, и список этот настолько длинен, что на вот такую статью как наверху потянет, чисто перечисление...

  • Почему мы перешли с Webpack на Vite
    +2

    Аналогичный опыт — долго провозился с Vite и Snowpack, пытаясь хотя бы самый простой рабочий проект завести. Но отсутствие возможности собирать нодовый сервер под SSR или без него сразу ограничило проекты до нескольких (экспериментальные плагины есть, но после долгой возни только с большими костылями завелись, плюс нет частичного обновления — серверная часть каждый раз прогоняется через бандлер, что в сотню раз медленнее). Часть из оставшихся использует асинхронные чанки, как вы описываете — с общими частями, lazy-подгрузкой, контентхешем в названиях, прелоадингом, экстрактом css-файлов и т.п. После долгой возни тоже корректно не завелись.


    Остались простейшие SPA-монолиты из пет-проджектов, потому что энтерпрайз так не делается. Там да, завелось, но бандлер с автополифиллингом опять же нужен, конфигурирование через env-параметры, комменты в файлы и куча всего еще, что в Вебпаке по привычке за пару минут делается, а тут приходится "женить" дев-сборщик (довольно сырые причем оба и Vite и Snowpack — в их issues прямо поселиться пришлось) и бандлер. С этим можно справиться, что-то завелось корректно, и в дев-режиме действительно быстрее собирается и в основном хот-релоад работает лучше, чем в Вебпаке, но однозначно оно того не стоит. С кешированием и параллельностью Вебпак такие проекты тоже за 0.03-0.05с пересобирает вместо 0.01с у этих новичков. Поэтому дальше копаться не стал, подожду, пока хотя бы основные энтерпрайз-фичи будут хорошо поддерживаться и с бандлерами начнут крепко дружить.

  • Реализация архитектуры Redux на MobX. Часть 1: «Проблемные места Redux»
    0

    Я посчитал, что это было банальной ошибкой в коде, так как смысла не оборачивать компонент не вижу, в комментарии слишком мало контекста и явно плохое понимание как работает observable. Если этот Page — компонент из сторонней библиотеки, то достаточно передать отдельные props, но тут еще упоминалась передача "state.auth в качестве пропса", так что это явно внутренний компонент.


    В целом ветка с перепутанными смыслами, неявным контекстом и мешаниной подходов, поэтому я написал комментарий не к ветке, а в общем — что есть механизм toJS, но актуальность его использования крайне редка — есть решения лучше (обернуть дочерний в observable или передавать отдельные пропсы если компонент сторонний). Ваш вариант с toJS некой объемной структуры данных, часть из которых может быть не нужна в дочерних и вызовет лишние ререндеры плохой в любом случае.

  • Реализация архитектуры Redux на MobX. Часть 1: «Проблемные места Redux»
    0

    Это-то тут причем? Конечно, он должен быть обернут в observer, разве об этом разговор? export const Home = observer(...).

  • Реализация архитектуры Redux на MobX. Часть 1: «Проблемные места Redux»
    –1

    Чем же оно прекрасное, зачем компоненту-обертке лишний раз ререндериться? И конкретные параметры тоже лучше не передавать, опять же, это нивелирует бенефиты от observable. Куда лучше в самом этом дочернем компоненте использовать store.auth.username — тогда только он и обновится. Реактивность работает именно так, как должна.

  • Реализация архитектуры Redux на MobX. Часть 1: «Проблемные места Redux»
    0

    Если нужно реагировать на изменения во всех дочерних структурах, можно использовать метод toJS из MobX, пример


    reaction(() => toJS(state.auth), function onAnyChangeInAuth() {
     ...
    })

    Через пропсы передавать с помощью toJS крайне нежелательно, так как родительский компонент будет ререндериться, когда это не нужно. В целом ситуации, когда этот механизм нужен, крайне редки — в голову приходит только синхронизация стейта из оперативной памяти и какого-нибудь persistent storage, того же localStorage, или онлайн-игр с сохранением состояния в Firebase. То есть при любом изменении в хранилище оно целиком (в реальности, конечно, через дифф-алгоритм) будет записываться в постоянное хранилище и не будет пропадать при перезагрузке страницы.

  • Как готовить микрофронтенды в Webpack 5
    0

    Спасибо за ответ, посмотрел подробнее — получается довольно удобно, каждый модуль собирается отдельно и вертится на своем порту, при этом можно красиво импортить отдельные компоненты, расшаривать общие библиотеки, прокидывать верхнеуровневое состояние и методы. Вебпаковский вариант выглядит намного лучше тех костыльных нагромождений, которые видел раньше.


    Тем не менее, недостатки, присущие проектам, разложенным по разным репозиториям и имеющим общие части остаются, но для 4+ команд по-другому и не получится — толпиться всем в одном репозитории становится тесно даже при грамотном менеджеринге веток, так как из-за разницы в релизных циклах мердж реквесты начнут копиться и устаревать. Можно сделать еще удобные рецепты, чтобы собирались только рут + нужные модули, этим разрулится проблема с производительностью. SSR тоже вполне можно прикрутить, включив в useDynamicScript механизм require и кэш в global, хотя прикрутить ожидание асинхронных вызовов перед рендером будет непросто (но наверняка будет еще немало подводных камней).


    В общем, Module Federation на первый взгляд — уже хоть что-то, похожее на удобство, по крайней мере для одностековых проектов.

  • Как готовить микрофронтенды в Webpack 5
    +1

    Поясните, пожалуйста, чем данное решение помогло в "разделении зоны ответственности и распараллеливании разработки". Как я понял, все модули лежат в одном репозитории и ревью / мерджи производятся в одном потоке с соответствующим пересечением в релизных циклах? Или для каждого модуля-папки заведет отдельный гит-репозиторий, просто получается в одной папке можно собрать сразу много репозиториев через cli-инструмент, который подтягивает версии?


    Так же, как вижу, в каждом из модулей могут использоваться разные версии npm-зависимостей, что приводит к рассинхрону и потенциальным багам, часть из которых описана в статье. Вскоре может понадобиться изменить конфиги вебпака для отдельного модуля — добавить другие лоадеры, плагины, сборку других фреймворков и т.п., но, как я понял, Module Federation опирается на единый конфиг. Как планируется разруливать этот кейс?


    И по поводу "разделения зоны ответственности" непонятно, чем данная схема лучше монолита — если код разбит на асинхронно загружаемые модули, то команды, их разрабатывающие, и так не будут пересекаться по коду. Проблема только в том, что используется один гит-репозиторий, но если команд не больше 4, разруливается менеджерингом лейблов и веток — в одном проекте так делали, пересечений фактически не было.


    В монолите, к сожалению, тоже есть одна существенная проблема — так как собирается все и сразу, то время сборки значительно увеличивается (хотя есть несколько стратегий для динамического билдинга), при Module Federation, как понимаю, будут собираться только переданные через cli модули или тоже все?

  • Фрактальный state-менеджер на генераторах*
    +1

    Да, там тоже многие еще сидят на старых компьютерах ввиду низкой покупательской способности или устаревшего отношения руководства компаний к интернету. Статистика сейчас разнится, но в районе 4% у IE9-11 все еще есть, а это ну почти 100млн машин если только ЮВА считать. Так что веб там очень специфичен и многие до сих пор придерживаются табличной верстки либо в качестве энтерпрайз решения — флоатов, что не требует полифиллинга. Благо очень многое полифиллится, но не все. У госконтор та же история, но с началом Медведевской "диджитализации" все-таки ситуация немного лучше, и хром-то даже на старую винду админы поставят.

  • Security с характером, или еще несколько слов о паттерне Singleton
    0

    Спасибо за пояснение, я в DI не хорош — видел реализации в проектах, но смысла для фронтенда так и не понял. Предпочитаю делать слои экшенов, апи и сайд-эффектов отдельно от хранилищ, с доступом к глобальному стору.

  • Security с характером, или еще несколько слов о паттерне Singleton
    0

    Сборка упадет и он поправит, это же обычная опечатка. Получается этот паттерн через getInstance неактуален? Ни разу не видел в современных проектах, везде просто готовый инстанс экспортируется

  • Security с характером, или еще несколько слов о паттерне Singleton
    +1

    Может глупый вопрос, но чем отличается от export const dataBase = new DataBase()? При импорте из разных мест придет один и тот же инстанс по правилам ES Imports. И DI соответственно class { private dataBase = dataBase; } без контейнера, передающего значение через декоратор.

  • Микрофронтенды: разделяй и властвуй
    +1
    1. Вот это "подтягивание хвостов" только звучит как будто это осуществимо, на деле приходится обновлять компонент (селект к примеру) в библиотеке компонентов для реакта, вью, ангуляра, ставить задачи на все команды по подъему версии, причем они могут быть ниже приоритетом чем задачи от бизнеса, в итоге 5 из 10 микрофронтов обновились через неделю, еще два — через две, еще в трех эти задачи "потерялись" и остались в глубоком бэклоге. В итоге приложение несинхронизировано, баги остаются надолго, стили остаются разными. С десятью обновлениями или тем более редизайном получается такой треш, что смотреть на это все невозможно. Организационно это тоже не решить, так как у команд разные циклы поставок. В монолите же один апдейт и если используется TS, то он не даст оставить "хвосты", придется переводить сразу все — это займет больше времени на задачу, но сэкономит десятки человекочасов (считая время аналитиков, тестировщиков, разработчиков) по сравнению с микрофронтами. Не в идеальном мире живем, когда все всегда доводят задачи до конца.


    2. Микрофронты всегда тесно связаны с рутом, в котором находятся глобальные компоненты и методы — не сделать серию нотификаций или модалок без доступа к информации, какие уже отображены, то же касается и авторизации, методов подключения/дестроя, роутинга. Изменения в каждом — критичны, если не поддерживать обратную совместимость, что сильно ограничивает возможности и раздувает код.


    3. С этим не сталкивался, так как использую автоматический полифиллинг (babel preset-env), соответственно достаточно изменить browserslist в каждом микрофронте, но эту схему используют далеко не все и действительно может стать проблемой.



    Микрофронты — не модный тренд, а метод обхода комплексного рефакторинга систем, чтобы можно было использовать легаси-части и постепенно их переводить на общую схему, имхо. А как по вашему, какое еще может быть у них назначение?

  • Микрофронтенды: разделяй и властвуй
    0

    На моем опыте был только один случай, когда приложение состояло из двухуровневых iframe — виджет встраивался в сайты, и в самом виджете было несколько фреймов из разных доменных зон, связанных по postMessage. Но и там сделал единую точку рендеринга, в которую ходили разные бэкенды за получением локализованного шаблонизированного html, соответственно "зоопарка" не было, просто такой мультифреймовый конструкт с большим оверхедом по доступу к данным соседних "микрофронтендов".


    В контекстном понимании, когда в едином поле страницы могут параллельно работать несколько разных фреймворков со своими компонентно-стилевыми системами, было только два проекта, и в обоих эта схема не была оправданной, так как приносила массу проблем и катастрофически замедляла разработку, несмотря на "параллелизацию поставок" — все равно в каждом релизе приходилось дорабатывать практически каждый микрофронтенд ввиду новых схем роутинга, подключения, общения с рутом, конфликтов лэйаута, обновления библиотек и дизайна и т.п. Поэтому я полностью отказался от подобных архитектур — оправдать их наличие перед бизнесом уже через пару месяцев становится нереально, так как профит только отрицательный. Думаю, что эта схема подходит только для легаси-проектов, как в статье, как переходный этап к новому монолиту, а проблема "Быстро писать код мешали устаревание подходов, фреймворков и зависимостей, а также связанность логики" решается планомерным рефакторингом — это обязательная часть разработки, не получится долго писать только бизнес-логику без архитектурных правок.

  • Микрофронтенды: разделяй и властвуй
    +3

    Можно еще писать компонент-тесты, делать подробную документацию к ним, обсуждать подходы типа двойные кавычки или одинарные, писать кастомные правила для ESLint, внедрять дополнительные статические анализаторы кода в CI/CD, делать обертки над многочисленными opensource-зависимостями для "абстракции от конкретной библиотеки", выносить каждое правило в стилях в миксины для "переиспользуемости", достигать какого-то уровня покрытия тестами кода, да мало ли еще бесполезной работы сейчас фронт-ендеры придумывают, лишь бы их бэк-енд был в тепле и достатке.

  • Крупные компании, использующие Node.js
    0

    Клоакинг, как много в этом слове… Когда поисковики еще обращали внимание на meta description и не обращали на opacity: 0; width: 0; или цепочку js-редиректов, можно было представить в поисковике сайт как угодно… Сейчас такие схемы только в даркнете работают ввиду отсутствия продуманности в краулерах сайтов. Но в лайтнете такое не работает уже лет 7.

  • Микрофронтенды: разделяй и властвуй
    +13

    В подобной архитектуре намного больше проблем, чем описано, и код, обслуживающий их, становится настолько сложным и трудноподдерживаемым, что приходится выделять отдельную команду. Участвовал в двух проектах с подобной схемой. В числе других проблем — отсутствие общих компонентов либо большая сложность в их интеграции (обновить шрифт в 10-20 микрофронтах? Поднять версию библиотек, подтянуть иконки? В монолите — час работы, в подобной системе — больше месяца, кроме шуток); подтягивание актуальных версий для локальной разработки (придется писать сложный cli-инструмент с резолвом конфликтов и менеджерингом гит-версий в каждом микрофронте); на поддержку root-обертки тоже нужна команда, со своим флоу поставок и разрастающимися версиями для поддержки обратной совместимости, что выливается со временем в катастрофическое торможение новых релизов; про SSR даже можно не думать; в каждом микрофронте свои подходы и устаревающие конфиги, которые тоже нужно синхронизировать; кратное увеличение времени CI/CD; в браузере общий DOM, соответственно общая раскладка, и если не пользоваться iframe то очень велика вероятность конфликтов стилей или лэйаута; дублирование полифиллов. Перечислять можно еще долго, но закономерный итог — замедление поставок и тонна багов от синхронизации. А что считается "достоинством"? "Свободная реализация компонентов системы разными командами", то есть тотальный зоопарк. Про "независимость поставок", который часто тоже служит аргументом, лучше и не упоминать — в реальности этого нет, наоборот, приходится часто лезть во все репозитории, разбираться в их коде и подходах, и править, влезая в циклы поставок других команд.


    За меньшее (!) время можно переписать легаси-код с полноценным рефакторингом и приведением к современным общим стандартам. Никто не мешает заложить архитектуру, в которой каждая страница — отдельный асинхронно загружаемый модуль, для развития которого не нужно лезть в рут и соответственно не будет конфликтов слияний, при этом он будет иметь доступ к глобальным методам и компонентам (модалки, нотификации, апи, роутинг), что уберет дубляж, будет поддерживать SSR, а апдейт зависимостей можно сразу протестировать на всем приложении. Не идите в эти дебри, тут вы не первопроходцы, а просто пополняете ряды страдальцев, занимающихся вместо продуктовой разработки решением самими же созданных проблем.

  • Крупные компании, использующие Node.js
    +1

    А я с вами и не спорил, читал внимательно — "Если вопрос про SSR то да", просто описал схему работы и показал, что это действительно ускоряет метрики загрузки интерфейса. Но в случае SPA, когда интерфейс описан на js, на сервере нужна среда, которая умеет его выполнять — так что нода практически без вариантов. Чтобы было более понятно, напишу пример:


    Клиентский код:


    export class App extends Component {
      render() {
        return (
            <div className={styles.app}>
              123
            </div>
        );
      }
    }

    Серверный код:


      app.get('*', (req, res) => {
        Promise.resolve()
          .then(() => injectAppMarkup(template))
          .then((modTemplate) => injectInitialStoreData(modTemplate))
          .then((modTemplate) => res.send(modTemplate))
      });
    
    export function injectInitialStoreData(str: string) {
      const storeEscaped = escapeAllStrings(store);
    
      return str.replace('<!-- INITIAL_DATA -->', JSON.stringify(storeEscaped));
    }
    
    export function injectAppMarkup(str: string) {
      return str.replace(`<!-- HTML -->`, renderToString(<App />));
    }

    В итоге получаем соответствующий странице html-код в первом запросе + объект вида window.INITIAL_DATA = { someData: 'test' };, который можно отправить в клиентский js-код и чисто гидрироваться с выданной сервером разметкой. Еще раз повторюсь, что говорю про SPA, когда один и тот же js изоморфно выполняется на клиенте и сервере, а не когда клиентский js вручную навешивает какие-то события и триггеры на шаблон, отданный бэком. В других серверных языках выполнение React.renderToString может быть только в виртуальном окружении.

  • Крупные компании, использующие Node.js
    +1

    Похоже, вы не знакомы с концептами SPA и SSR — почитайте. На сервере делается выполнение js-кода и конвертация в html-строку со всем размещением данных, этот html отдается клиенту, и он "гидрирует" то, что получил от сервера и то, что ожидают скрипты, выполняющиеся на клиенте. Это достаточно новый концепт, но он действительно значительно ускоряет загрузку клиентского интерфейса — я описывал выше.

  • Крупные компании, использующие Node.js
    +1

    И как же другие серверные языки могут выполнить js-код, на котором написан клиент, чтобы сформировать html? Разве что с помощью виртуальной node-среды, так это то же самое. Я сейчас говорю про SPA, а не про древнюю схему, когда на сервере хранятся html-темплейты и реплейсом заменяются какие-то части, а соответственно при переходе на новую страницу делается полный рефреш страницы либо по аяксу загружаются куски готового html и заменяются — эта схема давно устарела, у нее громадное количество недостатков.

  • Крупные компании, использующие Node.js
    +4

    Если вопрос про SSR то да, нода позволяет изоморфно выполнять js-код и ряд фреймворков может компилироваться в готовый html. Асинхронные запросы за данными тоже могут выполняться на сервере, предоставляя в json-формате готовые структуры. Если бэк написан на другом языке в соседнем докере — то делать запросы к нему можно эффективней, чем с фронтенда, напрямую в его докер. Если он написан на ноде — то еще быстрей, фактически только в базу сходить. Сюда добавляется эффективное кеширование, и в итоге если раньше SPA делало 5 запросов на клиенте после обработки JS, то есть это время плюсовалось и стадия отрисовки и тем более интерактивности наступала с большой задержкой, то с подобной схемой при первом открытии страницы нужно 0 запросов и готовый html получается при первом запросе, соответственно значительное ускорение. В энтерпрайзе такая схема уже четвертый год используется, по крайней мере в тех проектах, в которых я участвовал — все метрики перфоманса действительно значительно улучшаются.


    Минус — больше серверных ресурсов уходит на рендеринг, но это вполне горизонтально масштабируется. Количество запросов в секунду у ноды тоже стало приемлемым, при необходимости, опять же, балансируется. Но для хайлоада все же лучше оставить в ноде только веб-часть, а требовательные к перфомансу сервисы писать на более низкоуровневых и многопоточных платформах.

  • Чем дальше живёшь — тем меньше получаешь? Абсурд в условиях удалёнки
    +3

    Плюсанул за последний абзац — ровно 5к и 1-в-1 описание, пару лет так работаю на зарубежные компании. И бывшие коллеги точно по такой же схеме, так что максимально жизненно. Выше ставка только по проектной работе бывает — на 2-3 месяца, а с учетом простоя то на то и выходит.

  • Фрактальный state-менеджер на генераторах*
    +1

    Здорово получилось, действительно что-то новое, шустрое и почти юзабельное. По старой привычке переписал примеры для себя на mobx — намного меньше кода получилось и он полностью лишен бойлерплейта, кроме вызова makeAutoObservable в конструкторе, так что все-таки в проекты не потащу — там скорость восприятия кода и явность взаимосвязей намного важнее сэкономленных килобайтов, но для пет-проджекта для развития нового восприятия работы с данными — вполне можно.


    Об одном моменте задумался — генераторы же не полифиллятся, но судя по caniuse поддерживаются 95.41% клиентов, значит вполне уже можно в прод, если не для госконтор и азиатского рынка. В общем — годно.