Pull to refresh

Comments 65

Откровенно говоря все эти «сравнения фреймворков» уже в печенки сидят.
Ну надо же как то поддерживать хайп по JS'у.
Я так понимаю у Hyperapp никакого Virtual DOM нет, но при этом он сравним по производительности с React и Vue, судя по цифрам в вышеприведенных табличках. Тогда где же все это хваленное преимущество наличия Virtual DOM?
Окей, вроде есть VDOM, не внимателен.
Подскажите пожалуйста, чем отличается keyed от non-keyed?
Видимо имеется ввиду атрибут key: <Component key='unique-key'>. React использует его для того, чтобы рендерить соседние компоненты в правильном порядке
        .then(json => {
            actions.getDataComplete(json);
        });
    },
    getDataComplete: data => state => ({ posts: data })

может actions.getDataComplete(json)(state) или return actions.getDataComplete(json);? А то в текущем виде промис ничего не возвращает, только создает замыкание state => ({ posts: data }), которое потом выбрасывается.

> Он говорит, что причиной такого утверждения стало то, что он выяснил, что Hyperapp легче в освоении, чем эти два фреймворка.

А уже освоенный vue/react еще легче в освоении.

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

может actions.getDataComplete(json)(state)

Хех. Я на Hyperapp не пишу, так что тоже глаз цепился. Думал — ошибка в примере.


Но таки нет. Обратите внимание, что в здесь actions — это не глобальная переменная, а то, что в передалось в обработчик вторым параметром.
Это обертка над оригинальным объектом actions, где обработчики автоматически привязаны к state (см. исходный код)

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


Т.е. передать селектор это удобнее чем самому подобрать элемент и отдать фреймворку? Точно?
В случае если я отдаю элемент я сам решаю как его выбирать, возможно я даже его буду сам динамически создавать, подцеплять в DOM и потом уже инитить фреймворк. В случае селектора — извините, запихайте пожалуйста вначале элемент в разметку, а потом отдайте селектор фреймворку чтобы он опять пошел щупать DOM на предмет элемента, на котороый у меня вроде как уже ссылка есть.
UFO just landed and posted this here
Создаешь в нужном месте div с нужным id, потом инициализируешь vue.


именно так, а Vue лезет в DOM и ищет этот div, мне кажется тут присутствует некоторая избыточность — если бы я мог просто передать ссылку на элемент то и искать его в DOM было бы незачем

похоже что разработчики Vue смотрят на ситуацию под схожим углом — если посмотреть в доки Vue, то окажется что в параметр el можно передавать не только селектор, но HTMLElement (https://vuejs.org/v2/api/#el)
Параметр «el» в vue может принимать как строку-селектор, так и объект типа HTMLElement. Так что всё нормально здесь, автор статьи был либо невнимателен, либо предвзят =)
Прямо по примеру №1. Очень смелое утверждение:
то окажется, что Hyperapp, для реализации приложения-счётчика, требуется меньше всего строк кода
при том, что для Hyperapp использованы стрелочные функции, в отличие от reart/vue:

down: value => state => ({ count: state.count - value}),

down: function(value) {
    this.count -= value;
},
Пример странный. У меня получилось так:
import Vue from "vue/dist/vue";

new Vue({
    data: { count: 0 },

    template: `
        <div>
            <h1>{{count}}</h1>
            <button @click="count -= 1">-</button>
            <button @click="count += 1">+</button>
        </div>
    `,

    el: "#app"
});
@click="count -= 1"

Там внутри что-то типа with(this){ return eval(attr); } или new Function("with(this) ...")?

UFO just landed and posted this here
Весь шаблон обернут в with от контекста.

То есть, стоит опечататься в названии переменной и мы пишем уже не в контекст компонента, а в случайный контекст выше по иерархии вплоть до window?

Кстати говоря, with запрещён к использованию в strict-mode и вообще не рекомендован к пользованию в статье про него на MDN.


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

Апдейт: написал небольшой бенчмарк, проверил, насколько использование with просаживает производительность: https://esbench.com/bench/5b54ae36f2949800a0f61eb9



Проверил в Chrome и Firefox, разница на порядок, даже без использования "use strict". Если Vue действительно использует with в продакшен-сборке, то где-то здесь зарыт неплохой буст его производительности.

А почему в vue используется jsx? более аутентичным было бы использование шаблонов.
в этом сравнении как-то упустили размеры фреймворков, реакт весит 160кб, а hyperapp — 5кб. И для мобильников это существенная разница, бандл на мегабайт жаваскрипта инициализируется на телефоне секунд 5
реакт весит 160кб

React, конечно не 5 KiB весит (тут вам Preact может помочь), но уж точно не 160, с чего вы взяли. Вы development флаг отключить забыли?

https://unpkg.com/react@16.4.1/umd/react.production.min.js
7.0 KiB (plain), 2.9 KiB (gzipped)

https://unpkg.com/react-dom@16.4.1/umd/react-dom.production.min.js
94.2 KiB (plain), 29.6 KiB (gzipped)

= 101.2 KiB (plain), 32.5 KiB (gzipped).


Собственно вот. Не знаю что именно вы имели ввиду под 160 KiB — с gzip или без, но всё не так плохо. А для компактных небольших приложений вполне сгодится не только hyperapp, но и preact. Там вроде как размеры вполне сопоставимые.


Для сравнения, 3.3.1 версия jQuery весит 256 KiB -> 75.2 KiB. Благо её использование обычно это legacy проекты и реальной нужды использовать jQuery в новых продуктах уже давно нет.

точно, завтыкал, предыдущая версия реакта была 160кб

Я думаю тогда уж лучше сразу Svelte брать.

А Svelte вообще ничего не весит… :)

насколько я понял, чем больше компонентов в приложении, тем больше он весит, и размер растет довольно быстро
  1. Самого Svelte нету, вес есть только у бандла т.е. по факту вашего кода.
  2. Больше компонентов, а значит больше вес это и для любых других фреймворков актуально. Тот код который генерирует компилятор Svelte очень хорошо сжимается и минифицируется в итоге разница не очень большая но самое главное то что в 50-70кб кода можно уложить ВСЁ ваше приложение (с 40-50 жирными компонентами) тогда как у многих рассматриваемых тут фреймворков вес без пользовательского кода уже куда больше.
  3. А если вам надо реально делать огромное приложение то в любом случае его надо разбивать на разные части (микрофеймворки и это всё).

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

ок, я полез тестировать, взял вот этот проект github.com/charpeni/svelte-example, собрал, минифицировал… получилось 6.2кб
исходного кода там на 2кб без минификации, оно получается уже наровне с hyperapp по размеру бандла. Пара десятков компонентов, и бандл Svelte будет в несколько раз больше чем то же приложение с hyperapp
  1. Это достаточно старый пример для первого Svelte. (в новом много чего добавили и улучшили)
  2. Попробуйте всё же добавить пару компонентов. Как я писал выше код там крайне примитивный (и эффективный) генерируется и он очень хорошо сжимается. Просто все эти createElement и appendNode ужмуться во что то типо a(), b() .
  3. А я детальнее глянул на hyperapp честно говоря это больше походит на каркас для VanilaJS и мягко говоря с примитивным View. Ну т.е. тут просто не сопостовимые проекты по фичам и я не спорю что можно и hyperapp заюзать и получить результат но вопросс в удобстве. Сейчас Svelte близок к Reactive и Vue по фичам (а где то и больше).
  4. Опять же по оперативке Svelte сильно выигрывает т.к. нету VDOM и не надо дважды хранить информацию.

т.е. выходит что Svelte позволяет писать с фичами макрофреймворков но с размерами микрофреймворков.

  1. Можно ссылку на более актуальный пример?
  2. Приложение которое я тестировал собирается в 12кб, затем минифицируется до 6кб. С обычными библиотеками всегда понятен оверхед, здесь же размер растет нелинейно, непонятно до какого момента выгоднее использовать Svelte, а не реакт
  3. Статья показывает, что hyperapp справляется со стандартными задачами не хуже взрослых фреймворков, что есть такое в Svelte, чего нет в hyperapp?

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

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

