Вот тут наглядно показывают. В двух словах: если рендеринг какого-то поддерева компонентов занимает неприлично много времени, то ему можно назначить низкий приоритет. И остальной инрерфейс не будет тормозиться.
Настоящий ад начинается если внутри ручных подписок (intercept/observe/autorun) на одни реактивные данные, изменять другие реактивные данные. Но за такое надо бить по рукам.
На самом деле, никто не мешает для MobX завести не несколько хранилищ, а одно, как в Redux. Пару проектов делал именно в таком ключе. Один на MobX, другой по сложнее на mobx-state-tree.
Правда, бизнес логику нужно будет вывести в отдельный слой сервисов. А стор тогда получится вырожденным. Просто хранилище реактивных данных. И не нужно никаких отдельных классов. Да, в таком варианте мы несколько жертвуем эффективностью. В случае классов мы можем выборочно навешивать @observable. А тут реактивным будет все. Но в Vue же как то живут с этим и не жалуются.
ЕМНИП, они убрали componentWillReceiveProps ради concurrentMode. Просто потому что при асинхронном рендеринге может быть выкинуто несколько "фреймов" компонента и prevProps "отстанут" на несколько циклов рендеринга. Т.е. результат componentWillReceiveProps будет зависеть от того насколько тормозит рендеринг. А это уже дичь какая-то.
Еще в угоду concurentMode они пожертвовали корректностью работы библиотек, основанных на синхронных подписках. Как Redux и MobX ага =)
Хотя в целом, я с вами согласен. Завтраками с concurrentMode они кормят нас уже два года. Со стороны ситуация выглядит абсурдно — фичи еще нет, а люди от нее уже страдают =) И вообще не очевидно, будет ли от этого реальный профит. А не только красивые презентации на конференциях.
На самом деле в Elastic c русской морфологией сейчас беда.
Упомянутый плагин analysis-morphology от Игоря Мотова не поддерживает Elastic версий 6 и 7. Последнее, что я находил — это сборка под 6.6.1 сделанная каким-то энтузиастом. Под другие версии (даже 6.x.x) она не работает.
Не, ну на беке микросервисы хотя бы повышают отказоустойчивость и улучшают балансировку нагрузки. Теоретически. Если правильно их приготовить :) Но я и на беке не люблю, когда микросервисами злоупотребляют.
А тут просто какое-то натягивание архитектуры фронта на структуру отделов компании-разработчика.
Для каждого микро-приложения используются свои технологии. Как уменьшить размер бандлов, загружаемых на клиент? Ведь у нас для каждой фичи свой фреймворк. А может даже разные версии одной библиотеки. На беке то такой проблемы нет.
У нас вдруг запланирован редизайн. Как согласованно обновить N разных приложений со своим подходом к стилям? Или это должны делать N команд параллельно? Не слишком ли расточительно?
Вряд ли все микро-приложения будут активно развиваться в течение всего жизненного цикла продукта. Большая часть это сделал — забыл. А основная активность сосредоточена только в паре-тройке разделов. Как тогда управлять техническим долгом, обновлять зависимости? Не окажемся ли мы потом с кучей разрозненного хлама?
Последнее мне вообще напомнило разработку на классических серверных MVC фреймворках лет 7 назад. Когда разные страницы имели свой независимый набор подключенных JS-библиотек.
Такое чувство, что этот подход применим только для каких то очень больших сайтов, где параллельно только фронтом должны заниматься десятки человек. Или наоборот, когда нужно быстро наваять среднее приложение, а договариваться об архитектуре не хочестя. Главное, чтобы потом поддерживать это приложение не тебе =)
Просто непонятно, куда в итоге React развивается. Я с трудом представляю себе достаточно сложный SPA, написанный на голом реакте без state management библиотек. И что же они с этим делают?
Предоставляют более удобные примитивы для облегчения разработки state контейнеров? Нет. Учли наработки community и делают полноценный фреймворк? Нет.
Вместо этого они мутят какую-то свою уличную магию с хуками. А разрабы state контейнеров отплясывают вокруг этого с бубном, чтобы все оно хоть как-то работало.
Да, с хуками стало лучше. Вроде того, что если раньше на голом реакте боль начиналась с 10K строк кода, а теперь только с 20K. Но на 100K все равно нужен state management.
Нормальным было бы затягивать в апстрим best practices, опробованные коммъюнити в библиотеках. Как это делают в стандарте языка и Babel-плагинах. А сейчас мы имеем:
Хотите иммутабельного состояния — ну нате вам useReducer(). Что, Context API не умеет в селекторы? Ну так оно не для управления стейтом, а для тем всяких там. Механизм подписок не дружит с concurrent mode? Ну извиняйте. Короче, не мешайте нам делать красивые доклады на конференциях, а валите в свой Redux / MobX.
Сейчас, ясное дело, ничем. А вот при выходе следующей версии библиотеки, авторы могут: заменить class компонент на хуки; реализовать таки sCU(). И наша карета превратится в тыкву.
Да это понятно. По хорошему, TreeView должен иметь какой-нибудь опциональный prop renterTreeNode, в который мы могли бы запихнуть хоть observer(TreeView) хоть connect(...)(TreeView).
Но тогда непонятно, что делать самим авторам UI-фреймворков под реакт:
Поставлять отдельные версии компонентов под иммутабельные или реактивные данные? И если под иммутабельные еще можно, поскольку это все еще plain-объекты, то под реактивные — это зависимость от mobx (или чего там еще).
Делать все промежуточные компоненты конфигурируемыми (те, что пользователи фреймворка не используют напрямую, вроде TreeNode для TreeView)? Это уже интереснее, но попахивает каким-то внедрением зависимостей.
А вот о стандартном механизме DI должны были подумать авторы самого React. Сейчас есть много реализаций, но все они — пляски с бубном или как минимум неизвестны широкой публике. И тут у UI-фреймворка опять дилемма — вставлять зависимость на что-то маргинальное? Или ваять свою систему конфигурации?
Если мы полностью владеем кодом всех компонентов проекта, то проблем нет. А вот если используем какой-то визуальный фреймворк, то тут уже интереснее. У нас был затык с third-party TreeView, который рекурсивно рендерит сам себя для вложенных элементов дерева. Решений два:
Как-то пропатчить TreeView, чтобы он стал обсервером. С mobx-react 5 для этого достаточно вызвать observer() на TreeView, т.к. по счастливому стечению обстоятельств это был классовый а не функциональный компонент. Но это блин махровый манки-патчинг в самом худшем его проявлении.
Вызвать mobx.toJS() на корневом узле данных дерева, как советовали в одном issue от mobx. Это сразу подпишет рендеринг всего дерева на любое изменение данных. Ну и здравствуй пересоздание развесистых объектных графов на каждый чих. И прощай производительность.
В защиту mobx можно сказать что с Redux, как превратить рекурсивный third-party компонент в connected, тоже непонятно.
А не думали выкинуть moment в пользу какого-нибудь модульного date-fns? Это существенно уменьшит вес бандла. Единственное, чем можно объяснить сейчас использование moment — это legacy. Или библиотеки UI компонентов под реакт, где он прописан в зависимостях.
И как раз поэтому каждый проект на Redux, к которому ты подключился не со старта разработки — это целый комбайн спорных/чьих-то чужих решений. Кто-то обязательно натащит туда модных на данный момент библиотек для упрощения работы с ним. Потому что работать с голым редаксом — боль.
Основная проблема таких проектов — отсутствие коммъюнити, и как следствие, фрагментация.
Есть куча библиотек, построенных вокруг использования Proxy для отслеживания изменений. Например:
easy-peasy — Redux-like стор с Immer внутри и селекторами снаружи
react-tracked — а здесь наоборот, Proxy используются для отслеживания зависимостей при рендеринге, как в MobX
overmind — а здесь реализованы обе фичи, почти как mobx-state-tree. Но нет JSON-patch и объектного графа.
При чем здесь реакт компоненты? Я же говорю о выборочных
@observable
на разные поля класса модели. А не об@observer
на компоненты.Вот тут наглядно показывают. В двух словах: если рендеринг какого-то поддерева компонентов занимает неприлично много времени, то ему можно назначить низкий приоритет. И остальной инрерфейс не будет тормозиться.
Настоящий ад начинается если внутри ручных подписок (intercept/observe/autorun) на одни реактивные данные, изменять другие реактивные данные. Но за такое надо бить по рукам.
На самом деле, никто не мешает для MobX завести не несколько хранилищ, а одно, как в Redux. Пару проектов делал именно в таком ключе. Один на MobX, другой по сложнее на mobx-state-tree.
Правда, бизнес логику нужно будет вывести в отдельный слой сервисов. А стор тогда получится вырожденным. Просто хранилище реактивных данных. И не нужно никаких отдельных классов. Да, в таком варианте мы несколько жертвуем эффективностью. В случае классов мы можем выборочно навешивать @observable. А тут реактивным будет все. Но в Vue же как то живут с этим и не жалуются.
ЕМНИП, они убрали componentWillReceiveProps ради concurrentMode. Просто потому что при асинхронном рендеринге может быть выкинуто несколько "фреймов" компонента и prevProps "отстанут" на несколько циклов рендеринга. Т.е. результат componentWillReceiveProps будет зависеть от того насколько тормозит рендеринг. А это уже дичь какая-то.
Еще в угоду concurentMode они пожертвовали корректностью работы библиотек, основанных на синхронных подписках. Как Redux и MobX ага =)
Хотя в целом, я с вами согласен. Завтраками с concurrentMode они кормят нас уже два года. Со стороны ситуация выглядит абсурдно — фичи еще нет, а люди от нее уже страдают =) И вообще не очевидно, будет ли от этого реальный профит. А не только красивые презентации на конференциях.
На самом деле в Elastic c русской морфологией сейчас беда.
Упомянутый плагин analysis-morphology от Игоря Мотова не поддерживает Elastic версий 6 и 7. Последнее, что я находил — это сборка под 6.6.1 сделанная каким-то энтузиастом. Под другие версии (даже 6.x.x) она не работает.
Вместо него в оф. документации предлагается использовать морфологию на основе hunspell-словарей.
Ну и в принципе все работает, но:
Например, с "мама мыла раму" hunspell справится, а вот с "Бармаглотом" уже нет.
В отличие от russian_morphology:
На форуме вот советуют самому словари заполнять.
Не, ну на беке микросервисы хотя бы повышают отказоустойчивость и улучшают балансировку нагрузки. Теоретически. Если правильно их приготовить :) Но я и на беке не люблю, когда микросервисами злоупотребляют.
А тут просто какое-то натягивание архитектуры фронта на структуру отделов компании-разработчика.
Возникают еще проблемы, не озвученные в статье:
Последнее мне вообще напомнило разработку на классических серверных MVC фреймворках лет 7 назад. Когда разные страницы имели свой независимый набор подключенных JS-библиотек.
Такое чувство, что этот подход применим только для каких то очень больших сайтов, где параллельно только фронтом должны заниматься десятки человек. Или наоборот, когда нужно быстро наваять среднее приложение, а договариваться об архитектуре не хочестя. Главное, чтобы потом поддерживать это приложение не тебе =)
Да, действительно.
connect()
на top-level TreeView, а на внутренниеmemo()
.Просто непонятно, куда в итоге React развивается. Я с трудом представляю себе достаточно сложный SPA, написанный на голом реакте без state management библиотек. И что же они с этим делают?
Предоставляют более удобные примитивы для облегчения разработки state контейнеров? Нет. Учли наработки community и делают полноценный фреймворк? Нет.
Вместо этого они мутят какую-то свою уличную магию с хуками. А разрабы state контейнеров отплясывают вокруг этого с бубном, чтобы все оно хоть как-то работало.
Да, с хуками стало лучше. Вроде того, что если раньше на голом реакте боль начиналась с 10K строк кода, а теперь только с 20K. Но на 100K все равно нужен state management.
Зато мы имеем тривиальное преобразование JSX в JS, а значит и весь продвинутый тулинг (TypeScript, ESLint, Prettier, etc)
Прошу прощения. Конечно же я имел в виду Virtual DOM в Vue 2
Нормальным было бы затягивать в апстрим best practices, опробованные коммъюнити в библиотеках. Как это делают в стандарте языка и Babel-плагинах. А сейчас мы имеем:
Хотите иммутабельного состояния — ну нате вам
useReducer()
. Что, Context API не умеет в селекторы? Ну так оно не для управления стейтом, а для тем всяких там. Механизм подписок не дружит с concurrent mode? Ну извиняйте. Короче, не мешайте нам делать красивые доклады на конференциях, а валите в свой Redux / MobX.И получится KnockoutJS или Vue 1.0. Кстати, в Vue 2.0 они зачем-то же перешли на JSX.
Сейчас, ясное дело, ничем. А вот при выходе следующей версии библиотеки, авторы могут: заменить class компонент на хуки; реализовать таки
sCU()
. И наша карета превратится в тыкву.Да это понятно. По хорошему, TreeView должен иметь какой-нибудь опциональный prop
renterTreeNode
, в который мы могли бы запихнуть хотьobserver(TreeView)
хотьconnect(...)(TreeView)
.Но тогда непонятно, что делать самим авторам UI-фреймворков под реакт:
А вот о стандартном механизме DI должны были подумать авторы самого React. Сейчас есть много реализаций, но все они — пляски с бубном или как минимум неизвестны широкой публике. И тут у UI-фреймворка опять дилемма — вставлять зависимость на что-то маргинальное? Или ваять свою систему конфигурации?
Если мы полностью владеем кодом всех компонентов проекта, то проблем нет. А вот если используем какой-то визуальный фреймворк, то тут уже интереснее. У нас был затык с third-party TreeView, который рекурсивно рендерит сам себя для вложенных элементов дерева. Решений два:
В защиту mobx можно сказать что с Redux, как превратить рекурсивный third-party компонент в connected, тоже непонятно.
А не думали выкинуть moment в пользу какого-нибудь модульного date-fns? Это существенно уменьшит вес бандла. Единственное, чем можно объяснить сейчас использование moment — это legacy. Или библиотеки UI компонентов под реакт, где он прописан в зависимостях.
И как раз поэтому каждый проект на Redux, к которому ты подключился не со старта разработки — это целый комбайн спорных/чьих-то чужих решений. Кто-то обязательно натащит туда модных на данный момент библиотек для упрощения работы с ним. Потому что работать с голым редаксом — боль.
Основная проблема таких проектов — отсутствие коммъюнити, и как следствие, фрагментация.
Есть куча библиотек, построенных вокруг использования Proxy для отслеживания изменений. Например: