Обновить
8K+
52
Дмитрий Казаков@DmitryKazakov8

Front-end архитектор

16,1
Рейтинг
45
Подписчики
Отправить сообщение

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

По поводу metadata (title, description, social теги) - это хотя и можно сделать через роутер (внутри beforeEnter), лучше все-таки использовать компоненты страниц. То есть проставлять их при рендере на onMount или другими способами конкретной UI-библиотеки, так сохранится поддержка SSR и MPA.

Под локализацией не понял, что имеется в виду, так как есть разные схемы. Например, заводят поддомены вида lang.mydomain , тогда в конфигурации роутера никаких изменений делать не нужно. Либо если через params - можно к каждому path добавлять параметр /:lang/home , либо через query: { lang: (v) => ['en', 'ru'].includes(v) } . Я бы рекомендовал вариант с поддоменами - поисковики с этим лучше работают, да и код не нужно подстраивать.

Статистики именно по "качеству" нигде нет, исхожу только из личного опыта и открытой статистики. Например, в прошлом году на Гитхабе 81% коммитов были именно в приватных рабочих репо, и процессы там как правило строже - с ревью, тестами, постоянной production-доработкой и адаптацией к новым технологиям.

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

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

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

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

И хорошего варианта пока не видно. Можно, конечно, предоставлять skills - но это очень ненадежный и часто игнорируемый моделями файл, тем более что для всего зоопарка моделей и их весов и других характеристик не получится сделать стабильно. Даже если автоматизировать в CI промпт "напиши на Symbiote с нуля сайт вот с таким функционалом" и давать десятку разных агентов - результат будет всегда разным, это очень сложно проверить.

А ждать, пока конкретная библиотека "завирусится" и будет настолько широко использоваться, что перебьет веса других либ - очевидно, совершенно нерабочая схема. MCP же только для энтузиастов, его всегда надо использовать осторожно - очень большие риски для безопасности, и точно не для массового потребителя.

По сложности работы с Custom Elements и расхождению типов и рантайма тоже распространенная проблема, я вот стараюсь избегать всех технологий, которые к этому приводят.

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

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

Обычная очередная внутрикорпоративная библиотека, которая интегрируется в корпоративный стек этой компании, частично выпущенная в опенсорс. Вспоминается тот же БЭМ, который подходил если для него уже есть большая унифицированная инфраструктура, а как частичный выпуск в опенсорс был хуже тех же CSS Modules, так как решал проблему изоляции стилей многословно и ограниченно (все равно возможны глобальные пересечения).

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

Тут не наш профиль) Статью про блоги / контентные сайты тегнули Реактом зачем-то. И так понятно, что для этих задач даже Wordpress тяжеловат и лучше что-то совсем простое на статике делать с минимальным шаблонизатором и нативным js для кнопки "лайкнуть". И уж точно тут не нужен Next или другой мета-фреймворк.

Люди ругаются, что для простейших задач кто-то тянет инструменты уровня "из пушки по воробьям", и это оправданно. А для веб-приложений действительно нужен полноценный стек. Одно смущает - что кто-то этого действительно не понимает и ставит минусы, думаю тут просто недопонимание.

Ну получилась самая базовая реализация, до production-ready еще пара десятков итераций и переосмысления нужна.

Много бойлерплейта, создание через классы new FormGroup(), new FormContol() - это не сериализуется в json (значит не будет удобного SSR), синтаксис - плоские аргументы ('', [required()]) с "магическим маппингом что первый аргумент - значение, второй - массив валидаторов". Это не расширяется, а валидаторы в массиве - очень неудобно в реальности, лучше объектом.

Вывод в UI недекларативный. Да и в целом может понадобиться много параметров для инпутов - isFocused, isDisabled, options (для селектов), formatters, кастомное поведение валидации на onBlur либо на onSubmit, показ лоадеров и предзагрузка данных, и т.п. То есть лучше всегда оставлять конфиг формы гибким и расширяемым для пользователей библиотеки.