Хотя вполне могу помочь вам сократить изыскания, например, вот:
A Real-World Comparison of Front-End Frameworks with Benchmarks.

Там есть и про размеры в том числе.
т.е. выходит что Svelte позволяет писать с фичами макрофреймворков но с размерами микрофреймворков.

Очевидно, что если в микрофреймворк добавить фичи макрофреймворка, то получится макрофреймворк. С размером макрофреймворка.

да, но т.к. Svelte это компилятор то все эти фичи не влияют на рантайм.

то все эти фичи не влияют на рантайм.

Но ведь влияют. Чем больше у вас фич, тем больше будет вес итогового бандла.

Конечно влияют. Просто в случае с классическими фреймворками, вы тащите на клиент все что шипит фреймворк, даже если вам это не нужно. В случае с «исчезающими» таких проблем нет, а значит практически исчезает такая штука как «feature cost».

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

Это понятно. НО мы же в этой ветке говорим о: "Svelte позволяет писать с фичами макрофреймворков но с размерами микрофреймворков". Если вы используете все фичи — то и в бандле будут все фичи. Ничего "исчезнуть" не выйдет.


Если в микрофреймворк добавить фичи макрофреймворка, а потом все это дело статически проанализировать и потрясти хорошенько

То ничего не вытрясется, т.к. если вы используете фичу Х, то вытрясти ее нельзя.

Это понятно. НО мы же в этой ветке говорим о: «Svelte позволяет писать с фичами макрофреймворков но с размерами микрофреймворков». Если вы используете все фичи — то и в бандле будут все фичи. Ничего «исчезнуть» не выйдет.

Не знаю о чем говорите вы, но я так понял мысль stalkerg:

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

В мире в котором нет Svelte, у разработчика есть лишь 2 выбора:

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

Хорошо что мы живем не в этом мире, так как со Svelte у нас есть 3-й вариант:

3) Берем сразу макрофреймворк (по фичам), но юзаем только то, что нужно и при этом не платим костов за ненужные фичи, также как в случае с микрофреймворком.

> Не знаю о чем говорите вы, но я так понял мысль stalkerg:

То, о чем вы говорите, это: «Svelte позволяет писать с фичами _микро_фреймворков и размерами _микро_фреймворков».
Ангуляр, например, позволяет писать с фичами микрофреймворков, но не позволяет писать с размерами микрофреймворков (по крайней, мере пока Ivy не доделают). Svelte позволяет.
И ничего не позволит писать с фичами макрофреймворков и размерами микро, потому что если вы пишите с фичами макро — значит, они в коде. Вы их используете. Убрать их нельзя.
Не стоит вводить людей в заблуждение, утверждая, что Svelte — единственный микромодульный фреймворк. Не единственный. Более того, Svelte — всего-лишь низкоуровневый фреймворк, то есть предоставляет лишь базовую инфраструктуру, без хорошо интегрированной библиотеки модулей и компонент. Вы не сможете на нём поднять полноценный проект за один день.

Было бы интересно про более сложные концепции, типа render props, HOC и т.п.

UFO just landed and posted this here
Вспоминаются выборы президента в Футураме:
— Они похожи, как близнецы!
— Да они и есть близнецы…

Эх, опять не добавили к сравнению $mol. Исправляем ситуацию...


Пример№1: приложение-счётчик
$my_counter $mol_view
    sub /
        <= Count $mol_view sub / <= count?val 0
        -
        <= Down $mol_button
            title \-
            click?event <=> down?event null
        -
        <= Up $mol_button
            title \+
            click?event <=> up?event null

namespace $.$$ {
    export class $my_counter extends $.$my_counter {

        down() {
            this.count( this.count() - 1 )
        }

        up() {
            this.count( this.count() + 1 )
        }

    }
}

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


Пример№2: работа с асинхронным кодом

В предложенных в статье реализациях где-то потерялось отображение индикатора загрузки и обработка ошибок загрузки. Если их добавить, то кода станет куда больше. Мы же не будем халтурить и сделаем всё как следует:


