Сравнение фреймворков
Если вы читаете эту страницу, вероятно, вы использовали другие фреймворки для создания приложений и хотите узнать, поможет ли Mithril.js более эффективно решать ваши задачи.
Почему не [вставить сюда любимый фреймворк]?
Реальность такова, что большинство современных фреймворков достаточно быстры, хорошо подходят для создания сложных приложений и имеют поддержку, если вы знаете, как их эффективно использовать. Существуют примеры очень сложных приложений, использующих практически каждый популярный фреймворк: Udemy использует Angular, AirBnB использует React, Gitlab использует Vue, Guild Wars 2 использует Mithril.js (да, внутри игры!). Очевидно, все эти фреймворки пригодны для использования в production.
Как правило, если ваша команда уже в значительной степени инвестировала в другой фреймворк/библиотеку/стек, разумнее продолжать его использовать, если только ваша команда не придет к выводу, что есть очень веская причина для оправдания дорогостоящей переработки.
Однако, если вы начинаете что-то новое, подумайте о том, чтобы попробовать Mithril.js, хотя бы для того, чтобы оценить преимущества, которые пользователи Mithril.js получают от кода размером менее 10 КБ (в сжатом виде). Mithril.js используется многими известными компаниями (например, Vimeo, Nike, Fitbit) и применяется в крупных платформах с открытым исходным кодом (например, Lichess, Flarum).
Почему стоит использовать Mithril.js?
В одном предложении: потому что Mithril.js прагматичен. Этот 10-минутный гид - хороший пример: именно столько времени требуется, чтобы изучить компоненты, XHR и маршрутизацию - и это именно тот объем знаний, который необходим для создания полезных приложений.
Mithril.js - это инструмент для эффективного выполнения значимой работы. Загрузка файлов? Документация покажет вам, как это сделать. Аутентификация? Тоже есть документация. Выходные анимации? И это тоже есть. Никаких дополнительных библиотек, никакой магии.
Сравнения
React
React - это библиотека для создания пользовательских интерфейсов, поддерживаемая Facebook.
React и Mithril.js имеют много общего. Если вы уже изучили React, вы уже знаете почти все, что вам нужно для создания приложений с помощью Mithril.
- Оба используют виртуальный DOM, методы жизненного цикла и согласование на основе ключей.
- Оба организуют представления с помощью компонентов.
- Оба используют JavaScript в качестве механизма управления потоком внутри представлений.
Наиболее очевидное различие между React и Mithril.js заключается в их размере. React - это библиотека для создания пользовательских интерфейсов, поэтому типичное приложение на основе React полагается на сторонние библиотеки для маршрутизации, XHR и управления состоянием. Использование подхода, ориентированного на библиотеки, позволяет разработчикам настраивать свой стек в соответствии со своими потребностями. Менее приятный способ выразиться - архитектуры на основе React могут сильно различаться от проекта к проекту и часто превышают размер в 1 МБ.
Mithril.js имеет встроенные модули для общих потребностей, таких как маршрутизация и XHR, а руководство демонстрирует идиоматическое использование. Этот подход лучше подходит командам, ценящим последовательность и простоту адаптации.
Производительность
И React, и Mithril.js уделяют большое внимание производительности рендеринга, но подходят к этому по-разному. В прошлом у React было две реализации рендеринга DOM (одна с использованием DOM API, а другая с использованием innerHTML
). Его предстоящая архитектура fiber вводит планирование и приоритизацию единиц работы. React также имеет сложную систему сборки, которая отключает различные проверки и сообщения об ошибках для производственных развертываний, а также различные оптимизации для конкретных браузеров. Кроме того, существует также несколько библиотек, ориентированных на производительность, которые используют хук shouldComponentUpdate
React и свойства быстрой проверки равенства объектов библиотек неизменяемых структур данных для сокращения времени согласования виртуального DOM. В общем, подход React к производительности заключается в разработке относительно сложных решений.
Mithril.js придерживается принципа "меньше - значит больше". Он имеет значительно меньшую, агрессивно оптимизированную кодовую базу. Обоснование состоит в том, что небольшую кодовую базу легче проверять и оптимизировать, что приводит к меньшему объему выполняемого кода.
Вот сравнение времени загрузки библиотеки, то есть времени, необходимого для разбора и выполнения кода JavaScript для каждого фреймворка, путем добавления вызова console.time()
в первой строке и вызова console.timeEnd()
в последней строке скрипта, который состоит исключительно из кода фреймворка. Для вашего удобства чтения вот лучшие из 20 результатов с кодом ведения журнала, вручную добавленным в связанные скрипты, запущенные из файловой системы, в Chrome на скромном настольном ПК 2010 года:
React | Mithril.js |
---|---|
55.8 ms | 4.5 ms |
Время загрузки библиотеки имеет большое значение в приложениях, которые не остаются открытыми на длительное время (например, все, что связано с мобильными устройствами) и не могут быть улучшены с помощью кэширования или других методов оптимизации.
Поскольку это микро-бенчмарк, вам рекомендуется повторить эти тесты самостоятельно, поскольку оборудование может сильно повлиять на цифры. Обратите внимание, что фреймворки-сборщики, такие как Webpack, могут перемещать зависимости до вызовов таймера, чтобы эмулировать статическое разрешение модулей, поэтому вам следует либо скопировать код из скомпилированных файлов CDN, либо открыть выходной файл из библиотеки-сборщика и вручную добавить вызовы таймера высокого разрешения console.time
и console.timeEnd
в связанный скрипт. Избегайте использования new Date
и performance.now
, так как эти механизмы не являются статистически точными.
Для вашего удобства чтения вот версия этого бенчмарка, адаптированная для использования CDN в Интернете: бенчмарк для React находится здесь, а бенчмарк для Mithril.js находится здесь. Обратите внимание, что мы тестируем весь Mithril.js, а не только модуль рендеринга (который был бы эквивалентен по объему React). Также обратите внимание, что эта настройка, управляемая CDN, влечет за собой некоторые накладные расходы из-за получения ресурсов из дискового кэша (~2 мс на ресурс). По этим причинам цифры здесь не совсем точны, но их должно быть достаточно, чтобы заметить, что скорость инициализации Mithril.js заметно лучше, чем у React.
Вот немного более значимый бенчмарк: измерение времени скриптов для создания 10 000 div (и 10 000 текстовых узлов). Опять же, вот код бенчмарка для React и Mithril.js. Их лучшие результаты показаны ниже:
React | Mithril.js |
---|---|
99.7 ms | 42.8 ms |
Эти цифры показывают, что Mithril.js не только инициализируется значительно быстрее, но и может обрабатывать более 20 000 узлов виртуального DOM до того, как React будет готов к использованию.
Производительность обновления
Производительность обновления может быть даже более важной, чем производительность первого рендеринга, поскольку обновления могут происходить много раз во время работы одностраничного приложения.
Полезным инструментом для тестирования производительности обновления является инструмент, разработанный командой Ember под названием DbMonster. Он обновляет таблицу так быстро, как только может, и измеряет количество кадров в секунду (FPS) и время JavaScript (мин, макс и среднее). Количество FPS может быть трудно оценить, поскольку оно также включает время перерисовки браузера и задержку ограничения setTimeout
, поэтому наиболее значимой цифрой для просмотра является среднее время рендеринга. Вы можете сравнить реализацию React и реализацию Mithril.js. Пример результатов показан ниже:
React | Mithril.js |
---|---|
12.1 ms | 6.4 ms |
Производительность разработки
Еще одна вещь, которую следует иметь в виду, это то, что, поскольку React добавляет дополнительные проверки и полезные сообщения об ошибках в режиме разработки, он работает медленнее в разработке, чем производственная версия, используемая для приведенных выше тестов. Для иллюстрации, вот бенчмарк на 10 000 узлов, приведенный выше, с использованием версии React для разработки.
Заменяемые модули
Существуют несколько проектов которые заявляют о паритете API с React (некоторые через библиотеки уровня совместимости), но они не полностью совместимы (например, поддержка PropType обычно заглушена, синтетические события иногда не поддерживаются, а некоторые API имеют другую семантику). Обратите внимание, что эти библиотеки обычно также включают свои собственные функции, которые не являются частью официального API React, что может стать проблематичным в будущем, если кто-то решит вернуться к React Fiber.
Заявления о небольшом размере загрузки (по сравнению с React) точны, но большинство из этих библиотек немного больше, чем модуль рендеринга Mithril.js. Preact является единственным исключением.
Будьте осторожны с агрессивными заявлениями о производительности, поскольку тесты, используемые некоторыми из этих проектов, как известно, устарели и содержат недостатки (в том смысле, что их можно - и используют - эксплуатировать). Борис Каул (автор некоторых тестов) подробно написал о том, как проводятся тесты. Еще одна вещь, которую следует иметь в виду, это то, что некоторые тесты агрессивно используют расширенные функции оптимизации и, таким образом, демонстрируют потенциальную производительность, то есть производительность, которая возможна при некоторых оговорках, но реалистично маловероятна, если вы активно не тратите время на просмотр всей своей кодовой базы, выявляя кандидатов на оптимизацию и оценивая риски регрессии, вызванные оговорками оптимизации.
Чтобы продемонстрировать типичную производительность, тесты на этой странице сравнения реализованы простым, идиоматическим способом (то есть так, как вы обычно пишете 99% кода). Мы не использовали никаких трюков или продвинутых оптимизаций, чтобы искусственно улучшить показатели какого-либо фреймворка. Вам рекомендуется предложить свои изменения (pull request), если вы считаете, что какую-либо реализацию DbMonster можно написать более идиоматично.
Сложность
И React, и Mithril.js имеют относительно небольшие поверхности API по сравнению с другими фреймворками, что помогает облегчить кривую обучения. Однако, в то время как идиоматический Mithril.js может быть написан без потери читабельности с использованием простого ES5 и без каких-либо других зависимостей, идиоматический React в значительной степени полагается на сложные инструменты (например, Babel, плагин JSX и т. д.), и этот уровень сложности часто распространяется на популярные части его экосистемы, будь то в форме синтаксических расширений (например, нестандартный синтаксис распространения объектов в Redux), архитектур (например, использующих библиотеки неизменяемых данных) или наворотов (например, горячая перезагрузка модулей).
Хотя сложные цепочки инструментов также возможны с Mithril.js и другими фреймворками, настоятельно рекомендуется следовать принципам KISS и YAGNI при использовании Mithril.
Кривая обучения
И React, и Mithril.js имеют относительно небольшие кривые обучения. Кривая обучения React в основном включает понимание компонентов и их жизненного цикла. Кривая обучения для компонентов Mithril.js почти идентична. Очевидно, что в Mithril.js больше API для изучения, поскольку Mithril.js также включает маршрутизацию и XHR, но кривая обучения будет довольно похожа на изучение React, React Router и библиотеки XHR, такой как superagent или axios.
Идиоматический React требует знания JSX и его предостережений, и поэтому существует также небольшая кривая обучения, связанная с Babel.
Документация
Документация React ясна и хорошо написана и включает хорошую справочную информацию по API, учебные пособия для начала работы, а также страницы, охватывающие различные расширенные концепции. К сожалению, поскольку React ограничивается только библиотекой для создания пользовательских интерфейсов, его документация не рассматривает, как использовать React идиоматично в контексте реального приложения. В результате существует множество популярных библиотек управления состоянием, и поэтому архитектуры, использующие React, могут сильно отличаться от компании к компании (или даже между проектами).
Документация Mithril.js также включает вводные учебные пособия, страницы о расширенных концепциях и обширный раздел справочника API, который включает информацию о типах ввода/вывода, примеры для различных распространенных случаев использования и советы против неправильного использования и анти-паттернов. Он также включает шпаргалку для быстрого ознакомления.
Документация Mithril.js также демонстрирует простые, близкие к низкому уровню решения для распространенных случаев использования в реальных приложениях, где уместно информировать разработчика о том, что веб-стандарты теперь могут быть наравне с более крупными установленными библиотеками.
Angular
Angular - это фреймворк веб-приложений, поддерживаемый Google.
Angular и Mithril.js довольно разные, но у них есть несколько общих черт:
- Оба поддерживают компонентизацию.
- Оба имеют набор инструментов для различных аспектов веб-приложений (например, маршрутизация, XHR).
Наиболее очевидное различие между Angular и Mithril.js заключается в их сложности. Это можно увидеть проще всего в том, как реализованы представления. Представления Mithril.js - это простой JavaScript, а управление потоком осуществляется с помощью встроенных механизмов JavaScript, таких как тернарные операторы или Array.prototype.map
. Для этого Angular включает парсер и компилятор, написанные на JavaScript. Если это не кажется достаточно сложным, на самом деле есть два режима компиляции (режим по умолчанию, который динамически генерирует функции JavaScript для повышения производительности, и более медленный режим для работы с ограничениями политики безопасности контента).
Производительность
Angular добился большого прогресса в плане производительности за эти годы. Angular 1 использовал механизм, известный как dirty checking (грязная проверка), который, как правило, замедлялся из-за необходимости постоянно сравнивать большие структуры $scope
. Angular 2 использует механизм обнаружения изменений шаблона, который намного более производителен. Однако, даже несмотря на улучшения Angular, Mithril.js часто работает быстрее, чем Angular, из-за простоты аудита, которую обеспечивает небольшой размер кодовой базы Mithril.js.
Сложно провести сравнение времени загрузки между Angular и Mithril.js по нескольким причинам. Первая заключается в том, что Angular 1 и 2 на самом деле являются совершенно разными кодовыми базами, и обе версии официально поддерживаются и поддерживаются (и подавляющее большинство кодовых баз Angular в настоящее время все еще используют версию 1). Вторая причина заключается в том, что и Angular, и Mithril.js являются модульными. В обоих случаях можно удалить значительную часть фреймворка, которая не используется в данном приложении.
При этом самый маленький известный пакет Angular 2 - это 29 КБ hello world, сжатый с помощью алгоритма Brotli (35 КБ при использовании стандартного gzip), и с удалением большей части полезных функций Angular. Для сравнения, Mithril.js hello world - включая все ядро Mithril.js с батареями и всем остальным - будет около 10 КБ в сжатом виде.
Кроме того, помните, что такие фреймворки, как Angular и Mithril.js, предназначены для нетривиальных приложений, поэтому приложению, которому удалось использовать всю поверхность API Angular, потребуется загрузить несколько сотен КБ кода фреймворка, а не просто 29 КБ.
Производительность обновления
Полезным инструментом для тестирования производительности обновления является инструмент, разработанный командой Ember под названием DbMonster. Он обновляет таблицу так быстро, как только может, и измеряет количество кадров в секунду (FPS) и время JavaScript (мин, макс и среднее). Количество FPS может быть трудно оценить, поскольку оно также включает время перерисовки браузера и задержку ограничения setTimeout
, поэтому наиболее значимой цифрой для просмотра является среднее время рендеринга. Вы можете сравнить реализацию Angular и реализацию Mithril.js. Обе реализации наивны (то есть без оптимизаций). Пример результатов показан ниже:
Angular | Mithril.js |
---|---|
11.5 ms | 6.4 ms |
Сложность
Angular превосходит Mithril.js по количеству предлагаемых инструментов (в форме различных директив и сервисов), но он также гораздо сложнее. Сравните поверхность API Angular с API Mithril.js. Вы можете составить собственное суждение о том, какой API является более самоописывающим и более релевантным для ваших потребностей.
Angular 2 имеет гораздо больше концепций для понимания: на языковом уровне Typescript является рекомендуемым языком, и вдобавок к этому существует также специфический для Angular синтаксис шаблонов, такой как привязки, каналы, "оператор безопасной навигации". Вам также необходимо узнать об архитектурных концепциях, таких как модули, компоненты, сервисы, директивы и т. д., и о том, где уместно использовать что.
Кривая обучения
Если мы сравним яблоки с яблоками, Angular 2 и Mithril.js имеют схожие кривые обучения: в обоих компоненты являются центральным аспектом архитектуры, и оба имеют разумные инструменты маршрутизации и XHR.
При этом Angular имеет гораздо больше концепций для изучения, чем Mithril. Он предлагает специфические для Angular API для многих вещей, которые часто можно легко реализовать самостоятельно (например, плюрализация, по сути, является оператором switch, а проверка обязательного поля - это просто проверка на равенство и т. д.). Шаблоны Angular также имеют несколько уровней абстракций для эмуляции того, что JavaScript делает изначально в Mithril.js - ng-if
/ngIf
Angular - это директива, которая использует собственный парсер и компилятор для оценки строки выражения и эмуляции лексической области видимости... и так далее. Mithril.js, как правило, гораздо более прозрачен и, следовательно, его легче понять.
Документация
Документация Angular 2 предоставляет обширный вводный учебник и еще один учебник, который реализует приложение. Он также имеет различные руководства по расширенным концепциям, шпаргалку и руководство по стилю. К сожалению, на данный момент справочник API недостаточно полная. Некоторые API либо не документированы, либо не предоставляют контекста для того, для чего может использоваться API.
Документация Mithril.js также включает вводные учебные пособия, страницы о расширенных концепциях и обширный раздел справочника API, который включает информацию о типах ввода/вывода, примеры для различных распространенных случаев использования и советы против неправильного использования и анти-паттернов. Он также включает шпаргалку для быстрого ознакомления.
Документация Mithril.js также демонстрирует простые, близкие к низкому уровню решения для распространенных случаев использования в реальных приложениях, где уместно информировать разработчика о том, что веб-стандарты теперь могут быть наравне с более крупными установленными библиотеками.
Vue
Vue - это библиотека для создания пользовательских интерфейсов, похожая на Angular.
Vue и Mithril.js имеют много различий, но у них также есть некоторые общие черты:
- Оба используют виртуальный DOM и методы жизненного цикла.
- Оба организуют представления с помощью компонентов.
Vue 2 использует форк Snabbdom в качестве своей системы виртуального DOM. Кроме того, Vue также предоставляет инструменты для маршрутизации и управления состоянием в качестве отдельных модулей. Vue очень похож на Angular и предоставляет аналогичную систему директив, шаблоны на основе HTML и директивы логического потока. Он отличается от Angular тем, что реализует систему реактивности monkeypatching, которая перезаписывает собственные методы в дереве данных компонента (в то время как Angular 1 использует dirty checking (грязную проверку) и циклы digest/apply для достижения аналогичных результатов). Подобно Angular 2, Vue компилирует шаблоны HTML в функции, но скомпилированные функции больше похожи на представления Mithril.js или React, чем на скомпилированные функции рендеринга Angular.
Vue значительно меньше, чем Angular, при сравнении яблок с яблоками, но не так мал, как Mithril.js (ядро Vue составляет около 23 КБ в сжатом виде, тогда как эквивалентный модуль рендеринга в Mithril.js составляет около 4 КБ в сжатом виде). Оба имеют схожие характеристики производительности, но тесты обычно показывают, что Mithril.js немного быстрее.
Производительность
Вот сравнение времени загрузки библиотеки, то есть времени, необходимого для разбора и выполнения кода JavaScript для каждого фреймворка, путем добавления вызова console.time()
в первой строке и вызова console.timeEnd()
в последней строке скрипта, который состоит исключительно из кода фреймворка. Для вашего удобства чтения вот лучшие из 20 результатов с кодом ведения журнала, вручную добавленным в связанные скрипты, запущенные из файловой системы, в Chrome на скромном настольном ПК 2010 года:
Vue | Mithril.js |
---|---|
21.8 ms | 4.5 ms |
Время загрузки библиотеки имеет большое значение в приложениях, которые не остаются открытыми на длительное время (например, все, что связано с мобильными устройствами) и не могут быть улучшены с помощью кэширования или других методов оптимизации.
Производительность обновления
Полезным инструментом для тестирования производительности обновления является инструмент, разработанный командой Ember под названием DbMonster. Он обновляет таблицу так быстро, как только может, и измеряет количество кадров в секунду (FPS) и время JavaScript (мин, макс и среднее). Количество FPS может быть трудно оценить, поскольку оно также включает время перерисовки браузера и задержку ограничения setTimeout
, поэтому наиболее значимой цифрой для просмотра является среднее время рендеринга. Вы можете сравнить реализацию Vue и реализацию Mithril.js. Обе реализации наивны (то есть без оптимизаций). Пример результатов показан ниже:
Vue | Mithril.js |
---|---|
9.8 ms | 6.4 ms |
Сложность
Vue в значительной степени вдохновлен Angular и имеет много вещей, которые делает Angular (например, директивы, фильтры, двунаправленные привязки, v-cloak
), но также имеет вещи, вдохновленные React (например, компоненты). Начиная с Vue 2.0, также можно писать шаблоны с использованием синтаксиса hyperscript/JSX. Это дополняет возможность использования однофайловых компонентов и различных плагинов трансляции языков на основе webpack. Vue предоставляет как двунаправленную привязку данных, так и дополнительную библиотеку управления состоянием, подобную Redux, но, в отличие от Angular, не предоставляет руководства по стилю. Подход "много способов сделать одно и то же" может вызвать архитектурную фрагментацию в долгосрочных проектах.
Mithril.js имеет гораздо меньше концепций и обычно организует приложения с точки зрения компонентов и уровня данных. Все стили создания компонентов в Mithril.js выводят одну и ту же структуру vnode, используя только собственные функции JavaScript. Опора на язык позволяет использовать меньше инструментов и упрощает настройку проекта.
Документация
И Vue, и Mithril.js имеют хорошую документацию. Оба включают в себя хорошую справочную информацию по API с примерами, учебные пособия для начала работы, а также страницы, охватывающие различные расширенные концепции.
Однако из-за подхода Vue "много способов сделать одно и то же" некоторые вещи могут быть недостаточно документированы. Например, их hyperscript сильно затушеван.
Документация Mithril.js обычно ошибается в сторону чрезмерной тщательности, если тема включает в себя вещи, выходящие за рамки Mithril. Например, когда тема включает в себя стороннюю библиотеку, документация Mithril.js описывает процесс установки сторонней библиотеки. Документация Mithril.js также демонстрирует простые, близкие к низкому уровню решения для распространенных случаев использования в реальных приложениях, где уместно информировать разработчика о том, что веб-стандарты теперь могут быть наравне с более крупными установленными библиотеками.
Учебные пособия Mithril.js также охватывают гораздо больше материала, чем учебные пособия Vue: учебник Vue заканчивается простым локальным списком дел, после прохождения нескольких страниц для охвата его большого основного API. 10-минутный гид Mithril.js охватывает большую часть своего API и даже рассматривает ключевые аспекты реальных приложений, такие как получение данных с сервера и маршрутизация. Если этого недостаточно, есть также более длинный и подробный учебник.