В общем, ничего пока что интересного по сравнению с подходом отсюда .

Согласен, в статье хорошо разобрана одна из сфер, где пригодится BFF. В целом "классическое" его назначение - это SSR / SSG, если проекты клиентские (не внутренние админки в закрытых сетях), контроль CSP (т.к. фронтендерам часто удобнее поддерживать именно там динамические политики, чем лезть в nginx или другой прокси) и изоморфный контроль прав. Вот последнее - это интересная тема, разверну.

Возьмем как раз админку в закрытой сети. Бэк отвечает в целом за авторизацию, плюс есть роли / фича-тогглы и например 100 ручек. Нужна мощная система контроля доступа (например, показ определенного раздела только если есть фича-тоггл, а также гранулярный контроль возможности редактировать/обновлять/удалять/смотреть подразделы). Фронт в любом случае будет это делать if-else для показа элементов, то есть будет обладать 100% информации о том, что где кому доступно. А бэк обладает ограниченной информацией, т.к. часто нужно строить граф зависимостей фича-тогглов (например, раздел "продукты" тянет 10 ручек словарей, ручку авто-анализа, вывода таблицы, редактирования-удаления, стейт-машин и еще несколько смежных). Фронт уже имеет этот граф, и может безошибочно сказать "вот эти 10 ручек должны быть доступны, если включен фича-тоггл просмотр продуктов".

Поэтому в BFF просто можно взять готовый граф из фронта, и отдавать 403 сразу из node.js вместо проксирования в бэк. А поддерживать это все и синхронизировать в реальном бэке - "черная дыра" по ресурсам и потенциальным багам + замедление релизов и усложнение тестирования. Тут BFF для гранулярного контроля выступает отличным ускорителем разработки и достаточной защитой от несанкционированного доступа, тем более что при продуманной архитектуре нужно ровно 0 изменений в BFF - при изменении логики все подтянется автоматически.

Есть и множество более частных применений (например вебсокет-прослойка или SSE), и описанная в статье "подготовка и оптимизация данных под конкретного потребителя" - тоже очень валидный кейс. Особенно BFF помогает, когда узкое место - это количество/качество бэк-команды и она не успевает за фронтом, тогда можно временно "набросать для показа" на node (либо полноценно с интеграцией базы, либо на моках). Бизнес будет доволен, инвестиции будут получены, полноценный бэк - подтянется в своем ритме.

Будет интересно посмотреть, как у вас будут реализованы формы и сравнить. Я обычно беру такой подход (универсальный для React, Solid, Vue, просто движок реактивности разный под капотом - синтаксис полностью одинаковый).

const form = new FormConfig<{
  inputs: {
    objectType: TypeInputSelectConfig;
    insuranceStartDate: TypeInputDateConfig;
  };
  submit: TypeInputSubmitConfig;
}>({
  inputs: {
    objectType: {
      type: 'select',
      value: { name: '', value: '' },
      options: [
        { name: 'АЗС', value: 'gas' },
        { name: 'Краны', value: 'crane' },
      ],
      validators: { emptySelect: validators.emptySelect },
      errors: [],
      placeholder: messages.placeholderObjectType,
    },
    insuranceStartDate: {
      type: 'date',
      value: '',
      validators: { emptyString: validators.emptyString },
      errors: [],
      placeholder: messages.placeholderInsuranceStartDate,
    },
  },
  submit: {
    type: 'submit',
    label: messages.submit,
  },
});

class VM implements ViewModel {
  constructor() {
    makeAutoObservable(this, undefined, { autoBind: true });
  }

  form = form.copy();
  result = '';

  handleSubmit() {
    const { objectType, insuranceStartDate } = this.form.inputs;

    const someValueInvalid = 
      !objectType.check() || !insuranceStartDate.check();

    if (someValueInvalid) {
      console.log('prevent submit');
    }
	
	this.result = JSON.stringify(this.form.inputs, null, 2);
  }
}