$my_posts $mol_list
    loads?val 0
    rows /
        <= Load $mol_button
            title \Get posts
            click?event <=> load?event null
        <= Posts /
    Post $mol_view sub /
        <= Post_title $mol_view sub / <= post_title \
        <= Post_body $mol_view sub / <= post_body \

namespace $.$$ {
    export class $my_posts extends $.$my_posts {

        @ $mol_mem
        posts() {
            if( !this.loads() ) return []
            return this.$.$mol_http.resource( `https://jsonplaceholder.typicode.com/posts?${ this.loads() }` ).json()
        }

        load() {
            this.loads( this.loads() + 1 )
        }

        Posts() {
            return this.posts().map( ( post , index )=> this.Post( index ) )
        }

        post_title( index : number ) {
            return this.posts()[ index ].title
        }

        post_body( index : number ) {
            return this.posts()[ index ].body
        }

    }
}

Как видно, для отображения индикатора загрузки и сообщения об ошибке нам ничего не пришлось дополнительно писать, так как фреймворк взял эту рутину на себя. Логика загрузки мы описали в реактивном стиле, что даёт надёжность. Например, если пользователь будет неистово кликать по кнопке, то ранее посланные запросы будут отменяться, никак не влияя на работу приложения. Чего не скажешь про решения из статьи, где в этом случае на странице начнётся дискотека. Объём кода у всех сопоставимый.


Пример №3: компонент элемента списка для To-Do-приложения
$my_todo_item $mol_view
    attr * my_todo_item_done <= done?val false
    event * click?event <=> toggle?event null
    sub / <= title \

Мы получили самую комппактную реализацию, которая, в отличие от предложенных в статье решений, не создаёт новые обработчики событий при каждом рендеринге. Кроме того, архитектура $mol позволяет не выносить реализацию toggle во вне компонента, так что её можно описать тут же:


namespace $.$$ {
    export class $my_todo_item extends $.$my_todo_item {

        toggle() {
            this.done( !this.done() )
        }

    }
}

При этом владелец может переопределить как реализацию done, так и toggle.


Сравнение методов жизненного цикла компонентов

Жизненный цикл совершенно иной. Любые объекты создаются (constructor), когда кому-то нужны и разрушаются (destructor), когда никому не нужны. Когда кому-то требуется актуальное состояние дом дерева компонента — дёргается dom_tree. Если нужно именно монтирование/размонтирование, то достаточно подписаться на события DOMNodeInsertedIntoDocuments и DOMNodeRemovedFromDocument. Это довольно простой, но весьма мощный жизненный цикл.

Посмотрел ваши примеры, Дмитрий, теперь не смогу спать… Уже не раз зарекался, что не буду смотреть код на $mol, а просто ставить минус к комментарию с кодом, как это делают все, чтобы он быстрее стал сереньким, код стало не видно и он перестал давить на психику. Реально, после его прочтения снятся кошмары…
И кошмары не прекратятся, пока вы не перестанете ёрничать, а разберётесь в синтаксисе. Так что не затягивайте, чтобы нам не пришлось вызывать вам санитаров.
Да уж, если я начну разбираться в $mol, меня точно в дурку заберут. Видимо у меня не такая психика как у вас)))
А разве React это фреймворк?
Офф сайт говорит, что это библиотека.
А самому подумать? Фреймворк — это то что на выходе дает готовое решение, которое Вы кастомизируете своими хуками/каллбэками/DI и прочей магией. Либа — это набор функций который не диктует Вам архитектуру приложения. Реакт — фреймворк, независимо от того что написано на сайте.
Реакт разве вам что-то диктует?
Да, конечно. Он ждет на входе отдельные компоненты из которых собирается готовое приложение. Компонента может быть функцией или классом. Вы не сможете разбивать свое приложение не на компоненты а на какую то другую, Вам более удобную абстракцию (выше или ниже компонент) и при этом остаться в Реакте. Реакт вам диктует гранулярность абстракции.
Что именно вы не можете? Это же просто (пусть и кривой, огромный и неэффективный) шаблонизатор, вы его вольны использовать как вам вздумается.
Ну нет, шаблонизатор — это JSX сам по себе. Реакт же предполагает определенную логику синхронизации стейта.
JSX — язык шаблонов. Реакт — сам шаблонизатор. Какие там у него внутри оптимизации — дело десятое. На вход ему передаётся шаблон всего приложения и стейт, на выходе — отрендеренное dom дерево.
Реакт — сам шаблонизатор.

