Странно, Core i7-4550U 1.50GHz и 61-м хроме на убунте
10 вкладок с треугольником на mol летают (видимо я уже обновленную версию открыл), грузят где-то 10%, а на реакте под 100% все ядра грузят и вычисления стоят на одной цифре, правда анимация наиплавнейшая.
У вас, я так понимаю срабатывает трюк: если вкладка не видна, вычисления засыпают.
Тогда потеряется львиная доля преимуществ и получится шило на мыло.
Что-то потеряется, к сожалению. Мое предположение в том, что из-за конкуренции в вебе и js, вам без огромных вливаний ресурсов, как у гугла в ангулар, не продать огромный кусок чего-то сильно отличающегося.
У всех космические корабли похожи на энтерпрайс, у вас на инопланетную губку из водорослей, где все замкнуто на вас:
1. Свои соглашения по импортам и связянного с ними стилем кодирования
2. Необычная реализация инверсии контроля через контексты
3. Своя экосистема: пакетный менеджер и сборщик зависимостей (mam)
4. Своя библиотека для DOM, http и пр. утиль
5. Своя библиотека работы со стейтом (mol_atom), с удачной, но непривычной идеей в основе
6. Иерархическое наследование на tree, вместо плохо кастомизируемой, но простой и понятной всем композиции на шаблонах, таких как JSX
Это все может быть 100 раз оправданно, цельно и логично и опережать время лет на 5, но оно просто ни на что не похоже. Аналогии не работают, т.к. это новый подход к разработке в целом. Может попробовать продать маленький кусок, встроив в привычную экосистему, как автор mobx?
А где на него посмотреть?
Мне б тоже хотелось знать, может просто их спросить? Я помню как автор mobx много где упоминал свое решение пару лет назад, тогда еще mobservable, например как здесь и у него было пару десятков звезд, а сейчас 11К.
1. Слишком много новых концепций. Например, может лучше начать с mol_jsx, вместо tree, т.к. многие не хотят это постигать целиком
2. Нужны примеры в сравнении с аналогичными на react
3. Статьи на англоязычные ресурсы
4. Посмотреть на опыт авторов mobx, catberry, авторы которых с нуля и быстрее вас получили намного больше звезд
А в реальности, мне кажется, что только много денег, вложенные в маркетинг, могут помочь, у меня то всего 20 звезд на гитхабе, около 100 у вас это еще неплохо =)
Неубедительная аргументация, если честно. Артефакт может зависеть от загрузки процессора, версии файбера и расстановки приоритетов компонентам.
Во-первых, надо уточнить случаи, когда
рендеринг каждого кадра важнее скачков анимации и доказать, что это так.
Во-вторых, «полное отсутствие обновления» — экстраполяция. Лучше уточнять параметры. Т.е. на слабых мобилках, при неправильно расставленных приоритетах может и да, ваш способ лучше, но это пока не делает файбер костылем.
После отправки данных в пропсы MobX никак не сможет повлиять на реконсиляцию.
Смысл в mobx, если отправлять сырые данные в пропсы. Вот то, что в случае mobx и react, в пропсы должны попадать запакованные значения, что б магия работала, скорее это ограничение.
компоненты должны быть декомпозированы очень сильно. Чем меньше кирпичик — тем выше производительность. К чему и тяготеет мол.
Тут хотелось бы понять, какой пример мы обсуждаем: mol_jsx, mol или некий абстрактный на mobx и react без vdom на реальном dom.
Если я правильно вас понял, вы считаете, что все DOM-элементы в компоненте будут пересозданы, если какое-либо его observable-свойство поменялось.
Так реализация прослойки между mobx и DOM должна точечно мутировать DOM-ноду, если надо поменять одно из ее свойств или дочернюю ноду, как это и делает mol_jsx.
Наверное есть случаи, где такой подход будет работать хуже vDOM, но тут надо конкретный пример рассматривать и оценивать насколько это критично.
Для mol, лучше бы vintage объяснил, что будет, если делать все здоровенными компонентами.
вы должны быть уверены, что в вашем проекте нет узких мест, которые зафризят UI. Сюда включается и начальный рендер (от чего мол убежал с мотивацией «так код будет более идиоматичный») и тяжёлые обновления (а от этого мол не смог убежать — фризы на демках появляются регулярно).
Тут не понял. Как vDOM может уберечь от фризов? Что такого было бы в приложении с mobx и нативном DOM, что фризило бы рендеринг?
Подозреваю, что вместо реакта должно быть «ридакс»?
Именно реакта. Посыл был в том, что mobx делает многие вещи ненужными в реакте. Если бы проектировать начали с слоя данных, то дальше многие проблемы решать было бы проще. В Vue, кстати, в основе нечто похожее на mobx.
Почему не с redux, потому что это opinionated-подход, навязывающий определенный архитектурный стиль.
Mobx же претендует на unopinionated: обычные классы, минимум инфраструктурного кода. Нравится функциональный стиль — пожалуйста, mobx хорошая платформа для построения mst-подобных решений.
Можно было бы оставить только pure-компоненты, зоопарк способов менять состояние свелся бы к единообразному подходу на основе mobx и его надстройках. Все были бы счастливы.
shouldComponentUpdate и не нужен для того случая, который вы описали
Я показал, что в mobx, observer его реализует одинаково для всех оборачиваемых pure-компонент.
Не знаю, в курсе ли вы, но в recompose есть и более вкусные вещи: onlyUpdateForKeys() и onlyUpdateForPropTypes(). ShouldComponentUpdate нужен в очень редких случаях.
Изначальная идея — автоматически ускорить рендеринг и вдруг, для некоторых случаев, предлагается это делать вручную. Вопрос, где слабое звено в фреймворке, из-за которого возникла такая потребность? В vue как-то без shouldComponentUpdate обходятся.
Основной посыл был в том, что с mobx меньше инфраструктурного кода. Конечно со всякими redux-saga тоже меньше, но тут смысл в unopinionated, появляется выбор: можно напрямую в mobx состояние актуализировать, а можно и mst и saga-подобные решения накручивать.
P.S. пример с моловским треугольником стал тормозить уже после 5-й открытой вкладки, в то время как демонстрация файбера
Я к тому, что mol по сравнению с реактом без файбера выдавал лучшую производительность, сравнимую с реактом с файбером на одной вкладке, да.
Было б прикольно, если б vintage запилил свой файбер, но он наверное опять скажет «не нужно».
Всегда ли плавность важнее гарантированного отклика? Да и почему, собственно, понадобилось добавлять какой-то Fiber для видимости ускорения? Для меня убедительно выглядит пример треугольника на mol, который обеспечивает плавность без технологий, вроде Fiber. И для этого надо раз в 5 меньше кода и это все написал один человек, а не команда из гиганта FB.
Используя mobx, мы большую часть оптимизаций перекладываем с vDOM на mobx. Если эту идею довести до логического конца, то зачем тогда vDOM?.. А если не нужен vDOM, то некоторая часть реакта становится бесполезным оверхедом. Автор mol как раз это показал, написав небольшой наколеночный jsx-процессор на нативном DOM, сопоставимый с vDOM по производительности.
Рекомендации будут в случае любого фреймворка. Тут вопрос, не является ли часть из них следствием неудачных решений, принятых где-то раньше? Что было бы с рекомендациями, если бы перед реактом сделали mobx?
Вместо redux мы бы сразу получили mobx-state-tree с его децентрализованным стейтом и другими фичами.
shouldComponentUpdate стал бы не нужен, т.к. mobx решает эту проблему автоматически, не привнося сложности в прикладной код. Observer просто делает shallowEqual при любом обновлении данных.
componentWillMount стал бы не нужен, т.к. актуализацию данных можно делать в роутере или в самих данных (через fromPromise и lazyObservable из mobx-utils). О чем и говорит Michel Weststrate в статье How to decouple state and UI
У файбера есть и недостатки: плавность, ценой пропуска кадров. Это проявляется, если проц слабый или загружен. Откройте 10 демок на файбере и в одной повозите мышкой над цифрами. Проблему производительности он скорее маскирует, чем решает. Может быть когда-нибудь в многопоточной среде и будет решать, но не в однопоточной.
Про скорость repaint в DOM, мне кажется, Дмитрий имел в виду, что если на странице много элементов, в том числе и за пределами видимой области, то это будет тормозить. И vDOM тут никак не поможет.
vDOM не бесплатный, поэтому есть shouldComponentUpdate, отчасти setState, а также много попыток написать быстрее, чем в react (тот же inferno или ivi).
vDOM — это оптимизация внизу, перед выводом в браузер. А mobx-подобные решения — это оптимизация наверху, сразу после изменения данных. Что может быть гораздо быстрее любого vDOM, т.к. глубина вычислений будет меньше в среднем случае.
Многие фреймворки добиваются высокой производительности, используя точечные обновления, вместо vDOM (тот же angular4, отчасти vue). Интересно наблюдать, как развивается этот альтернативный подход, в том числе и в mol.
На мой взгляд, изолированные бенчмарки алгоритмов тоже нужны. Тут дело в нестандартных условиях, которые нельзя предугадать. Например, что такое видимая область, это сколько?
А если стена из мониторов, с очень большим суммарным разрешением?
А если это приложение на каком-нибудь electron или phantomjs, задача которого срендерить много-много страниц pdf? Хотя тут наверное SSR поможет, а он у вас без такой оптимизации.
Как будет масштабироваться mol в сравнении с конкурентами на нестандартные решения? Хоть это сейчас и редкие случаи, но интересный был бы задел на будущее.
Вы не думали сделать эту фичу отключаемой? Кому очень нужен Ctrl-F, для бенчмарков и для споров.
Отстали бы те, кто использует аргумент ленивости против mol.
Т.к. я использовал атомы (основу mol) вместе с реактом и делал бенчмарки, то думаю, что mol все-равно бы в среднем чуть обгонял популярные фреймворки за счет легковесности.
Даже если скорость будет такая же, она достигается гораздо более простыми алгоритмами, в 5 раз меньшим объемом кода, кастомизируемостью, которых нет у других, а это уже аргумент.
Еще раз: JavaScript на клиенте не лагает. Лагает медленный DOM (точнее манипуляции с DOM).
Из этой фразы можно подумать, что проблемы только в DOM, лагает он и все тут. А как только его ускорят, все фреймворки залетают.
DOM медленный, но есть тот же mol, который работает с реальным DOM напрямую и судя по todomvc бенчмаркам (раз, два), гораздо быстрее многих фреймворков вроде реакта и ангулара. Дело в том, как изменения в стейте отражаются на DOM, в цене минимизации обновлений, а это уже архитектурные проблемы на стороне фреймворка.
Ускорив DOM, можно только замаскировать эти проблемы, задвинуть их на второй план.
Удалить и заменить деталь внутри можно, а вот что бы добавить, надо делать композицию заново (правда, в отличие от чистого реакта, в rdi это можно проделать не для основного компонента, а для его внутренней детали). У вас, в tree, такая перекомпозиция происходит дешево в sub.
Пока не представляю как в jsx это также дешево сделать. Можно выделять детали на первом уровне в компоненты и делая компонент, который выстроит последовательность из этих деталей.
Это первая моя статья, буду пытаться улучшать подачу в следующих. Хотя бы пример с HelloWorld понятен? Могу для сравнения еще насоздавать, только задачу сформулируйте.
Суть такая примерно:
Развить идею контекста в реакте
Привнести SOLID на фронтенд наименьшей ценой
Дать возможность писать код, максимально свободный от каркаса, убрав vendor lock-in
Использовать типы и DI для связывания частей, вместо решений вроде connect, redux-thunk, reselect и т.д.
Сложность уменьшается за счет простых базовых концепций, которые позволяют писать меньше кода, оставляя его понятным (хочется верить).
В TypeScript строковые литералы не считаются нетипобезопасными, так как есть строковые литеральные типы.
В ts да, такая штука будет типобезопасной:
import { InjectionToken } from '@angular/core';
interface AppConfig {
title: string;
}
export let APP_CONFIG = new InjectionToken<AppConfig>('app.config');
//...
constructor(@Inject(APP_CONFIG) config: AppConfig) {
this.title = config.title;
}
Однако такой подход все-равно требует расстановки декораторов, это не нативно из-за InjectionToken. Второй момент — заранее надо продумывать точки расширения, расставляя эти декораторы.
Redux предназначен не для хранения состояния компонентов.
Redux лучше впишется туда, где используются транзакции, timetravel, распределенная работа с данными. Если эти навороты не нужны, то есть более простые способы менять состояние, поэтому многие перешли на mobx.
Задачу связывания redux решает не очень хорошо: redux-thunk, reselect, connect — низкоуровневые инструменты. Если основа DI, можно все связывание построить на типах, не привнося фреймворко-специфичных конструкций.
Сравните примеры Hello world, кода сильно меньше при сравнимом уровне абстракции:
Через алиасинг HelloWorldStore также можно разделить компонент и реакцию на событие.
Без lifecycle очень плохо.
Тут бы глянуть конкретные примеры. Есть мнение, что если правильно построить работу с состоянием, большинство lifecycle не нужными становятся. Я об этом хотел написать в следующей статье.
Например, hello world с загрузкой, обработкой ошибок и крутилкой:
Как минимум, загрузку и ошибки в Angular придется обрабатывать вручную. Красивый биндинг данных работает внутри компонента, если нужна декомпозиция Hello (например расшарить между двумя компонентами, ничего не знающими друг о друге), то уже надо тащить стримы, подписываться/отписываться.
Что бы использовать сервис, надо объявить его в provide и помечать Injectable. А typescript работает внутри Angular template, как в JSX?
Объем кода тоже можно отметить, Angular4 core+common+forms = 13459 SLOC, rdi+lom_atom+preact, на котором мои примеры, около 2048 SLOC.
Тут конечно простые примеры рассмотрены, если подкинете сложные, я их запилю на rdi.
DI мне интересно развивать, как фундамент для связывания частей приложения, без привязки к каким либо фреймворкам. Еще была важна ненавязчивость, в коде нету import some from 'reactive-di' (кроме cloneComponent), только чистые функции + метаданные.
Redux немного другие задачи решает, навязывает определенный стиль программирования (экшены, редьюсеры и т.д.) не избавляет от HOC и этого connect в коде. Если нужны транзакции, версионирование и т.д., то решения вроде redux можно накрутить и поверх DI. Например, mobx-state-tree — это как раз пример того, как выглядел бы redux поверх mobx.
10 вкладок с треугольником на mol летают (видимо я уже обновленную версию открыл), грузят где-то 10%, а на реакте под 100% все ядра грузят и вычисления стоят на одной цифре, правда анимация наиплавнейшая.
У вас, я так понимаю срабатывает трюк: если вкладка не видна, вычисления засыпают.
У всех космические корабли похожи на энтерпрайс, у вас на инопланетную губку из водорослей, где все замкнуто на вас:
1. Свои соглашения по импортам и связянного с ними стилем кодирования
2. Необычная реализация инверсии контроля через контексты
3. Своя экосистема: пакетный менеджер и сборщик зависимостей (mam)
4. Своя библиотека для DOM, http и пр. утиль
5. Своя библиотека работы со стейтом (mol_atom), с удачной, но непривычной идеей в основе
6. Иерархическое наследование на tree, вместо плохо кастомизируемой, но простой и понятной всем композиции на шаблонах, таких как JSX
Это все может быть 100 раз оправданно, цельно и логично и опережать время лет на 5, но оно просто ни на что не похоже. Аналогии не работают, т.к. это новый подход к разработке в целом. Может попробовать продать маленький кусок, встроив в привычную экосистему, как автор mobx?
Мне б тоже хотелось знать, может просто их спросить? Я помню как автор mobx много где упоминал свое решение пару лет назад, тогда еще mobservable, например как здесь и у него было пару десятков звезд, а сейчас 11К.
2. Нужны примеры в сравнении с аналогичными на react
3. Статьи на англоязычные ресурсы
4. Посмотреть на опыт авторов mobx, catberry, авторы которых с нуля и быстрее вас получили намного больше звезд
А в реальности, мне кажется, что только много денег, вложенные в маркетинг, могут помочь, у меня то всего 20 звезд на гитхабе, около 100 у вас это еще неплохо =)
Во-первых, надо уточнить случаи, когда
рендеринг каждого кадра важнее скачков анимации и доказать, что это так.
Во-вторых, «полное отсутствие обновления» — экстраполяция. Лучше уточнять параметры. Т.е. на слабых мобилках, при неправильно расставленных приоритетах может и да, ваш способ лучше, но это пока не делает файбер костылем.
Тут хотелось бы понять, какой пример мы обсуждаем: mol_jsx, mol или некий абстрактный на mobx и react без vdom на реальном dom.
Если я правильно вас понял, вы считаете, что все DOM-элементы в компоненте будут пересозданы, если какое-либо его observable-свойство поменялось.
Так реализация прослойки между mobx и DOM должна точечно мутировать DOM-ноду, если надо поменять одно из ее свойств или дочернюю ноду, как это и делает mol_jsx.
Наверное есть случаи, где такой подход будет работать хуже vDOM, но тут надо конкретный пример рассматривать и оценивать насколько это критично.
Для mol, лучше бы vintage объяснил, что будет, если делать все здоровенными компонентами.
Тут не понял. Как vDOM может уберечь от фризов? Что такого было бы в приложении с mobx и нативном DOM, что фризило бы рендеринг?
Именно реакта. Посыл был в том, что mobx делает многие вещи ненужными в реакте. Если бы проектировать начали с слоя данных, то дальше многие проблемы решать было бы проще. В Vue, кстати, в основе нечто похожее на mobx.
Почему не с redux, потому что это opinionated-подход, навязывающий определенный архитектурный стиль.
Mobx же претендует на unopinionated: обычные классы, минимум инфраструктурного кода. Нравится функциональный стиль — пожалуйста, mobx хорошая платформа для построения mst-подобных решений.
Можно было бы оставить только pure-компоненты, зоопарк способов менять состояние свелся бы к единообразному подходу на основе mobx и его надстройках. Все были бы счастливы.
Я показал, что в mobx, observer его реализует одинаково для всех оборачиваемых pure-компонент.
Изначальная идея — автоматически ускорить рендеринг и вдруг, для некоторых случаев, предлагается это делать вручную. Вопрос, где слабое звено в фреймворке, из-за которого возникла такая потребность? В vue как-то без shouldComponentUpdate обходятся.
Основной посыл был в том, что с mobx меньше инфраструктурного кода. Конечно со всякими redux-saga тоже меньше, но тут смысл в unopinionated, появляется выбор: можно напрямую в mobx состояние актуализировать, а можно и mst и saga-подобные решения накручивать.
Я к тому, что mol по сравнению с реактом без файбера выдавал лучшую производительность, сравнимую с реактом с файбером на одной вкладке, да.
Было б прикольно, если б vintage запилил свой файбер, но он наверное опять скажет «не нужно».
Используя mobx, мы большую часть оптимизаций перекладываем с vDOM на mobx. Если эту идею довести до логического конца, то зачем тогда vDOM?.. А если не нужен vDOM, то некоторая часть реакта становится бесполезным оверхедом. Автор mol как раз это показал, написав небольшой наколеночный jsx-процессор на нативном DOM, сопоставимый с vDOM по производительности.
Рекомендации будут в случае любого фреймворка. Тут вопрос, не является ли часть из них следствием неудачных решений, принятых где-то раньше? Что было бы с рекомендациями, если бы перед реактом сделали mobx?
Вместо redux мы бы сразу получили mobx-state-tree с его децентрализованным стейтом и другими фичами.
shouldComponentUpdate стал бы не нужен, т.к. mobx решает эту проблему автоматически, не привнося сложности в прикладной код. Observer просто делает shallowEqual при любом обновлении данных.
componentWillMount стал бы не нужен, т.к. актуализацию данных можно делать в роутере или в самих данных (через fromPromise и lazyObservable из mobx-utils). О чем и говорит Michel Weststrate в статье How to decouple state and UI
Про скорость repaint в DOM, мне кажется, Дмитрий имел в виду, что если на странице много элементов, в том числе и за пределами видимой области, то это будет тормозить. И vDOM тут никак не поможет.
vDOM не бесплатный, поэтому есть shouldComponentUpdate, отчасти setState, а также много попыток написать быстрее, чем в react (тот же inferno или ivi).
vDOM — это оптимизация внизу, перед выводом в браузер. А mobx-подобные решения — это оптимизация наверху, сразу после изменения данных. Что может быть гораздо быстрее любого vDOM, т.к. глубина вычислений будет меньше в среднем случае.
Многие фреймворки добиваются высокой производительности, используя точечные обновления, вместо vDOM (тот же angular4, отчасти vue). Интересно наблюдать, как развивается этот альтернативный подход, в том числе и в mol.
А если стена из мониторов, с очень большим суммарным разрешением?
А если это приложение на каком-нибудь electron или phantomjs, задача которого срендерить много-много страниц pdf? Хотя тут наверное SSR поможет, а он у вас без такой оптимизации.
Как будет масштабироваться mol в сравнении с конкурентами на нестандартные решения? Хоть это сейчас и редкие случаи, но интересный был бы задел на будущее.
Отстали бы те, кто использует аргумент ленивости против mol.
Т.к. я использовал атомы (основу mol) вместе с реактом и делал бенчмарки, то думаю, что mol все-равно бы в среднем чуть обгонял популярные фреймворки за счет легковесности.
Даже если скорость будет такая же, она достигается гораздо более простыми алгоритмами, в 5 раз меньшим объемом кода, кастомизируемостью, которых нет у других, а это уже аргумент.
Вопрос в другом, почему mol на видимой области медленнее vdom, чему там тормозить, если обновления точечные и все-равно все упирается в DOM?
Из этой фразы можно подумать, что проблемы только в DOM, лагает он и все тут. А как только его ускорят, все фреймворки залетают.
DOM медленный, но есть тот же mol, который работает с реальным DOM напрямую и судя по todomvc бенчмаркам (раз, два), гораздо быстрее многих фреймворков вроде реакта и ангулара. Дело в том, как изменения в стейте отражаются на DOM, в цене минимизации обновлений, а это уже архитектурные проблемы на стороне фреймворка.
Ускорив DOM, можно только замаскировать эти проблемы, задвинуть их на второй план.
Пока не представляю как в jsx это также дешево сделать. Можно выделять детали на первом уровне в компоненты и делая компонент, который выстроит последовательность из этих деталей.
Суть такая примерно:
Сложность уменьшается за счет простых базовых концепций, которые позволяют писать меньше кода, оставляя его понятным (хочется верить).
Однако такой подход все-равно требует расстановки декораторов, это не нативно из-за InjectionToken. Второй момент — заранее надо продумывать точки расширения, расставляя эти декораторы.
Redux лучше впишется туда, где используются транзакции, timetravel, распределенная работа с данными. Если эти навороты не нужны, то есть более простые способы менять состояние, поэтому многие перешли на mobx.
Задачу связывания redux решает не очень хорошо: redux-thunk, reselect, connect — низкоуровневые инструменты. Если основа DI, можно все связывание построить на типах, не привнося фреймворко-специфичных конструкций.
Сравните примеры Hello world, кода сильно меньше при сравнимом уровне абстракции:
Через алиасинг HelloWorldStore также можно разделить компонент и реакцию на событие.
Тут бы глянуть конкретные примеры. Есть мнение, что если правильно построить работу с состоянием, большинство lifecycle не нужными становятся. Я об этом хотел написать в следующей статье.
Например, hello world с загрузкой, обработкой ошибок и крутилкой:
Как минимум, загрузку и ошибки в Angular придется обрабатывать вручную. Красивый биндинг данных работает внутри компонента, если нужна декомпозиция Hello (например расшарить между двумя компонентами, ничего не знающими друг о друге), то уже надо тащить стримы, подписываться/отписываться.
Что бы использовать сервис, надо объявить его в provide и помечать Injectable. А typescript работает внутри Angular template, как в JSX?
Объем кода тоже можно отметить, Angular4 core+common+forms = 13459 SLOC, rdi+lom_atom+preact, на котором мои примеры, около 2048 SLOC.
Тут конечно простые примеры рассмотрены, если подкинете сложные, я их запилю на rdi.
Redux немного другие задачи решает, навязывает определенный стиль программирования (экшены, редьюсеры и т.д.) не избавляет от HOC и этого connect в коде. Если нужны транзакции, версионирование и т.д., то решения вроде redux можно накрутить и поверх DI. Например, mobx-state-tree — это как раз пример того, как выглядел бы redux поверх mobx.