export function Example() {
  const { vm } = useStore(VM);

  return (
    <>
      <Form formConfig={vm.form} onSubmit={vm.handleSubmit}>
        {({ inputs, submit }) => (
          <>
            <div className={styles.inputsLine}>
              {inputs.objectType}
              {inputs.insuranceStartDate}
            </div>
            {submit}
          </>
        )}
      </Form>
      <pre className={styles.pre}>{vm.result}</pre>
    </>
  );
}

form здесь - независимый реактивный объект, в терминологии Mobx - observable. Расширяемый, полностью типизированный, можно создавать копии или использовать 1 инстанс если нужна синхронизация, SSR из коробки (в том числе с уже выведенными в интерфейс ошибками).

Разметка - декларативная, сами компоненты инпутов просто маппятся по type из любой UI-библиотеки с простой интеграцией (по сути в onChange инпуты меняют соответствующий value).

Соответственно, работают любые реактивные паттерны - computed геттеры (если нужно собрать данные из нескольких полей и по-особому вывести), autorun / reaction если нужна логика взаимосвязанности (например - при изменении одного поля изменить значение в другом или отфильтровать options / перевести в disabled, а также для взаимодействия нескольких форм).

В целом, подходит для сложнейших форм и не натыкался на ограничения. Единственное, что не всем понравится - data-driven (отсутствие каких-либо onChange колбэков). Если надо отреагировать на установку фокуса в инпуте - будет reaction(() => insuranceStartDate.isFocused, callback), а это часто сложнее воспринимается, чем onFocus, и требует dispose при анмаунте компонента. Но для использующих реактивные подходы - привычно.

Будет интересно сравнить с вашим решением.

Вот как раз что я и ожидал - ответ от ИИ, полностью игнорирующий описанный мной концепт, и рекламирующий библиотеку)

i18next, next-intl или vue-i18n - неоптимизированные библиотеки с неэффективным использованием, тут соглашусь, но я же описал подход, никак с ними не связанный. Файлы message.ts - модульные, а общий json нужен только для переводчиков и удобной выгрузки в системы локализации. В коде его вполне можно разбивать на чанки хоть под каждый модуль, хоть под скоуп модулей (например для страницы src/pages/intro брать все тексты из json с этим префиксом). Это гибкость, универсальность и минимальный бойлерплейт.

Конфликты при слиянии веток здесь возможны только если параллельно работают над одним и тем же messages.ts - и точно такие же конфликты будут в Intlayer, так как он тоже использует модульные файлы с локализацией (но вроде без сборки их в большой json). Но это "слабые" конфликты, которые легко решаются автоматически, т.к. все ключи - уникальные.