Нет. Если бы реакт был шаблонизатором — он бы только генерил dom из jsx. Он вместо этого генерит вдом, апдейтит его в соответствии с изменением пропсов, и апдейтит из него дом.


На вход ему передаётся шаблон всего приложения и стейт, на выходе — отрендеренное dom дерево.

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

Во первых не хамите.
Во вторых Вы совершенно не понимаете, термины фреймворк и библиотека.

«Фреймворк» отличается от понятия библиотеки тем, что библиотека может быть использована в программном продукте просто как набор подпрограмм близкой функциональности, не влияя на архитектуру программного продукта и не накладывая на неё никаких ограничений. «Фреймворк» же диктует правила построения архитектуры приложения, задавая на начальном этапе разработки поведение по умолчанию — «каркас», который нужно будет расширять и изменять согласно указанным требованиям. Пример программного фреймворка — C.M.F. (Content Management Framework), а пример библиотеки — модуль электронной почты.

ru.wikipedia.org/wiki/%D0%A4%D1%80%D0%B5%D0%B9%D0%BC%D0%B2%D0%BE%D1%80%D0%BA#%D0%9E%D1%82%D0%BB%D0%B8%D1%87%D0%B8%D0%B5_%D0%BE%D1%82_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B8

В случае React это былобы React + Redux + React-Router + Blueprint +…
Так же как Rails = ActiveRecord + ActiveSupport + ActiveMailer +…

А так это библиотека для "building user interfaces"
Вы:
>то библиотека может быть… не влияя на архитектуру программного продукта и не накладывая на неё никаких ограничений.

Я:
>Либа — это набор функций который не диктует Вам архитектуру приложения.

Вопрос — это я не не понимаю терминологии или Вы не в состоянии вдуматься в то что цитируете? И да, можете считать что я хамлю.
React можно встроить в существующее приложение, даже если уже используется jquery, angular или backbone, он (react) не диктует правила построения архитектуры.

Соответственно он полностью подходит под определение библиотеки, а не фреймворка.

Проводите логический анализ текста перед тем как писать.
реакт это чистое вью. И все что за пределами вью — да, он не диктует ничего. Прикручивайте редакс, роутер, граф апи, проблем нет. Но редакс диктует вам как будет организована логика вью. Он заставляет вас знать, когда будет перерисовка, обновление пропсов, у него есть свой лайфсайкл и вы его не можете изменить, можете только в него встроиться. И вот в переделах этого процесса редакс — фреймворк, за пределами его — называйте как хотите.
а теперь расскажите мне как вы будете встраивать в приложение где уже есть логика вью, не меняя этой логики. Например кусок кода jquery, который делает выборку по странице и навешивает на выбранное стили (или хандлеры или еще что то, пофигу) И тут у нас реакт, у которого перерисовка по каждому чиху. Будут они безконфликто существовать вместе? Не вынудит использование реакта засунуть jquery код внутрь компоненты? Не придется Вам, засовывая этот код в компоненту начать считаться со всеми правилами реакта и перебить код под эти правила?
Если у Вас есть такой реакт, в котором все это возможно — дайте ссылку, я с удовольствием с ним познакомлюсь.

ЗЫ — теоретики (небрежно)
Хотя конечно существует вероятность, что Вы умней и знаете больше об этой замечательной библиотеке, чем ее создатели. Но она крайне мизерна.

Как то всё это грустно т.к. на Svelte всё гораздо проще получается, весит меньше а уж рессурсов жрёт куда меньше (он же магически исчезающий).
Мне кажется новый и современный фреймворк без компиляции и с VDOM это прошлый век.

Sign up to leave a comment.