ИИ захватывает Хабр(

Довольно часто вижу в ленте статьи по Intlayer - вы стараетесь его популяризировать, но не понимаю практической применимости. Обычно переводы в проектах делаются проще и эффективнее.

Посмотрим в контексте "ретроспективного внедрения интернационализации" + React. На данный момент все тексты захардкожены в компонентах, бизнес ставит задачу - перевести на несколько языков.

1.Нужно вынести тексты в объекты, это прекрасно типизируется TS и есть немало инструментов, позволяющих идентифицировать "неиспользуемые ключи в объекте", то есть масштабируемость - хорошая.

// было
function Component() {
  return <div>Hello</div>
}

// стало
const messages = {
  hello: 'Hello'
}

function Component() {
  return <div>{messages.hello}</div>
}

2.Вынести объект messages в отдельные файлы для переиспользуемости и задать автогенерацию уникальных ключей

// src/pages/intro/messages.ts

export const messages = wrap(__dirname, {
  hello: 'Hello'
})

console.log(messages);

// { "src/pages/intro__hello": { default: "Hello" } }

__dirname здесь - простейший уникальный для файла идентификатор, многие бандлеры умеют с ним работать "из коробки". Но можно использовать любой, прокидывая бандлером.

3.Добавить возможность подключить шаблонизатор для плюрализации, работы с датами, падежами и т.п., готовых в js-экосистеме масса. Достаточно сделать функцию ln, а движок подбирать по нуждам проекта либо делегировать это сторонней системе вроде Localise.

function Component() {
  return <div>{ln(messages.hello)}</div>
}

Функция ln может под капотом иметь разную реализацию (например, возвращать реакт-компонент) или быть реактивной на сигналах (сменилась локализация - все функции перевызвались, обновив тексты в приложении), это все делается парой строк.

4.Собрать все тексты в json-файлы и встроить генерацию в бандлер перед сборкой и в watch-режиме

// translations.json
{ 
  "src/pages/intro__hello": { "default": "Hello", "ru": "", "en": "" } 
}

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

Собственно, все. Это база, которая и так есть в большинстве проектов, и может очень гибко настраиваться под стек, в том числе делая отдельные json-чанки под компонент (чтобы не все локализации грузились сразу). С ИИ этапы 1 и 2 делаются за полчаса, 3 и 4 пишутся за день под конкретные технологии и требования в проекте.

Итог - задача выполнена, при добавлении/удалении ключей в любом модульном messages.ts обновляется JSON, выгружается в систему переводов, и для изменения переводов не нужны разработчики - переводчики могут менять тексты сами, не влияя на код проекта.

А каждый раз, когда захожу на документацию Intlayer, не понимаю зачем столько бойлерплейта и сложностей, зачем вручную задавать ключи с дубляжом для каждого языка; писать переводы прямо в messages вместо того, чтобы отдавать json переводчикам или в автоперевод (поэкономьте время разработчиков); привязываться к встроенным механизмам шаблонизации (когда часто это должно быть частью локализационной системы типа облачного Localise). И много еще другого, что мне кажется крайне неэффективным, и видя это закрываю вкладку с документацией.

Скорее всего, пишу это "в пустоту" - половина ваших комментариев на Хабре ИИ-нейрослоп, и все для рекламы, но слишком уж часто эта поделка попадает в ленту.

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

Раньше вот были профессии "вебмастер" или "веб-технолог" - это и дизайн, и верстка, и фронт, и бэк на CMS, и настройка серверов, и обслуживание / мониторинг, и общение с бизнесом для составления ТЗ, и даже наполнение контентом. Да, глубоко погружаться в каждую область не требовалось - зато позволяло выбрать то, что интересно.

Я тоже выбрал фронт - и это огромная область, к которой сам раньше относился как к "формошлепству", но оказалось что требуется десяток лет, чтобы нормально сделать архитектуру под форму на 50 взаимосвязанных полей с 15 компонентами (range, daterange, tree select) с десятком модалок на заведение новых сущностей тоже с громадными формами, SSR этого всего с асинхронной подгрузкой данных для каждого селекта, параллельной работой по сокету нескольких сотрудников, сохранением недозаполненных форм в Local Storage, фича-тогглами и ролями какой кому показывать инпут а какой отключать в disabled... Это маленькая задача, каких тысячи в реальных проектах среднего (даже не крупного) размера на 2 дня, и нужна мощнейшая автофайлогенерация, продуманные полностью типизированные библиотеки и длинные надежные цепочки отказоустойчивости с мониторингом (иногда - в реальном времени).

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

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

По бэку сложнее, но опять же все публичные контракты можно вытянуть и вывести логику через эксперименты в Postman, и запрограммировать на любом удобном языке. Главная ценность в ИТ с давних пор - не код и логика, а данные и привязка аудитории. Так, никому не нужен клон Telegram - его код спокойно лежит в опенсорсе, потому что у клона не будет аудитории. А у клона Хабра - не будет данных и опять же лояльности посетителей.

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

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

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

ИИ предлагает вероятностный код как со StackOverflow, ты его просматриваешь и не вчитываешься - задачу решает, тесты проходят, стиль немного "не твой", ну и ладно. И сразу же теряешь экспертизу, потому что не сам прошел путь написания, не выстрадал решение и оно не стало твоим "капиталом" - это просто копи-паста, которая не развивает как инженера.

Даже в рутинных задачах лучше заниматься кодом самому - видишь, где можно оптимизировать, где сделать автогенерацию, например readFile -> regexp(endpoints) -> writeFiles(boilerplate service + tests + types). Иногда приходят мысли об изоляции или наоборот универсализации для сокращения кода и удобства управления. В итоге через какое-то время достаточно 1 строчки кода для нового функционала - остальное генерируется стандартно, стабильно, отказоустойчиво, без лишней когнитивной нагрузки и за 0.01с при изменении файлов, которые наблюдаются file watcher.

И получается что "30% экономии времени с ИИ" превращается в "через год все заросло дубляжом и легаси, потому что не оптимизировалось и упрощалось вживую" + "ухудшились навыки как инженера на 30%, потому что разучился тщательно продумывать решения". В итоге - деградация и скатывание в написание промптов и оркестрацию.

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

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

Самое главное - давать удобные "коннекторы" для других "кирпичиков". В случае Mobx даже их не требуется - синтаксис остается идентичным, как если Mobx вообще не подключать, а писать на голом JS. То есть по умолчанию с ним совместимо большинство js-библиотек, если конечно у них не встроена своя система состояний.

Вы как-то не совсем правильно сравниваете Mobx и Reatom.

Mobx - шуруповерт без насадок. Он добавляет в JS реактивность для объектов, то есть если меняется свойство - то вызываются подписчики, все. Это хороший мотор, который может крутить все что угодно. Это не СТМ, а очень крутой полифилл для deprecated нативного Object.observe. Если нужны "насадки" (экосистема) - этим занимаются другие библиотеки. Можно писать обычный код на js с обычными объектами/классами, но только реактовые компоненты не будут ререндериться. Добавляем observable+observer - все точечно ререндерится.

Reatom - это большая коробка отверток "на все случаи жизни". Как вы заметили - туда запихнули работу с асинхронностью, роутер, ленивый фетчинг, кешы и механизмы для работы с апи, снепшоты состояний и даже sleep функцию. Это можно сказать целый фреймворк со своими гайдлайнами и способами написания кода (например, что свойства надо вызывать как функции counter()). То есть нужно изначально писать на Reatom весь код, нельзя написать на js-объектах и обернуть в пару функций, чтобы все стало реактивным.

Странно слышать, что в Mobx "нет этого или того-то", у него абсолютно другая парадигма - "делать свое дело и делать хорошо". А у ряда библиотек, например Реакта, другая парадигма - "сделаем все-в-одном". Вместо того, чтобы просто рендерить компоненты в DOM и делать это хорошо, они стали внедрять свой стейт-менеджмент, асинхронные механизмы, серверные компоненты, навязывать парадигмы вроде иммутабельности и правил хуков. Да и у ряда компаний есть такой подход - Яндекс например или Сбер стараются охватить все рынки, от образования и развлечений до доставки еды, платежных систем и такси.

Кому-то нравится, когда все в единой экосистеме и "поддерживается одной командой", пусть определенные части сделаны откровенно ужасно (мы ведь тут в статье про Реакт обсуждаем СТМ для него, а ведь у него уже есть встроенная СТМ, просто она слишком плоха). А кто-то выбирает пользоваться специализированными сервисами/библиотеками с ясной ответственностью, которые сделаны максимально качественно. И чем больше насмотренности, экспертизы и опыта, тем менее хочется мириться с подходом "все-в-одном", и вы тут с нами в одной лодке, отказавшись от реактовых подходов. Но в Реатоме я как и другие вижу много недостатков, и не готов полностью на него переходить, а выберу лучше несколько специализированных библиотек.

Я тоже работал в проектах, где на Mobx создавали абсолютно неподдерживаемого монстра, используя все возможные антипаттерны. Например, использовали автонормализацию snake_case -> camelCase при получении данных из сторонних источников, что ломало быстрые переходы и поиск по проекту. Делали огромные Rich Store на тысячи строк, неконтролируемые autorun во всех возможных местах, использовали одновременно реактивные состояния и useState/useEffect, причем пытаясь из их комбинации сделать computed. По структуре тоже была каша - и Entity Stores, и сервисы со своими сторами, и модульные, и глобальные в несколько уровней.

Так что ваш аргумент тоже корректен - чем более гибок инструмент, тем легче писать некачественный код. Но вот еще один поинт - из Mobx очень легко сделать Redux. Просто добавить в ваш пример в статье метод dispatch(action, payload) , который будет делать Object.assign(this._state, payload) в мутабельном стиле (для оптимизации изменения глубоко вложенных структур придется чуть усложнить). Ну и switch-case туда. При этом рендеринг UI компонентов будет оптимизирован из коробки - что бы мы ни меняли, будут точечно ререндериться только те компоненты, которые читают конкретный параметр, и только когда он изменился.

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

То есть никто не запрещает написать на Mobx флоу работы с данными как в Redux, описать это в тех. документации и на ревью проверять, что все разработчики придерживаются этого флоу. Либо не Redux-like, а выбрать удобный для проекта и команды способ установки-получения значений, ведь этих паттернов огромное количество, и Mobx с очень большой вероятностью сможет так работать. То есть он - это все остальные СТМ вместе взятые, остается только выбрать удобный подход и консистентно работать с ним.

В Mobx тоже перерисовка связана явно, только вместо dispatch с полным пересозданием структуры здесь просто мутация store.param = value. Это дает намного более удобный DX - можно в IDE посмотреть все места, где читается/изменяется конкретное свойство и работают быстрые переходы.

А в Redux нужно сначала найти нужный initialState, потом найти десяток редюсеров, которые меняют в нем param, потом найти action name, по нему сделать полный поиск по проекту, чтобы найти все места где делается dispatch с этим названием экшена, не забыть пройтись по селекторам и connect HOC, чтобы узнать, где используются конкретный стор, а потом в каждом найденном компоненте искать где читается param. К сожалению, довольно много работал с Redux и пол-дня состояло как раз из этих действий, потому что никаких быстрых переходов или Find Usages у него не предусмотрено.

И с Redux в итоге не так-то просто найти, "почему компонент перерендерился", потому что нужно смотреть в Dev Tools и вручную искать какой именно из диспатчей данных повлиял на конкретный компонент, проходя все этапы, описанные выше. Но да, в нем есть диффы состояний, которые немного могут упростить процесс.

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

На Mobx можно писать так же, как в примере на Valtio, используя вместо proxy функцию observable. Единственное отличие в коде будет в том, что Mobx подключается к реактовым компонентам через враппинг в HOC observer, а Valtio - через useSnapshot. Плюсы Mobx подхода с враппингом в том, что можно использовать хоть 100 разных реактивных состояний в компоненте напрямую, без вызова для каждого useSnapshot, а сам враппинг можно сделать автоматически через бандлер, то есть компоненты в коде будут выглядеть чистыми.

Вариант с классовыми сторами просто более удобен в плане DX, поэтому часто выбирают его (меньше импортов и констант, меньше коллизии имен, не важен порядок объявления методов и геттеров). Но можно писать и объектами

Хорошо структурированный код - это не только разбиение по семантическим папкам (пакетам) и отдельным файлам со связанной логикой и заботой о переиспользовании. Это еще и удобный DX в виде быстрых переходов на место объявления. Здесь же чтобы попасть в нужное место приходится делать десяток быстрых переходов, причем иногда они динамические и могут быть не связаны типами, и приходится делать "поиск по всем репозиториям". Другими словами - "обертка на обертке с названиями переменных в 1 символ".

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

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

1
23 ...

Информация

В рейтинге
470-й
Зарегистрирован
Активность