Pull to refresh

Comments 180

Больше магии. Меньше профессионализма и полного понимания как работает то, что ты только что написал.
Частично с вами соглашусь, однако это работает лишь для тех, кто не хочет разбираться.)))

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

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

уже давно четверки… хотя разве что вы ember решили выкинуть

Не уверен, может быть у вас какие-то другие источники, но когда я пишу «большая тройка» фронденда я пользуюсь терминологией довольно известной статьи The Ultimate Guide to JavaScript Frameworks.

Если вы ее откроете, то сразу увидите, что в большую тройку входят современные Angular, React и Vue. Такие штуки как Ember, Backbone и AngularJS называются там «исторически значимыми». Фактически, это предыдущая «большая тройка» фронденда.

Прочитайте, интересная статья. Надеюсь я ответил на вопрос.
Да да да, верните VueJS в список )
Рейтинг, который ничего не значит, давайте честно. Это известная проблема, что технология выбирается по количеству звёздочек на GitHub.
Рейтинг обозначает известность, а это в свою очередь означает что разработчики найдут на нем работу а заказчики(те кто оплачивают музыку) найдут разработчика. Так же это означает что закинув стек ошибки в гугл вы найдете 10 страниц выдачи с SO/github и тд а не перекати поле. Поэтому выберут React а не Inferno, Backbone а не CanJS.
Мой опыт гугления ошибок Ангуляра (40k звёзд):

1. В половине случаев вообще ничего похожего не гуглится.
2. В другой половине гуглятся открытые issue двухлетней давности с россыпью воркэраундов. Яркий пример: github.com/angular/angular/issues/18469

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

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


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

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

Явно не по-этому, там ведь все те же самые проблемы.

кривущему AOT компилятору

А можно подробнее? Действительно интересно, это мне, так сказать, для отчетности. ))))

https://angular-2-training-book.rangle.io/handout/aot/aot_limitations.html


Из того, на что я напоролся:


  1. Ругается на использование декораторов объявленных вне проекта.
  2. Ругается на код, не используемый в приложении.
  3. Требует, чтобы любая ерунда была объявлена в каком-либо модуле.
  4. Ругается, что одна и та же ерунда объявлена в нескольких модулях.
  5. Иногда забывает перекомпилировать код.
  6. Иногда забывает проверить типы (он это делает отложенно).
  7. Из-за кастомных модулей tree-shaking почти не работает.
  8. То и дело, продовый билд ломается по разным причинам — разные пайплайны для прода и дева дают о себе знать.
  9. Не работает для тестов — тесты фактически гоняются на совершенно другом рантайме.
  10. Не поддерживает динамическое задание lifecycle hooks. Даже через наследование. Их всегда нужно в явном виде писать в каждом классе. Люди выкручиваются через директивы.
  11. Ломает инкапсулированные стили, использующие host-context().
Интересно… Как раз скоро у нас на митапе будет битва «Svelte vs Angular AoT». Надо будет нарыть компромата на конкурента, спасибо за наводку)))))
Как раз скоро у нас на митапе будет битва «Svelte vs Angular AoT».

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

С чего вы взяли, что в Svelte для уменьшения объема только? Там как бы кодогенерация идет еще как минимум на некоторые фичи, в том числе на работу с DOM.

Так то идея была не моя, а автора 5-минутки Ангуляра, Леши Охрименко, и суть была именно померяться размерами.
С чего вы взяли, что в Svelte для уменьшения объема только?

Я не говорил, что только, я говорил об основной задаче.

Нет, я бы так не говорил. Основная задача — это преобразование SFC в ванила код. Уменьшение размера — это побочный эффект статического анализа, который нужен для генерации кода.
Нет, я бы так не говорил. Основная задача — это преобразование SFC в ванила код.

Это можно делать джитом, без АОТ-компиляции, то есть преобразование в ванилла-код — это задача компиляции в принципе. Точно так же в ангуляре преобразование шаблонов в ванилла-код или в реакте преобразование jsx в ванилла-код — это задача компиляции в принципе. То есть задача компиляции-то везде совпадает, да :)
А вот если вы ответите на вопрос: "почему вместо джита применяется АОТ" — тогда вы и назовете основную задачу именно АОТ-компиляции :)

Это можно делать джитом, без АОТ-компиляции, то есть преобразование в ванилла-код — это задача компиляции в принципе.

А зачем это делать джитом, если можно aot-ом? Опять же, многие вещи можно делать по-разному. Я же конкретно говорю, что в Svelte AoT используется не только и не столько для уменьшения размера. Зачем вы тут JIT приписали я не понимаю.

А вот если вы ответите на вопрос: «почему вместо джита применяется АОТ» — тогда вы и назовете основную задачу именно АОТ-компиляции :)

Назову, но это не будет уменьшение размера.
JIT == runtime, AOT == buildtime.

Отвечу пословицей: «Не оставляй на завтра то, что можно сделать сегодня».
Отвечу пословицей: «Не оставляй на завтра то, что можно сделать сегодня».

Ну вы же это не всерьез, что архитектурные решения принимаются исходя из пословиц? :)
Вы если можете объяснить, какая именно цель выбора именно аот позиционируется основной — так и скажите, можете даже перечислить несколько, в порядке убывания важности, если знаете. Чего вокруг да около ходить?

Ну вы же это не всерьез, что архитектурные решения принимаются исходя из пословиц? :)

Мне показалось, что моя мысль будет ясна, видимо я ошибся. Если кратко, суть в том, что если что-то можно сделать в buildtime оптимальнее это сделать там. В runtime оставить только то, что не может работать по-другому. Я даже не знаю что тут объяснять толком.
> Если кратко, суть в том, что если что-то можно сделать в buildtime оптимальнее это сделать там. В runtime оставить только то, что не может работать по-другому.

Но то что вы описали _само по себе_ никакой пользы ведь не дает. Это действительно цель, позиционируемая svelte как основная? «в компайлтайме, потому что лучше раньше чем позже»?
Как это не дает? Сделать большую часть работы на машине разработчика и не делать ее на машине пользователя, разве не дает нам ничего? Серьезно? Я думаю это дает нам многое.
Как это не дает? Сделать большую часть работы на машине разработчика и не делать ее на машине пользователя, разве не дает нам ничего?

Само по себе — конечно, нет. Вот повышение производительности приложения у пользователя за счет экономии времени на компиляцию — это да, дает. Это хорошая цель. А просто переместить вычисления в компайлтайм — это не цель, это способ достижения цели.


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

У вас большая часть претензий сводится к тому, что аот-компилятор является аот-компилятором. Если вам не нужна аот-компиляция — ну не используйте. Предъявлять же молотку претензии в том, что он забивает гвозди — как минимум, странно.

Почему же, например, в $mol таких проблем нет, где есть только AOT компиляция и никаких JIT?

А в чем у вас АОТ в мол заключается? Ну, что там делается?

Анализируются исходники на предмет зависимостей и берутся модули, что фактически используются и выстраиваются в порядке от зависимостей к зависимым. Из всех модулей берутся декларативные описания компонент, которые транслируются в TypeScript класс и json с текстами. Из всех модулей берутся json с текстами и генерятся текстовые бандлы под каждый язык. Из всех модулей берутся TS и транслируются в JS. Из всех модулей берутся JS и собираются в JS бандлы (под веб, под ноду, тесты). Из всех модулей берутся CSS прогоняются через PostCSS и собирается в CSS бандл. Из всех модулей берётся реестр статических файлов и найденные там файлы перекладываются в билд директорию. Девелоперский сервер мониторит изменения всех файлов, к которым при сборке было обращение, и автоматически перезапускает сборку соответствующих бандлов.
Анализируются исходники на предмет зависимостей и берутся модули

Ну если я где-то там в потрохах напишу if(hang()) { require("something") } то что ваш компилятор сделает?


Из всех модулей берутся декларативные описания компонент

Что если я написал ф-ю, которая генерирует описания компонент, и объявляю компоненты вызовом этой ф-и?

Ну если я где-то там в потрохах напишу if(hang()) { require("something") } то что ваш компилятор сделает?

Ничего. Вот если напишете if(hang()) { $node.something }, то соответствующий модуль будет включён в бандл.


Что если я написал ф-ю, которая генерирует описания компонент, и объявляю компоненты вызовом этой ф-и?

Вы не сможете этого сделать.

А чем это принципиально отличается от webpack-бандла?

Честно говоря, очень сложно сравнивать AoT-компилятор + статический анализатор с бандлером вроде Webpack. ))))

Более того, если говорить о Svelte, да и о других аналогах, я думаю, процесс компиляции стартует именно во время сборки бандлером. Иными словами, обычно, это часть процесса сборки.

Если вы хотите разобраться в данной теме немного глубже, советую вам ознакомиться со статьями приведенными в конце, а также комментариями к ним.
bundle — сжатые исходники в один файл(меньше запросов к серверу), минимизированые исходники. Тут же подход к коду другой. Идея генерировать простой, легкий и быстрый код. Но если мы используем для библиотек cdn, то скорость загрузки и размер этой библиотеки уже не важна, т.к вероятно уже будет у клиента или скачается при первом посещении. Но ещё одно за «раздутые» фреймворки, это стоимость поддержки, много ли разработчиков на Svelte, доверит ли бизнес свои продукты тому про что первый раз слышат.
Но на свою полочку инструментов, хорошо бы добавить альтернатив.

Есть ещё такая актуальная проблемма для мобильных устройств — скорость разбора js. Да и cdn для библиотек всё же не так часто используют, скорее бандлят всё. А на счёт продуктов — в моей конторе я пишу на Svelte. Достаточно большую админку удерживаю в размерах 50кб.

Кроме того, что это перевод, а не авторская статья, Prepack все же немного не о том. Более того, его легко можно натравить на код, который генерируется Svelte, чтобы еще больше его оптимизировать.
UFO just landed and posted this here
Как посчитал Alex Russell, превышение размера всего в 130KB для всех наших ресурсов, может означать невозможность уложиться в 5 секундный интервал загрузки на стандартном телефоне и мобильной сети.

Например, в этой статье суммарный объём, занимаемый встроенными в неё картинками, превысил 4Mb, что, вероятно, ощутимо для мобильного телефона.

Открываем пример на svelte https://svelte.technology/repl?version=2.8.1&demo=each-blocks, тыкаем снизу на кнопку "input" и смотрим на функции: create_main_fragment() и create_each_block(). И сразу становится очевидным что как только приложение будет более менее серьёзным, то кол-во кода которое генерирует "Магически исчезающий JS фреймворк" будет превышать размер фрэймворка, который был оптимизирован под размер генерируемого кода.

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

Во-первых, Svelte — это компилятор, который имеет множество настроек. К примеру, есть настройка, которая позволяет автоматически вырезать не используемые cтили из Svelte компонентов и еще много всего. Так вот, есть настройка shared: true, которая говорит Svelte переиспользовать общий код компонентов, чтобы избежать дублирования.

Во-вторых, в REPL вы действительно видите полный код всех компонентов, но сделано это для вашего же удобства. Проще говоря, код в REPL компилируется с shared: false и вам не стоит обращать на это внимание.

Можно также рассмотреть реальные кейсы, например, вот сравнение реализаций на разных фреймворках одного и того же проекта RealWorld — блогосоциальная сеть, как Medium или Хабр:

image
Transfer size (KB) — lower is better

https://medium.freecodecamp.org/a-real-world-comparison-of-front-end-frameworks-with-benchmarks-2018-update-e5760fb4a962

Не смотря не то, что RealWorld — это уже проект среднего размера, далеко не Hello World или
TodoMVC. Однако, как вы можете заметить, размер реализации на Svelte даже не приближается к размеру реализаций на популяных фреймворках «большой тройки».

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

Я специально указал на какие функции смотреть, а не на весь сгенерированый код.

> Можно также рассмотреть реальные кейсы, например, вот сравнение реализаций на разных фреймворках одного и того же проекта RealWorld — блогосоциальная сеть, как Medium или Хабр:

Совершенно бессмысленный бэнчмарк если смотреть на цифры и не понимать ключевые отличия в реализациях, например какие реализации используют code splitting, какие либы используются для client-server взаимодействия итд.

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

Это если сравнивать с фреймворками «большой тройки». А если посмотреть на либы которые так же замарачиваются на размере, то есть всякие preact или hyperapp, которые не будут генерировать 3 различных пути исполнения для создания/обновления/удаления дом нодов.
Я специально указал на какие функции смотреть, а не на весь сгенерированый код.

Не вижу ничего криминального в этих функциях. Довольно примитивные и понятные фукнции. В итоговом коде — это будут семки.

Совершенно бессмысленный бэнчмарк если смотреть на цифры и не понимать ключевые отличия в реализациях, например какие реализации используют code splitting, какие либы используются для client-server взаимодействия итд.


Там сравнивается полный размер доставляемого кода, поэтому ни SSR, ни code-splitting роли не играет. Отличия в реализациях, безусловно, есть, но не в 2-3 раза, как отличия в размере.

К тому же, кроме размера, есть и иные показатели, и по ним Svelte также хорош. В том числе, если посмотреть всем известные js-framework-benchmark. Весь столбик Svelte, включая старт и память, зелен как летняя листва)))

Это если сравнивать с фреймворками «большой тройки». А если посмотреть на либы которые так же замарачиваются на размере, то есть всякие preact или hyperapp, которые не будут генерировать 3 различных пути исполнения для создания/обновления/удаления дом нодов.


Тут, пожалуй, я с вами соглашусь вот в чем… действительно, я сравниваю Svelte, по большей части, с поплурными фреймворками, такими как React/Vue/Angular/Ember/etc. И редко упоминаю о всевозможных маргинальных вещах, среди которых, есть весьма достойные конкуренты в вопросах скорости, размера и т.п. Это правда. Тот же AppRun, из RealWorld сравнения, уделал всех.

Однако, я делаю это потому, что считаю, что Svelte может стать столь же популярным, как и фреймворки «большой тройки». Кроме того, я и не утверждаю, что Svelte — абсолютно лучше всех и во всем. Даже сам его создатель писал, что пока не знает как вообще можно побить в скорости Inferno, потому что его создатель реально демон. Но Svelte достаточно хорош во всех основных показателях и при этом имеет довольно обширный набор возможностей, которых нет в том же Inferno, Preact или AppRun.

Проще говоря, Svelte — очень хорошо сбалансирован во всем, достаточно для того, чтобы я мог делать на нем практически любые виды приложений. Он не имеет каких-то ярко-выраженных перекосов ни по одной из характеристик, выжных для удобства и качества разработки.
Там сравнивается полный размер доставляемого кода, поэтому ни SSR, ни code-splitting роли не играет

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


В том числе, если посмотреть всем известные js-framework-benchmark. Весь столбик Svelte, включая старт и память, зелен как летняя листва)))

В этом бэнчмарке нужно смотреть не на цвет, а на абсолютную разницу с ванилой. На создание нодов в svelte приходится примерно столько же времени сколько на рендеринг страницы с тяжёлыми css правилами и табличным лэйаутом. Очень печальная цифра для библиотеки, которая генерирует "оптимальный" код и не замарачивается о размере генерируемого кода. Этот бенчмарк содержит тесты, которые должны быть идеальными для такой библиотеки как svelte, но несмотря на это, она показывает оч печальные цифры.


Даже сам его создатель писал, что пока не знает как вообще можно побить в скорости Inferno, потому что его создатель реально демон.

Создателю Inferno я долго объяснял такие вещи как мономорфизм и что очень важно чтоб все виртуальные ноды имели один и тот же шэйп, как работает мой алгоритм для нахождения минимальных перестановок, большинство всех архитектурных решений как сделать быстрый vdom, даже понадобилось объяснять почему я использовал битовые операции в моей либе. Я тоже немного знаю о производительности :)


Но Svelte достаточно хорош во всех основных показателях и при этом имеет довольно обширный набор возможностей, которых нет в том же Inferno, Preact или AppRun.

Вы это серьёзно? Он смог написать компилятор только благодаря тому что выкинул гибкость, которую предоставляют традиционные vdom либы.

У Svelte вообще нету vdom, о чём вы говорите?

О возможностях svelte, тк там урезан функционал по сравнению с vdom'ом, то есть возможность статического анализа и можно использовать различные стратегии для генерации кода. Поэтому разговор об его обширных возможностях сразу намекает о том что человек совершенно не разбирается в этом вопросе.
Вообще то, как раз Svelte и производит статический анализ кода перед генерацией. Проще говоря Svelte — это статический анализатор + компилятор SFC в ванилу.

Причем тут статический анализ и Virtual DOM, который априори runtime, я не понимаю.
Я и говорю что у svelte есть статический анализ, и есть он благодаря тому что повыкидывали возможности которые есть «в том же Inferno, Preact». Поэтому какие-то обширные возможности Svelte в сравнении с этими библиотеками как-то выглядят странно, хотя может вы про экосистему говорите, а не о возможностях библиотек.
Знаете, пытаюсь понять вашу мысль, но не получается. Говорите какими-то общими фразами, а я люблю конкретику. А уже причем тут статический анализ вообще не ясно.

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

Давайте может конкретно, какие такие возможности есть у Inferno или Preact, которых нет в Svelte? Вот список функциональных возможностей, которые есть в Svelte:

  1. Однофайловые и много-файловые компоненты
  2. Использование любых предпроцессоров кода (eg Coffescript) и стилей (eg SCSS) и шаблонов (eg Pug)
  3. Встроенная система Scoced-стилей компонента + вырезка неиспользуемых стилей (unused style removal)
  4. Композиция компонентов и инекция с помощью слотов (slot)
  5. Полностью реактивный встроенный стейт компонентов
  6. Реактивные вычисляемые свойства (computed props) компонентов
  7. Опциональное двойное связывание (two-way binding) как для пользовательского ввода, так и для компонентов
  8. Хуки жизненного цикла (life-cycle hooks)
  9. Наблюдатели (observers)
  10. Кастомные события и proxy-события
  11. Экшены (декораторы) над dom узлами и поддержкой синхронизации данных
  12. Анимации переходов (transitions)
  13. Язык шаблонов с поддержкой JS выражений
  14. Дерективы
  15. Методы и хелперы
  16. Иерархический глобальный Store на основе классов c вычисляемыми свойствами, событиями и хуками (тоже все реактивное)
  17. Поддержка асинхронных данных (можно хранить промисы в стейте и резолвить их по месту назначения)
  18. Полная поддержка SVG с соответствующим namespace
  19. Специальные компонент тег для рекурсивного вложения компонента (удобно для TreeView, например)
  20. Специальный тег для декларативной работы с window
  21. Специальный тег для декларативной работы с head
  22. Специальный тег для динамической подмены компонентов
  23. Поддержка Custom Elements стандарта из коробки
  24. Поддержка SSR с гидрацией на клиенте (hydrate)
  25. Набор фичей самого компилятора, который будет расширяться


Возможно не все привел и что-то упустил, но это не суть. Можете перечислить что из этого умеет Inferno или Preact, или даже React, и мы посмеемся вместе?))) Ну и жду от вас список возможностей оных, которых нет в Svelte)))


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


Нет, не одной страницы. 40Кб это размер всего кода реализации на Svelte. Размер скриптов первой страницы занимает всего 12Кб. Откройте дев-консоль и посмотрите сами. Поэтому code-splitting тут вообще не причем. И не надо, пожалуйста, думать, что все вокруг тупые, только вы один Д'Артаньян, а автор сравнения не догадался учесть все чанки суммарно.

В этом бэнчмарке нужно смотреть не на цвет, а на абсолютную разницу с ванилой. На создание нодов в svelte приходится примерно столько же времени сколько на рендеринг страницы с тяжёлыми css правилами и табличным лэйаутом. Очень печальная цифра для библиотеки, которая генерирует «оптимальный» код и не замарачивается о размере генерируемого кода. Этот бенчмарк содержит тесты, которые должны быть идеальными для такой библиотеки как svelte, но несмотря на это, она показывает оч печальные цифры.


Ну зачем вы ерунду то пишете? Важно смотреть на все показатели сразу. Вытаскивать отдельные показатели и строить по ним мнение о чем-то — это не более чем демагогия. Вы вот вытащили показатель create rows и вот мол, у Svelte 1.8 к ваниле, но во-первых, вы же не посмотрели на версию Svelte в сравнении (1.58.5), а сейчас (2.8.0) и насколько я знаю, есть серьезные улучшений в этом показателе.

Но возвращаясь к тому, что вытаскивать куски — это не серьезно. Тогда я могу вытащить вам в ответ swap rows, а там уже у ванилы 1.2 к Svelte. И что? Должно ли это доказать всем, что Svelte быстрее ваниллы?

Именно поэтому, смотреть надо на все показатели. И в сравнении Svelte против «большой тройки», только у Svelte все показатели ± положительные. Да, например, по некоторым тестам Svelte чуть уступает Angular 6, но если вы посмотрите сколько при этом памяти жрет Angular, чтобы добиться таких показателей, сразу все станет понятным.

Создателю Inferno я долго объяснял такие вещи как мономорфизм и что очень важно чтоб все виртуальные ноды имели один и тот же шэйп, как работает мой алгоритм для нахождения минимальных перестановок, большинство всех архитектурных решений как сделать быстрый vdom, даже понадобилось объяснять почему я использовал битовые операции в моей либе. Я тоже немного знаю о производительности :)

Вы вот тут говорите, что мол такой молодец и красавчег, и даже автору Inferno советы даете. И либа то у вас там какая-то с супер алгоритмом, но что-то я не вижу ни одной статьи об этой чудо либе, да и вообще никакой информации. Поэтому разговор ни о чем. Если кичитесь своей работой, так предоставьте ее на свеобщее обозрение, посмотрим — оценим. Будет предмет для разговора.

Вы это серьёзно? Он смог написать компилятор только благодаря тому что выкинул гибкость, которую предоставляют традиционные vdom либы.

О чем это вы? Какую такую «гибкость» дает vdom в buildtime? Это же чистый runtime.)))) Возможно, вам стоит ознакомиться с докладом Сергея Чикуенка из Одноклассников — А так ли нужен Virtual DOM?

Да и вообще, давно уже идет тенденция, что Virtual DOM оказался не такой уж здравой идеей.

Нет, не одной страницы. 40Кб это размер всего кода реализации на Svelte. Размер скриптов первой страницы занимает всего 12Кб

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


И не надо, пожалуйста, думать, что все вокруг тупые, только вы один Д'Артаньян

Я просто в теме веб бэнчмарков очень давно и отлично знаю какое враньё там постоянно происходит, и что в первую очередь нужно смотреть на различия в реализациях, потом на возможности библиотеки и заканчивая специальными хаками, которые были добавлены чтоб получить хорошую цифру в бэнчмарке. Втч я сам сабмитил реализации которые были специально оптимизированы под то чтобы выигрывать в бэнчмарках https://medium.com/@localvoid/how-to-win-in-web-framework-benchmarks-8bc31af76ce7


Важно смотреть на все показатели сразу.

Если не понимаете как читать результаты этого бэнчмарка, то можете отсабмитить там issue, и другие участники этого проекта вам объяснят, если уж вы не верите моим словам.


И опять же, в этом бэнчмарке так же важно понимать различия в реализациях. К примеру если я повыкидываю компоненты и коннекторы из оригинальной реализации на ivi и просто сделаю реализацию, удовлетворяющую условиям бэнчмарка https://github.com/localvoid/js-framework-benchmark/blob/sandbox/frameworks/ivi-SIMPLE/src/main.js то кол-во потребляемой памяти резко упадёт до уровня Svelte https://rawgit.com/localvoid/js-framework-benchmark/sandbox/webdriver-ts-results/table.html. Так же и с остальными реализациями в этом бэнчмарке, если нет глубого понимания внутренностей, то рассматривание цифр в этом бэнчмарке ничего не даст.


и даже автору Inferno советы даете.

Автор Инферны не привнёс никаких новшеств в разработке производительных UI либ, он только собирал в различные чатики разработчиков других либ, где мы обсуждали всякие проблемы.


Если кичитесь своей работой, так предоставьте ее на свеобщее обозрение, посмотрим — оценим.

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


Но если хотите взглянуть:


https://github.com/localvoid/kivi — Библиотека, которую я использовал чтобы выигрывать в бэнчмарках, оптимизированы только низкоуровневые примитивы. Большая часть архитектурных решений Инферны была склонирована с этой либы.


https://github.com/localvoid/ivi — Здесь уже совершенно другая архитектура и вместо фокуса на низкоуровневых примитивах, фокус на понижение стоимости высокоуровневых абстракций.


О чем это вы? Какую такую «гибкость» дает vdom в buildtime? Это же чистый runtime.))))

https://www.youtube.com/watch?v=mVVNJKv9esE


Да и вообще, давно уже идет тенденция, что Virtual DOM оказался не такой уж здравой идеей.

И видимо поэтому в angular2+ давно ушли от модели компиляции в "оптимальный" код с кучей путей исполнения как в Svelte, а в angular ivy так вообще переходят к компиляции во что-то похожее на incremental dom, который очень близок к тому как работает vdom.

И что же общего у incremental dom и virtual dom?

Единственное отличие в том что в incremental dom инструкциями являются вызовы функций, а в virtual dom это жаваскрипт объекты, которыми можно произвольно манипулировать.


И я не считаю что эта возможность virtual dom'а прям оч сильно важна, поэтому мне очень любопытно как в angular ivy будет выглядеть конечная реализация когда разрулят все edge case'ы.

То есть ничего общего между ними нет.
Всё остальное тоже самое, просто вместо диффа vnode<>vnode, переход по предыдущему дереву происходит сразу же в «render» функции и там же применяются изменения.
Можно использовать все те же самые структуры данных для хранения предыдущего состояния и алгоритмы для обхода дерева и диффа.
Вы издеваетесь? :) В чём отличие алгоритмов для диффа, которые используются в incremental dom?
Возможно мы говорим о разных вещах :) Под incremental dom я подразумеваю идеи, которые использовались в github.com/google/incremental-dom (An in-place DOM diffing library)
Там применяются патчи к реальному дому без вычисления диффов.
Там диффается с реальным домом. В библиотеках типа Preact тоже происходит дифф с реальным домом. Но это не особо интересно и тормозно, гораздо интереснее какой оверхэд будет у angular ivy, который диффает с «виртуальным домом» github.com/angular/angular/blob/637805a0c90b201f3e258eaeff967d5992d71faf/packages/core/src/render3/interfaces/node.ts

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

Дифф — это вычисление разницы. Чтобы применить патч вовсе не нужно вычислять разницу. Например, такой код:


el.setAttribute( 'id' , id )

Оказывается даже быстрее, чем такой:


if( el.getAttribute( 'id' ) !== id ) {
    el.setAttribute( 'id' , id )
}

Поэтому я и говорил что интересно какой оверхэд будет у angular ivy, тк там не нужно вызывать getAttribute() для получения предыдущего значения и дифф в куче случаев будет отрабатывать на interned строках, так что продиффать будет гораздо эффективнее чем вызывать setAttribute(), производительность которого ещё может зависеть от того насколько будет забит stub cache, тк там у них вроде повсюду мегаморфные колсайты.

Так что на счёт Svelte то? (в котором никаких vdom нету)

Всё что я хотел сказать про Svelte, я сказал в самом первом комментарии.

То что мне тут приписывают о том что я где-то сказал про то что в Svelte есть vdom, или о том что у vdom есть гибкость в buildtime меня как-то не особо интересует. Может я как-то невнятно изъясняюсь, может просто у кого-то недостаточно фундаментальных знаний чтобы вести разговор на эти темы. В любом случае, не вижу смысла продолжать разговор на эту тему.
nuit Ну давайте тогда разберемся. Вот ваше первое утверждение, основанное лишь на беглом просмотре куска кода в REPL:
И сразу становится очевидным что как только приложение будет более менее серьёзным, то кол-во кода которое генерирует «Магически исчезающий JS фреймворк» будет превышать размер фрэймворка, который был оптимизирован под размер генерируемого кода.

На что я вам сразу привел пример «более менее серьезного» приложения RealWorld, результаты которого 40Кб у Svelte против, пусть даже, 78Кб у React, т.е. в 2 раза.

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

Насколько я знаю, опыт stalkerg примерно такой же.

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

Далее, вы сфорумулировали следующее важное утверждение:
О возможностях svelte, тк там урезан функционал по сравнению с vdom'ом, то есть возможность статического анализа и можно использовать различные стратегии для генерации кода. Поэтому разговор об его обширных возможностях сразу намекает о том что человек совершенно не разбирается в этом вопросе.


На что я вам привел список обширных возможностей Svelte, лишь малая часть из которых представлена или имеет аналоги в таких фреймворках как Inferno, Preact, React и Ivi.

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

LOL

На что я вам сразу привел пример «более менее серьезного» приложения RealWorld, результаты которого 40Кб у Svelte против, пусть даже, 78Кб у React, т.е. в 2 раза.

Тк все веб бэнчмарки с которыми я когда-либо имел дело сопровождались враньём, то я никогда просто так не верю в подобные сравнения, и сразу начал искать различия в реализациях. Допустил ошибку в том что при подсчёте использовался code-splitting, тк результаты как-то не сходились с реальностью, увидел что в реактовой реализации зачем-то тащится тяжёлая superagent либа которая ещё и в cjs формате, в то время как в svelte используется обычный fetch. Сделал вывод, что этот бэнчмарк ничем не отличается от остальных и что если углубиться в детали, то скорее всего можно найти ещё различия, которые могут сильно повлиять на размер конечного приложения.


Кроме того, я вам четко сформулировал квинтесенцию своего чуть более чем годового опыта работы со Svelte в реальных проектах

На что я вам ответил что есть другие библиотеки, у которых маленький размер и у которых будет компактный код приложения: Preact и HyperApp. Обе используют vdom.


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

Потомучто я говорил про Preact и HyperApp, которые используют vdom. И когда вы начали говорить что в Preact/Inferno нет какого-то обширного набора возможностей, то вы порушили все мои стереотипы :) Тк благодаря тому что в Svelte невозможно работать с элементами интерфейса, как с простыми жаваскрипт объектами, то из-за этого теряется гибкость, но за счёт потери гибкости появляется возможность статического анализа. Поэтому для решения реальных задач в Svelte пришлось добавлять всякие директивы, слоты итд, которые совершенно не нужны в таких библиотеках как React.


И я не утверждаю что это плохо или хорошо, я считаю что для подавляющего большинства задач вполне достаточно возможностей Svelte. Но при этом утверждение что у Svelte гораздо больше возможностей звучит очень странно. У него есть ряд возможностей, которые не доступны в Preact/Inferno вроде статического анализа и отлова всяки a11y ошибок на этапе компиляции, но при этом в нём нельзя использовать элементы интерфейса как простые жаваскрипт объекты. Для команды реакта например очень важна эта возможность On The Spectrum of Abstraction, для пользователей Svelte возможно нет, нет каких-то идеальных решений. Любой разработчик фрэймворка, который крутится в этой области достаточно давно сможет с лёгкостью указать на косяки в любой из библиотек, невозможно сделать какое-то идеальное решение, всё время приходится чем-то жертвовать, особенно когда всё это делается поверх web платформы, у которой очень много проблем.


На что я вам привел список обширных возможностей Svelte, лишь малая часть из которых представлена или имеет аналоги в таких фреймворках как Inferno, Preact, React и Ivi.

Часть этих "возможностей" относится к решением проблем с шаблонизатором в Svelte, часть к экосистеме, которая в React гораздо богаче, часть к инструментам сборки. Вместо всего этого, могли просто сказать какой юзкэйс вы не сможете решить с помощью библиотеки типа React, тк я тоже могу начать кидаться всякими сложными проектами из экосистемы реакта: react-beautiful-dnd, draft.js, react-spring и много-много других.


И ivi тут как бы вообще не конкурент, тк никакой экосистемы нет, поэтому я стараюсь не говорить об этой библиотеке и когда мне приходят письма на тему ivi, я всем отвечаю чтоб использовали React. А вот с Preact и Inferno многие проекты из экосистемы реакта должны работать без особых проблем, кроме совсем сложных вроде draft js.

увидел что в реактовой реализации зачем-то тащится тяжёлая superagent либа которая ещё и в cjs формате, в то время как в svelte используется обычный fetch. Сделал вывод, что этот бэнчмарк ничем не отличается от остальных и что если углубиться в детали, то скорее всего можно найти ещё различия, которые могут сильно повлиять на размер конечного приложения.

Послушайте, все понимают, что если дать разным людям написать какой-то проект, то они напишут его по-разному. Ну и что, что чел, который писал имплементацию на React жить не может без Superagent? В gzip он весит 5КБ примерно, даже если вычесть их, то разница в размере все равно получается существенная. Не нужно притягивать вещи за уши.
На что я вам ответил что есть другие библиотеки, у которых маленький размер и у которых будет компактный код приложения: Preact и HyperApp. Обе используют vdom.

Ну есть они и что? Много чего есть. Хотите, напишите статью о них. Разве в этой статье речь шла о vdom библиотеках? Или раз есть +100500 vdom библиотек, которые из которых быстрые, все остальные подходы побоку? Да и откровенно говоря сравнивать Preact со Svelte — это смешно. У него и половины возможностей нет. Это не более чем тонюсенький view-слой. Я бы понял, если бы вы сравнивали Svelte с Vue, у которого тоже vdom.

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

Слоты — это как бы часть стандарта Web Components, если что, а директивы — это вполне себе HTML-like стиль. Причем кастомных директив у Svelte нет, и это хорошо.

Но при этом утверждение что у Svelte гораздо больше возможностей звучит очень странно. У него есть ряд возможностей, которые не доступны в Preact/Inferno вроде статического анализа и отлова всяки a11y ошибок на этапе компиляции, но при этом в нём нельзя использовать элементы интерфейса как простые жаваскрипт объекты.

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

Что это за такая функциональная возможность «использовать элементы интерфейса как простые жаваскрипт объекты» и что такого она мне дает, я не знаю. Это скорее похоже на императивный способ решения задач, но зачем он мне я представить не могу, потому что предпочитаю декларативный стиль. А так то, пожалуйста, используйте элементы интерфейса как JS объекты в Svelte:

<input ref:input>
<NestedComponent ref:nested />
<script>
    export default {
        oncreate() {
             // вот вам dom-элемент в виде js объекта
             const input = this.refs.input; 

             // вот компонент в виде js объекта
             const nested = this.refs.nested;

             // работаем с ними
             const value = input.value;
             nested.set({ value });
        } 
    };
</script>

Только накой черт мне это все делать, если можно писать в 100 раз проще?

Часть этих «возможностей» относится к решением проблем с шаблонизатором в Svelte, часть к экосистеме, которая в React гораздо богаче, часть к инструментам сборки.

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

Любой действительно реактивный юзкейс. Хотя конечно решить то можно, но какими усилиями. Опять же говорим про средства React, без всяких там Mobx.
тк я тоже могу начать кидаться всякими сложными проектами из экосистемы реакта: react-beautiful-dnd, draft.js, react-spring и много-много других.

Да под React сейчас больше всего понаписано — это факт, никто о богатстве экосистемы и не спорит. Но когда он только появился, ничем таким он похвастаться не мог. Ничего супер сложного в этих проектах я не вижу, однако без слез на их код не взглянешь, конечно. Написано настолько сложно, насколько только можно придумать. Ну, а на Svelte, вполне можно пока использовать существующие решения на ваниле, нежели все писать свое. Благо на нем все делается просто и лаконично:

REPL

Разве в этой статье речь шла о vdom библиотеках?

В этой статье речь шла о размере приложений, я указал на то что Svelte генерирует гораздо больше кода, чем еслиб использовалась библиотека вроде Preact или HyperApp, всё, конец. Нет желания вести с вами диалог, вы явно не открыты к диалогу со мной и с лёгкостью готовы поливать говном работу других людей "Ничего супер сложного в этих проектах я не вижу, однако без слез на их код не взглянешь, конечно.", вы тут знаете больше всех, так что кто я такой чтобы вам что-то объяснять.

UFO just landed and posted this here
А вообще, я лишь только хотел указать на небольшой недостаток Svelte, когда он в простом примере сгенерирует ~90 строк «оптимального» non-shareable кода. В то время как если использовать какой-нибудь preact, у которого есть небольшой оверхэд в размере, от которого тяжело избавиться на hello world демках, но зато на том же примере его апи позволит реализовать тот же функционал используя ~5 строк менее «оптимального» кода.

Svelte:

Скрытый текст
function create_main_fragment(component, ctx) {
	var ul;

	var each_value = ctx.cats;

	var each_blocks = [];

	for (var i = 0; i < each_value.length; i += 1) {
		each_blocks[i] = create_each_block(component, get_each_context(ctx, each_value, i));
	}

	return {
		c: function create() {
			ul = createElement("ul");

			for (var i = 0; i < each_blocks.length; i += 1) {
				each_blocks[i].c();
			}
		},

		m: function mount(target, anchor) {
			insertNode(ul, target, anchor);

			for (var i = 0; i < each_blocks.length; i += 1) {
				each_blocks[i].m(ul, null);
			}
		},

		p: function update(changed, ctx) {
			if (changed.cats) {
				each_value = ctx.cats;

				for (var i = 0; i < each_value.length; i += 1) {
					const child_ctx = get_each_context(ctx, each_value, i);

					if (each_blocks[i]) {
						each_blocks[i].p(changed, child_ctx);
					} else {
						each_blocks[i] = create_each_block(component, child_ctx);
						each_blocks[i].c();
						each_blocks[i].m(ul, null);
					}
				}

				for (; i < each_blocks.length; i += 1) {
					each_blocks[i].d(1);
				}
				each_blocks.length = each_value.length;
			}
		},

		d: function destroy(detach) {
			if (detach) {
				detachNode(ul);
			}

			destroyEach(each_blocks, detach);
		}
	};
}

function create_each_block(component, ctx) {
	var li, a, text_value = ctx.cat.name, text, a_href_value;

	return {
		c: function create() {
			li = createElement("li");
			a = createElement("a");
			text = createText(text_value);
			a.target = "_blank";
			a.href = a_href_value = ctx.cat.video;
		},

		m: function mount(target, anchor) {
			insertNode(li, target, anchor);
			appendNode(a, li);
			appendNode(text, a);
		},

		p: function update(changed, ctx) {
			if ((changed.cats) && text_value !== (text_value = ctx.cat.name)) {
				text.data = text_value;
			}

			if ((changed.cats) && a_href_value !== (a_href_value = ctx.cat.video)) {
				a.href = a_href_value;
			}
		},

		d: function destroy(detach) {
			if (detach) {
				detachNode(li);
			}
		}
	};
}



Preact:

Скрытый текст
function Main({ cats }) {
  return h('ul', null, cats.map((cat) => (
    h('li', null, h('a', null, { target: '_blank', href: cat.video }, cat.name))
  ));
}



А вы зачем-то начали упоминать всякие бессмысленные бэнчмарки, которые традиционно связаны с кучей вранья. О каких-то сверх возможностях Svelte, которых нет в Preact/Inferno. О том что автор Svelte не понимает как разрабатывать производительные UI библиотеки. Не понимаю какое это всё имеет отношение к тому о чём я изначально написал и к теме этой статьи, в которой рассказывается о размере приложений.
А вообще, я лишь только хотел указать на небольшой недостаток Svelte, когда он в простом примере сгенерирует ~90 строк «оптимального» non-shareable кода.

На что я вам сразу четко ответил, что:
Не вижу ничего криминального в этих функциях. Довольно примитивные и понятные фукнции. В итоговом коде — это будут семки.


А вы зачем-то начали упоминать всякие бессмысленные бэнчмарки, которые традиционно связаны с кучей вранья.

Пожалуй с этим я частично согласен, но других у нас нет.
О каких-то сверх возможностях Svelte, которых нет в Preact/Inferno.

Ну так давайте разберемся в этих возможностях подробнее здесь. Я так и не долждался ваших уточнений.

Нет, не одной страницы. 40Кб это размер всего кода реализации на Svelte. Размер скриптов первой страницы занимает всего 12Кб. Откройте дев-консоль и посмотрите сами. Поэтому code-splitting тут вообще не причем.

Всё же не поленился, выкачал исходники, прочитал конфиги вебпака, собрал и посчитал сколько занимает всё приложение, нашёл коммент автора Svelte на эту тему https://twitter.com/Rich_Harris/status/948223658836799490 и всё что я говорил — подтвердилось, используется code splitting, учитывается размер только жаваскрипта который подгружается на одной странице. Не понимаю зачем нужно было врать о том что это размер всех кусков.

Не понял, что вы там откопали. То, что используется code splitting это и так говорилось. Зачем вам исходники также не ясно. Я вам толдучу уже которое сообщение, что даже если используется code splitting, это вовсе не значит, что нельзя сложить все приходящие скрипты и получить общий Transfer Size в Gzip.

Последовательность действий, для тех, кто в танке:

1) Открываем страницу: svelte-realworld.now.sh
2) Открываем дев-тулз и вкладку network
3) Наживаем там фильтр по JS
4) Перезагружаем страницу с отчисткой кэша и жесткой перезагрузкой.
5) Смотрим:



6) Если считать в уме не умеем, то берем калькулятор:
7.0Кб gzip (main.js) + 5.6Кб gzip (_.7.js) = 12.6Кб gzip
А, лол, ошибся :) После паковки у Svelte 40kb, забыл о том как `du` считает.

Но в любом случае размер реакта 78kb.

Там и функциональность не вся реализована.


Svelte:


Заголовок спойлера


Vue:


Заголовок спойлера

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

В той статье что-то не так с билдом React + Redux.


https://react-redux.realworld.io/main.js — gzipped 193KB (как на графике)


Я клонировал репозиторий и собрал:


File sizes after gzip:

76.46 KB build/static/js/main.79839d36.js

291 KB без сжатия


Так что вопрос к правильности и актуальности информации в этой статье

Наверное, прислали какой-нибудь pull-request с улучшениями (скорее всего, вот этот), а цифры в статье не обновились.

Сравнение не мое, поэтому отвечать за цифры я не буду. Вполне возможно, что информация как-то устарела. В любом случае, спасибо за внимательность.
UFO just landed and posted this here

В любом случае в Svelte нету этих 58кб. И если я прав то камень был в огрод React.


которую можно (и нужно) подгружать по мере необходимости через тот же requirejs

тут это не нужно

UFO just landed and posted this here
Как я понял, автор имеет в виду вес всей страницы целиком, не только скриптов. Далее, приводится мнение исследователя данной проблемы (Alex Russell), делается вывод, что скриптов должно быть не более 100Кб gzip.
Если не бояться компиляции, то почему не воспользоваться более серьезным языком, компилируемым в js?

Это дело вкуса. Лично я не считаю, что ES6 не серьёзный язык. И тут компиляция достаточно высокоуровневая что приводит к тому что компилятор крайне прост.

Нетипизированный язык не может быть серьезным.
Это как русский мат. Когда нужно быстро выразить малообдуманные инспирированные внезапными эмоциями мысли — это походит. Если цель — построить сложную и надежную логически непротиворичевую конструкцию — такой инструментарий жидковат.
Честно говоря, пишете глупости. Я, например, пришел в веб-разработку из C++ (правда это было более 8 лет назад), а уважаемый stalkerg до сих пор на C пишет, когда нужно. Мне иногда в JS не хватает опциональной статической типизации и очень надеюсь, что ее все же введут, но делать такие громкие утверждения, что язык не серьёзный я бы не стал. Особенно учитывая, что софт на JS скоро вам кофе варить будет.))))

Отвечая на изначальный вопрос, почему бы не использовать другой язык и компилировать его в JS, ответ простой — люди. Svelte позволяет использовать в работе наиболее стандартный веб-стек технологий, т.е. JS/HTML/CSS и это удобно, потому что все уже это умеют и никого не надо учить.

Svelte добавляет к этим знаниям лишь пару вещей — язык шаблонов, который состоит буквально из 4-5 конструкций и Single File Component — формат файла компонентов, который итак многие знают из Ractive, Riot и Vue.

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

Это не говорит о том, что на ES6 невозможно писать, да. Можно, конечно, но в «большой тройке», например, о которой вы так часто говорите, либо уже ушли от ваниллы (Angular и в некотором смысле React), либо жалеют, что не ушли (Vue).
Всё-таки её [статической типизации] пользу трудно переоценить)
В целом и на Vue можно писать используя TS, поэтому да, «тройка» дает возможность писать на этом диалекте.

Плюс это или минус? Однозначно плюс, чем больше возможностей тем лучше!

Считаю ли я, что все должны писать на TS, а фреймворки должны склонять к этому (привет Angular)? Однозначно нет!

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

Нравится TS? Ваше право, могу понять почему. На удивление это детеще MS зашло многим, но не нужно пытаться всех чесать под одну гребенку.
Я шучу, конечно же. Но в некоторых шутках достаточно выстраданной правды)
Софт на JS, к своему стыду, легко сварит мне вместо кофе чай или борщ, или чёртову бабушку на том простом основании, что ошибочно переданный на вход объект реализовал варящий метод.
Не все такое любят, видите ли. Но хипстеров с каждым годом в профессии всё больше.

Я больше 10 лет работал с Python и честно говоря проблем с типизацией почти не было и точно ни разу не было случая когда не тот тип падает в фукнцию. Это больше походит на страшилку от адептов статической типизации.
Вот с чем я реально сталкивался это с проблемами памяти особенно во многопоточных приложениях по этому Rust это очень классно. Но возможно у вас другой был опыт...

Я больше 10 лет работал с Python и честно говоря проблем с типизацией почти не было и точно ни разу не было случая когда не тот тип падает в фукнцию.

Дело в том, что сам процесс написания кода становится другим, это ощущается. С-но и код на динамическом языке получается с на порядок меньшим количеством ошибок типов. При использовании статики об этом просто не думаешь, т.к. знаешь, что компилятор все поправит.

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

Заинтересовался Svelte, прочитал их документацию, посмотрел что на выходе приходит в клиент с их сайта — не понимаю как в результатах тестов получилось 40 Кб (получается посчитаны только main.js + _7.js, хотя на самом деле скриптов тянется намного больше), если на выходе весь бандл всё-равно занимает ~140 Кб (http://joxi.ru/KAxXnG0CMZWwyA), или я ошибаюсь?


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


Линк с их тестовым приложением, если кому интересно: https://svelte-realworld.now.sh/ (взято отсюда)

А как вы интересно эти 140кб посчитали? Сложили размер всех бандлов из папки public ?)))))
Вы на глазок их в gzip архивируете?)))
40кб — это gzip'нутый размер всех чанков. И проблема в том что main.js + _7.js так же занимают ~40кб, поэтому легко ошибиться, особенно когда текущая реактовая gzip'нутая реализация весит ~78кб, а не ~193кб что создаётся впечатление о том что на этом графике демонстрируется какая-то чушь что начинаешь искать в каком варианте цифры более менее отражают то что нарисовано на этом графике.

Если откроете dev tools -> Network, то там в хидэрах ответов должно отображаться что отдаются gzip'нутые js'ки.


Но важно же понять то как эти цифры были посчитаны, когда рисовали этот график, а не то как сервер отдаёт. Можете просто запаковать все чанки gzip * и посчитать их размер, должно быть ~40kb.

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

Если вас устраивает "исчезающий фреймворк", то это значит лишь одно — вам вообще не нужен js фреймворк на клиенте и SPA в принципе. Достаточно просто отдавать страницы с сервера. Если же вам нужен клиентский рендеринг (с-но то, ради чего существуют SPA) то и "исчезающие фреймворки" использовать не выйдет, т.к. требуемый функционал по-просту отсутствует.
Аналогично, изоморфный рендеринг — если вы можете корректно рендерить приложение на сервере, то при чем тут SPA? Типичное SPA-приложение на сервере отрендерить просто невозможно (с разумными затратами, конечно).

Вы статью то читали? Или сразу в комментарии))))

Если вас устраивает «исчезающий фреймворк», то это значит лишь одно — вам вообще не нужен js фреймворк на клиенте и SPA в принципе.

«Исчезающий фреймворк» отличается от не исчезающего только тем, что последний вы тянете на клиент как есть, в полном объеме. А каждый, даже самый маленький кусочек вашего кода, будет завязан на весь фреймворк сразу. Исчезающий фреймворк оптимизирует состав результирующего кода так, что этот код решает только задачи вашего приложения. Поэтому, лично я не понимаю, как вы сделали вывод, что SPA в данном случае будет не нужен. Более того, все представленные в статье фреймворки — это именно SPA фреймворки.

Если же вам нужен клиентский рендеринг (с-но то, ради чего существуют SPA) то и «исчезающие фреймворки» использовать не выйдет, т.к. требуемый функционал по-просту отсутствует.

Нет, вы точно статью не читали… Как это отсутствует? Это основная часть их функционала, создание и обновление DOM в data-driven стиле и на основе компонентов.

Аналогично, изоморфный рендеринг — если вы можете корректно рендерить приложение на сервере, то при чем тут SPA?

А почему бы не рендерить приложение и на сервере и на клиенте? Особенно если это делает один и тот же код и нет никакого over-engineering. Как минимум это хорошо для SEO и для Progressive Enhancement.

Типичное SPA-приложение на сервере отрендерить просто невозможно (с разумными затратами, конечно).

Что? Когда мы говорим об SPA и фреймворках для SPA, в голову сразу приходят такие штуки как React, Vue и Angular. Все они умеет SSR из коробки, более того, без необходимости приспосабливать кодовую базу. Поэтому я не понимаю вашего «невозможно».


«Исчезающий фреймворк» отличается от не исчезающего только тем, что последний вы тянете на клиент как есть, в полном объеме.

Если вы можете не тянуть какую-то часть фреймворка, то, значит, вам не требуется тот функционал, что вы не тянете. Разве это не очевидно?


Нет, вы точно статью не читали… Как это отсутствует?

Потому что если бы он не отсутствовал, его бы пришлось тянуть с собой на клиент, правильно?


А почему бы не рендерить приложение и на сервере и на клиенте?

А зачем, если можно просто рендерить на сервере?


Особенно если это делает один и тот же код и нет никакого over-engineering.

Никакого оверинжиринга нет только в том случае, если приложение в принципе хорошо ложится на серверный рендеринг (то есть не-SPA по функциональности). Действительно — нет проблем отрендерить на клиенте то, что хорошо рендерится на сервере (именно по-этому в фейсбуке сделали реакт, изначально ведь это php-фреймворк для серверного рендеринга, который просто портировали на js, чтобы можно было использовать легаси php код на клиенте без архитектурных изменений).


Все они умеет SSR из коробки, более того, без необходимости приспосабливать кодовую базу. Поэтому я не понимаю вашего «невозможно».

Ну, в простых случаях (когда ваше приложение не-SPA де-факто) — да, умеют. Но тут вопрос, зачем вообще вы его сделали в виде SPA, если это вам нафиг не нужно?

Если вы можете не тянуть какую-то часть фреймворка, то, значит, вам не требуется тот функционал, что вы не тянете. Разве это не очевидно?

Потому что если бы он не отсутствовал, его бы пришлось тянуть с собой на клиент, правильно?

Я просто не понимаю, как для SPA может не требоваться функционал по созданию и обновлению DOM дерева? Это его основная функциональность и это не специфично для исчезающих или не исчезающих фреймворках. Другое дело, что все современные фреймворки, кроме этого умеют еще десяток вещей. И тут как раз разница проявляется, например, и Svelte и Vue, имеют функционал реактивных данных, вычисляемых свойств и кастомных ивентов. Если ваши компоненты Vue, используют только реактивные данные и не используют всего остального, то код, которых реализует эту фичи все равно будет тянуться на клиент, вместе с фреймворком. В Svelte же будет подтянут только ваш собственный код, а также небольшое кол-во хелперов, которые реализуют реактивные данные. Вычисляемые свойства, кастомные ивенты и другие фичи в бандл не попадут.

Никакого оверинжиринга нет только в том случае, если приложение в принципе хорошо ложится на серверный рендеринг (то есть не-SPA по функциональности). Действительно — нет проблем отрендерить на клиенте то, что хорошо рендерится на сервере (именно по-этому в фейсбуке сделали реакт, изначально ведь это php-фреймворк для серверного рендеринга, который просто портировали на js, чтобы можно было использовать легаси php код на клиенте без архитектурных изменений).

Ну, в простых случаях (когда ваше приложение не-SPA де-факто) — да, умеют.

Мне кажется тут у нас путаница в терминологии и представлениях о границах SPA. Мне представляется, что вы считаете, что SPA — это какие-то интерактивные приложения, аля десктоп, для работы с медиа, графикой, например чаты, видео-звонилки, редакторы графики и т.п. Все эти вещи плохо ложаться на SSR, тут вы правы. И есть действительно большая набор видов веб-приложений, для которых SSR, в принципе, ничего не дает.

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

Но тут вопрос, зачем вообще вы его сделали в виде SPA, если это вам нафиг не нужно?

SPA — это практически синоним клиентского-рендеринга, а сам по себе он очень полезен во многих случаях, прежде всего, чтобы экономить время и трафик пользователя. Зачем пререзагружать страницу, если надо обновить лишь часть интерфейса? А далее, зачем иметь шаблоны и на чисто серверном языке и на JS, если JS есть и там и там (вот вам и изоморфность подъехала).

В целом, сам термин SPA, подярком устарел, поэтому и путаница я так думаю.

И тут как раз разница проявляется, например, и Svelte и Vue, имеют функционал реактивных данных, вычисляемых свойств и кастомных ивентов.

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


Мне представляется, что вы считаете, что SPA ...

Да, именно так и считаю.


Однако же, термин SPA значительно шире. Более того, большинство SPA, которые сейчас пишутся, это всевозможные админки, контрольные панели, клиент-банки, короче говоря backoffice.

Я понимаю, что сейчас пишется. Речь как раз и идет о том, что все это, что сейчас пишется, оно прекрасно будет работать (да и прекрасно работало еще по сути несколько лет назад, чего уж там) без SPA-элементов. По-этому для таких задач вы можете взять какой-нибудь svelte, прикрутить, оно отрежет 90% функционала (и будет маленькое), будет легко рендериться на сервере (потому что чо там рендерить?), но смысл то тут в том, что в данном случае svelte или любой другой фреймворк тут в принципе как телеге пятое колесо, прикручено по принципу "а пусть будет, почему бы и нет?".


То есть, смотрите, вы сперва говорите "а пусть у меня будет SPA", тянете какую-то библиотеку для клиентского рендера, отрезаете от нее 90% потому что они вам не нужны и остаетесь с "почти исчезнувшей библиотекой". Мой тезис заключается в следующем — нафига это все? Зачем изначально было совершать первый шаг и делать SPA?


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

Проблема именно в том, чтобы были реактивные данные, вычисляемые свойства, кастомные эвенты и прочая, прочая, прочая. Если вам все это не надо — то вам и SPA не надо. Если же ваше приложение сложнее хеллоуворда, то все эти фичи будут нужны и они подтянутся.

Не согласен. Не для всех приложений нужны абсолютно все фичи. Не для всех приложений нужна обработка абсолютно всех пограничных кейсов. Результирующий код на основе фреймворка, такого как Vue, решает проблемы всех возможных приложений на Vue, результирующий код на Svelte решает только задачи вашего конкретно приложения. Мы используем Svelte около года в коммерческой разработке, совместно с Vue и Ractive, и по моему опыту это очень ощущается.

Да, именно так и считаю.

Что и отсылает нас к моему выводу из предыдущего комментария. SPA — стали слишком емким и уже устаревшим термином, который каждый использует как хочет.

Я понимаю, что сейчас пишется. Речь как раз и идет о том, что все это, что сейчас пишется, оно прекрасно будет работать (да и прекрасно работало еще по сути несколько лет назад, чего уж там) без SPA-элементов.

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

По-этому для таких задач вы можете взять какой-нибудь svelte, прикрутить, оно отрежет 90% функционала (и будет маленькое), будет легко рендериться на сервере (потому что чо там рендерить?), но смысл то тут в том, что в данном случае svelte или любой другой фреймворк тут в принципе как телеге пятое колесо, прикручено по принципу «а пусть будет, почему бы и нет?».

Нет, потому что мы хотим DRY и при этом, чтобы интерфейс или части интерфейса могли рендерится как на клиенте, так и на сервере.

Мой тезис заключается в следующем — нафига это все? Зачем изначально было совершать первый шаг и делать SPA?

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

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

С таким подходом, вы видимо в качестве фреймворка для SPA рассматриваете только Angular/Ember или, о боже, ExtJS?

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

Дык можете подгружать куски страницы аяксом, для этого никаких СПА-фреймворков не надо :)


С таким подходом, вы видимо в качестве фреймворка для SPA рассматриваете только Angular/Ember или, о боже, ExtJS?

Ну а что еще? Тот же реакт, как известно библиотека :)

Дык можете подгружать куски страницы аяксом, для этого никаких СПА-фреймворков не надо :)

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

Ну а что еще? Тот же реакт, как известно библиотека :)

Это демагогия на тему терминологии, уж простите :)
Ага, точно, юзер добавил товар в корзину и при этом в нескольких местах страницы должны произойти изменения. Ну там, счетчик увелится, в корзинке товар появиться как-то анимировано, в списке тоже пометка появится, что товар уже добавлен и т.п. Вы все эти кусочки HTML будете с сервера заново запрашивать?

А в чем вы видите проблему?

В чем я вижу проблему запрашивать n-е кол-во кусков HTML с сервера, вместо того, чтобы поменять одно значение на клиенте? Вы это так шутки шутите?
В чем я вижу проблему запрашивать n-е кол-во кусков HTML с сервера, вместо того, чтобы поменять одно значение на клиенте?

Так если вы поменяете значение на клиенте то ничего не произойдет, вам надо еще перерендерить вид. Что ничем не отличается от получения тех же кусков кода с сервера (что очевидно, ведь иначе SSR бы не мог работать ;)).

Не смотря на то, что у меня стойкое ощущение, что вы либо троллите меня, либо просто ничего не понимаете, я все равно отвечу.

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

А этим как раз занимается мой фреймворк. Вот как это примерно будет выглядеть на Svelte:

    this.push('cart.products', product);


Все, после этого все связанные данные, вычисляемые свойства и части HTML будут автоматически пересчитаны. Реактивность знаете ли.

Что ничем не отличается от получения тех же кусков кода с сервера

Очень даже отличается. Вы хоть представляете себе объем работы, который надо произвести, чтобы научить сервер отдельно отдавать html-сниипет 155-го товара на 8 странице с примененным фильтром и сортировкой и при этом его еще на клиенте в правильное место DOM вставить? Или вы предлагаете при добавлении в корзину весь список товаров перерендарить на сервере?

(что очевидно, ведь иначе SSR бы не мог работать ;)).

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

Ну а в случае серверсайда этим будет заниматься сервер. Какая разница? И там и там генерируется кусок dom (несколько кусков), который потом вставляется в нужное место страницы вместо старого куска.


Вы хоть представляете себе объем работы, который надо произвести, чтобы научить сервер отдельно отдавать html-сниипет 155-го товара на 8 странице с примененным фильтром и сортировкой и при этом его еще на клиенте в правильное место DOM вставить?

Нулевой примерно. Еесли у вас серверсайд рендеринг, то сервер уже умеет отдавать хтмл-сниппет 155-го товара на 8 странице с примененным фильтром (ну и да, зачем каждый товар отдельно-то? очевидно всю ленту товаров скопом отдавать). А если он не умеет, то как вы этот снипет на этой странице показываете?


Нет не очевидно, во время SSR не функционируют никакие экшены, типа добавления в корзину.

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

Ну а в случае серверсайда этим будет заниматься сервер. Какая разница? И там и там генерируется кусок dom (несколько кусков), который потом вставляется в нужное место страницы вместо старого куска.

Разница огромная))) Усложнение серверной части, усложнение клиентской части, накладные расходы на сеть, ухудшение UX и так далее. Если вы всего этого не понимаете, значит не троллите меня и я в вас ошибся.

Нулевой примерно. Еесли у вас серверсайд рендеринг, то сервер уже умеет отдавать хтмл-сниппет 155-го товара на 8 странице с примененным фильтром

Совершенно не обязательно, что умеет. Сервер должен уметь отдавать всю страницу в случае изоморфного приложения, а не по кускам. Это значительно упрощает серверную часть.
ну и да, зачем каждый товар отдельно-то? очевидно всю ленту товаров скопом отдавать).

Зачем, что быстрее обновить пару dom элементов, чем ходить на сервер, получать несколько Kb полностью готового html с товарами, которые даже не были изменены, и вставлять в DOM. Все это бред, знаете ли.

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

Конечно другое, SSR — это снимок некоторого статического состояния приложения, соответствующего некому запросу. SSR не умеет делать действия, анимации и тому подобное. Можно конечно на ajax-запрос на добавление товара, ответом присылать кусок html с обновленной корзиной, но это сложнее и работает только, если вы обновляете лишь корзину, а если обновления в DOM в несольких местах, то придется присылать несколько кусочков, держать знание от местах для вставки и еще кучу всего.

Короче это все не нужно, а если вы считаете по-другому, тогда давайте переходить к более конкретным кейсам, например сниипетам кода или хотя бы диаграммам взаимодействий. Пока то что вы говорите выглядит крайне не убедительно.
Разница огромная))) Усложнение серверной части,

Усложнение серверной части ЧЕМ, прошу прощения? Сервер и так может генерить все ваши страницы, иначе как вы их выводить собираетесь?


ухудшение UX и так далее.

Ухудшение UX за счет чего именно? В обоих случаях вы получаете данные и перерендериваете кусок страницы без перезагрузки, с-но, страницы.


Совершенно не обязательно, что умеет. Сервер должен уметь отдавать всю страницу в случае изоморфного приложения, а не по кускам.

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


Зачем, что быстрее обновить пару dom элементов, чем ходить на сервер, получать несколько Kb полностью готового html с товарами, которые даже не были изменены, и вставлять в DOM.

Быстрее для пользователя? Ничего. Он не заметит разницы. Другое дело, конечно, если вы не пару кб решили отдавать, а сотни или хотя бы десятки.


Короче это все не нужно

Не нужно что? Я требований не формулировал, это пока делали только вы.

Усложнение серверной части ЧЕМ, прошу прощения? Сервер и так может генерить все ваши страницы, иначе как вы их выводить собираетесь?

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

Ухудшение UX за счет чего именно? В обоих случаях вы получаете данные и перерендериваете кусок страницы без перезагрузки, с-но, страницы.

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

При чем тут изоморфное приложение, если мы обсуждаем классическую архитектуру?.

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

Сервер может генерить разметку для отдельных сниппетов?

В изоморфном подходе этого не требуется. То что вы говорите, это скорее в сторону «пиджак»-приложений из второй половины нулевых, когда на сервере был HMVC, а на клиента jquery + plax.
Ну, конечно, может (вы же не хотите сказать, что предлагаете весь сайт делать в виде одной большой портянки-шаблона, мм?).

Конечно нет, само приложение внутри разбито на компоненты, но это совершенно не значит, что сервер умеет отдавать каждый компонент отдельно. Это совершенно лишняя работа и не нужное усложнение.
Быстрее для пользователя? Ничего. Он не заметит разницы. Другое дело, конечно, если вы не пару кб решили отдавать, а сотни или хотя бы десятки.

Чем докажете? Что значит, пофиг, он не заметит. Может быть вы точно знаете какой у него девайс/интернет? Это крайне дилетантский подход.
Не нужно что? Я требований не формулировал, это пока делали только вы.

Вы просто никогда не делали такие приложения, либо делали, но так и не поняли как. А мне будет сложно вам объяснить. На самом деле это проще чем кажется и сервер даже не должен быть таким «умным» как вы расписываете тут. Совершенно не обязательно, чтобы он умел отдавать компоненты по отдельности и т.п.

Так как я люблю реальные веши, я вам напишу реальный кусок кода, который отличает отдно из мои изоморфных приложений от простого SPA. Это коротенькое express-middleware, вот ВЕСЬ его код:

const serialize = require('serialize-javascript');
const run = require('../src/app');

module.exports = () => (req, res, next) => {

	const app = run(),
	    route = app.$page.show(req.url);

	app.ready((error, data) => {

	    const meta = route.state.meta,
	        content = app.toHTML(),
		styles = app.toCSS();

            app.teardown();
		
	    data = serialize(data || {});
	
	    res.render('index', { 
                meta, 
                content, 
                styles, 
                data, 
                error 
            });
    });
};

Этот код превращает мой SPA в изоморфное приложение.

А какая разница с точки зрения SSR у изоморфного приложения и классического подхода?

Да никакого, но мы изначально сравнивали именно SPA с классическим вариантом, а не SSR с классическим вариантом (ну потому что SSR — это и есть "классический вариант", что тут сравнивать, извините?). А вы куда-то улетели в изоморфные дебри.

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

Давайте я напомню основные тезисы, которые привели к этому треду и кратко отвечу на них снова:

Если же вам нужен клиентский рендеринг (с-но то, ради чего существуют SPA) то и «исчезающие фреймворки» использовать не выйдет, т.к. требуемый функционал по-просту отсутствует.

Любой клиентский фреймворк имеет функционал по клиентскому рендерингу. «Исчезающие фреймворки» тоже имеют этот функционал, а также любой другой функционал, если конечно он вам нужен. Это выгодно отличает их от классических реализаций — тащим только то, что используем.

Аналогично, изоморфный рендеринг — если вы можете корректно рендерить приложение на сервере, то при чем тут SPA?

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

Типичное SPA-приложение на сервере отрендерить просто невозможно (с разумными затратами, конечно).

Очень даже возможно. Отличия чистого SPA от SPA + SSR минимальны, как я уже привел выше. Конечно же есть вещи, которые просто не могу работать во всех окружениях, потому что жестко завязаны на одном из них. Именно поэтому некоторые виды SPA рендерятся на сервере не полностью, а лишь частично. Никаких особых затрат при этом нет.

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

Нет, я специально ветку перечитал :)
Я говорил про SPA вс серверсайд и упомянул изоморфный рендеринг исключительно в контексте того, что если сервер ssr генерит, то значит может и в целом сам по себе все генерить, без клиентской части. А вы уже там зацепились за это упоминание, хотя разговор был в целом не о том.

Я вам еще раз кратко ответил на все ваши заблуждения из начального комментария. Если вы не понимаете пользу клиентского рендеринга, я тут ничего больше сделать не смогу.

Я понимаю, какую он приносит пользу в пирнципе. Я не понимаю, какую он приносит пользу там, где он не нужен.

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

Не обобщайте. Есть современные фреймворки построенные не по монолитному, а по микромодульному принципу, где в бандл попадают только фактически используемые модули.

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

Давайте уж учтем, что где как и что в бандл попадает — это вообще не свойство фреймворка, это свойство в общем js-инфраструктуры.

Это не совсем так. То что вы и vintage говорите, относится только к импортируемым модулям. То есть фактически tree-shaking, но это не будет работать для таких вот вещей, например:

<input ref:input>

<script>
   export default {
       oncreate() {
           const input = this.refs.input;
           // do something
       }
   };
</script>


С помощью статического анализа, Svelte поймет что вы используете ref'ки и сгенерит нужный код.
Какой код он сгенерирует? Подключит какой-то хелпер? Это и есть подключение модуля, «то есть фактически tree-shaking». Или нагенерирует копипасты, вместо того, чтобы вынести её в обобщённый код?
Это и есть подключение модуля, «то есть фактически tree-shaking».

По-сути да, и на самом деле не суть важно, как именно это обыграно, через import или даже генерацией куска кода. Вопрос в другом, что фреймворк без статического анализатора, но с tree-shaking через rollup/webpack просто не сможет распознать используете вы реально эту фичу или нет.
$mol круче всех! Ура, $mol!

p/s Надеюсь я потешил ваше эго и мы сможем продолжить общение по сабжу.

Давайте попробую объяснить по-своему.


Если вы можете не тянуть какую-то часть фреймворка, то, значит, вам не требуется тот функционал, что вы не тянете. Разве это не очевидно?

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


Svelte проводит статический анализ вашего кода, чтобы собрать в рантайм только те фичи, что вам нужны. (Я сам Svelte не пробовал, но судя по объяснениям в разных статьях, это так).


Но тут вопрос, зачем вообще вы его сделали в виде SPA, если это вам нафиг не нужно?

В SPA проще управлять состоянием элементов на странице. Например есть сайт VK, рендерится на сервере, обновляется через Ajax. Регулярно возникают проблемы с синхронизацией текущего проигрываемого трека в шапке сайта и в теле страницы. Аналогично, в списке слева остается фантомный счетчик сообщений (+1), хотя сообщение уже было прочитано.


С SPA подходом такая проблема не случится в принципе. Все данные для UI берутся с одного источника, неконсистентности не возникет.

С SPA подходом такая проблема не случится в принципе. Все данные для UI берутся с одного источника, неконсистентности не возникет.

Во-первых, то, что все данные берутся из одного источника, никакого отношения к СПА не имеет. Во-вторых — как раз старый подход с рендером на сервере предполагал дефолтное "single source of truth", на клиентсайд он проник с появлением реакто-редакса, который являлся как раз портированием серверного flow на клиент.


Svelte проводит статический анализ вашего кода, чтобы собрать в рантайм только те фичи, что вам нужны. (Я сам Svelte не пробовал, но судя по объяснениям в разных статьях, это так).

Ну так еще раз, чтобы что-то вырезать, это что-то должно быть вам не нужно. Речь надо вести не о том, что "фреймворк исчезающий", а о том, что для 99% того, что сейчас называется "SPA" в общем-то тот функционал, который под SPA изначально подразумевался и под который затачивались SPA-фреймворки не требуется. Ну да, не нужен вам ангуляр, чтобы написать гостевую книгу.

как раз старый подход с рендером на сервере предполагал дефолтное "single source of truth", на клиентсайд он проник с появлением реакто-редакса, который являлся как раз портированием серверного flow на клиент.

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

Всё же не стоит путать единственный источник истины и хранение всего состояния в одной корзине.

Так я и не путаю. На сервере у вас одна "корзина" — это бд, но ее желательно держать в по возможности нормализованном виде, что как раз и исключает дублирование, то есть соответствует single source of truth. На самом деле и редакс-то как таковой в виде single source of truth работает только при нормализации состояния, а иначе ну будет у вас один глобальный стор, но если при этом данные там дублируются, то вы сами себе будете злобный буратина, если не сможете их потом нормально синхронизировать.

Да нет, путаете. У каждого компонента, элемента, узла, есть некоторое состояние. И далеко не все из них нужно/возможно задавать в глобальной помойке. Хоть в нормализованном виде, хоть нет. Например, виджет "таббар" может сам себе являться источником истины о том, какой таб сейчас выбран.

У каждого компонента, элемента, узла, есть некоторое состояние. И далеко не все из них нужно/возможно задавать в глобальной помойке.

А кто говорит, что нужно?


Например, виджет "таббар" может сам себе являться источником истины о том, какой таб сейчас выбран.

И, т.о., ваше состояние нормализовано и соответствует single source of truth. А если у вас есть какой-то другой компонент, в котором тоже есть информация о выбранном таббаре — то состояние ненормализовано и нарушает single source of truth.

Если второе реактивно зависит от первого, то не нарушает.
Если второе реактивно зависит от первого, то не нарушает.

Если второе реактивно зависит от первого то состояние остается нормализованным, т.к. второе нельзя изменить независимо от первого.

К чему тогда ваше упоминание баз данных и редукса? SSoT с ними никак не связан. Это ортогональные вещи.

Я вообще-то отвечал человеку на тезис о том, что "спа про SSoT". Про SSoT не спа, а редакс, с другой стороны, классический подход с рендером на сервере — тоже про SSoT.

Про "single source of truth" уже ответили, отвечу на вторую часть


Ну так еще раз, чтобы что-то вырезать, это что-то должно быть вам не нужно.

Если это не нужно в этом конкретном проекте, этого не достаточно, чтобы заявить "У вас не полноценное SPA".


Например ref-ы из моего оригинального коммента: если ваше приложение их не использует, это значит, что ему не нужно это API, не более того.


Еще примеры (тоже из React, его API я лучше знаю)


  • ReactDOM.createPortal. Используется для рендеринга модальных диалогов. Нет диалогов — не SPA, так что ли?
  • ReactClass.getDerivedStateFromProps — используется для специальных вычислений состояния. Нет вычислений — не SPA?

SPA скорее определяется рендерингом и роутингом на клиенте, чем (не) использованием каких-то фич.

Если это не нужно в этом конкретном проекте, этого не достаточно, чтобы заявить "У вас не полноценное SPA".

Если вам не нужны некоторые вещи, то конечно не достаточно. Но на некоторых вещах и экономии никакой не будет. Если же вам не нужно 90% фреймворка — то это уже другой разговор, согласитесь?

Я соглашусь с тем, что если удаляется основная часть (рендеринг HTML из JSON), то такой фреймворк изначально брать не стоит.


Но какая это будет доля в процентах — неважно. Фреймворк может быть очень навороченным, и если ядро рендеринга составит меньше 10% кода, это нормально.


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

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

И в итоге вы получаете большой бандл со всеми фичами, так?


Я как бы веду к тому, что тут дело не во фреймворках. Дело в том, что 99% приложений функционал большей части спа-фреймворков не используют. Не надо оно какой-нибудь гостевухе вроде твиттера, вот и не используют. Ну и, с-но? При чем тут "исчезающие фреймворки"? При чем тут вообще фреймворки если суть вся в потребностях?

Суть в эластичности.


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


А если писать на эластичном фреймворке, который не сильно усложняет все на старте и растет вместе с вами, то переписывания можно избежать.

А если писать на эластичном фреймворке, который не сильно усложняет все на старте и растет вместе с вами, то переписывания можно избежать.

Согласитесь, что лучше раньше переписать с jquery, чем позже с какого-нибудь svelte.

Да, что у разработчиков есть большой опыт миграции с jQuery на SPA фреймворки. Но это не значит, что этот опыт хороший, и его хочется повторять снова и снова.

А при переписывании со svelte опыт хороший, значит? Или вы исходите из того, что с jquery он уж точно плохой (потому что пробовали), а со svelte, может, и ок (несмотря на то, что портировать придется по факту больше)?.

Что в Svelte, что в React рендер описывается декларативно, есть понятие UI-компонентов. Почему вы считаете, что портировать придётся больше?


Я, например, недавно переписал одну штуку с Vue на React. Это было легко и быстро. Подозреваю, что со Svelte будет не хуже

Что в Svelte, что в React рендер описывается декларативно, есть понятие UI-компонентов. Почему вы считаете, что портировать придётся больше?

А если не на реакт? Если реакт и свелте такие одинаковые, то зачем тогда брать свелте, если можно сразу брать реакт?

Зачем брать React если можно сразу брать Svelte?

Очевидно, что если вы сразу возьмете реакт, то вам не придется переписывать со свелте на реакт впоследствии (пусть это и "легко и быстро" как сказали выше).

Очевидно, что если вы сразу возьмете свелте, то вам не придется переписывать с реакт на свелте впоследствии. Хотя это реально легко и быстро)))

А зачем переписывать с реакт на свелте, если потребность может возникнуть только в обратном переписывании?

UFO just landed and posted this here
1) отдать клиенту готовую отреднеренную страничку, чтобы он мог видеть не пустой экран и не ждать пока с сервера все подтянется и 2) отдавать веб-краулеру любимую и понятную для него готовую статику.

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

UFO just landed and posted this here
Этот подход практикуют все кто делает SPA

Не все, не обобщайте. Типичные проблемы вашего подхода:


  1. Задержка выдачи html (и как следствие остальных ресурсов), невозможность его закешировать.
  2. Долгая выдача html, а зачастую скрипты ждут полной загрузки html для инициализации, даже если они взяты из кеша.
  3. Лишний трафик, замедление полной загрузки (отрендеренный html весит много больше json с данными, а json с данными так или иначе всё-равно придётся дополнительно загрузить).
  4. Пока скрипты не прогрузятся приложение в лучшем случае не работает, а в худшем срабатывают noscript фолбэки, что негатива даёт больше, чем профит от обмана пользователя "быстрым" показом картинки.

Проблему долгой загрузки нужно решать с другого конца — просто не грузить клиенту 10мб скриптов, чтобы показать простенькую страничку из шапки и одной формы.

UFO just landed and posted this here
Ощущение, что люди что-то слышали где-то, что-то не так поняли и из-за пробелов в понимании назначения и механизма начинают клеймить, а это непрофессионально и неправильно.

Да не, вы просто не в курсе с кем беседуете! Это же сам Карловский! Создатель самого лучшего, быстрого и оптимального в мире фреймворка $mol. У которого только один минус — им никто не пользуется и никогда не будет. В остальном он прекрасен!

p/s

vintage Несмотря на то, что я немного подтруниваю, ваш доклад на РИТ++ в том году мне понравился. )))) Просто хотелось бы хотя бы одну статью о JS фреймворках и без $mol. Уверяю вас, вы уже приложили все усилия, чтобы рассказать всему Хабру о нем.
UFO just landed and posted this here
первые два пункта убивает ssr caching, если это вообще надо, никакой долгой выдачи изначально нет, наоборот

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


это компромисс между передачей одной лишней html-кой только при первом посещении сайта и лучшими user experience

Не при первом посещении, а при открытии каждой новой вкладки. Берём первый попавшийся сайт с SSR: https://nextjs.org/docs/


Что мы видим (все цифры с учётом зипования на Slow 3G):


  1. Объём html: 25KB ~ 2.5s
  2. Чтобы заработала менюшка ждём загрузки скриптов (которые включают в себя и данные, которые уже есть в html): 150KB ~ 7s

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


Ладно, берём сопоставимое приложение без SSR, но на микромодулях: http://mol.js.org/app/slides/


Что мы видим:


  1. Объём html: 1KB ~ 2s
  2. Скрипты + стили: 30КБ ~ 3s
  3. Промежуточный редирект не учитываем — это особенности халявного гитхаба.
  4. Собственно контент (я замерял, объём текста тот же): 15KB ~ 2.5s

Итого: Через 5 секунд приложение полностью работоспособно и показывает анимацию. Ещё через пару уже загружен контент.


Ок, это первый заход на сайт, давайте зайдём снова в предположении, что статика уже закешировалась:


  1. SSR: 2.5 секунды любуемся пустым экраном пока грузится html, остальное всё достаётся из кеша.
  2. Без SSR: Приложение мгновенно поднимается из кеша и 2 секунды развлекает пользователя анимацией, пока грузится новый контент. А то и сразу же показывает закешированный контент, грузя обновление в фоне.

conversion rate

В этом показателе слишком много маркетинга и слишком мало научного метода.


пригодности сайта для нормального анализа краулерами

https://prerender.io/


в худшем случае если юзер кликнет по ссылке просто придется подождать загрузки дольше чем при полностью загруженном SPA.

А вы попробуйте с примером выше. Кликаешь — урл меняется, но ничего не происходит. Всё догрузилось — урл меняется обратно. Только после этого меню начинает работать. Особенно весело по таким сайтам тыкаться при нестабильном интернете.

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
Задержка выдачи html (и как следствие остальных ресурсов), невозможность его закешировать.

С чего бы это? Вы про браузерный кэш или на стороне сервера?

Долгая выдача html, а зачастую скрипты ждут полной загрузки html для инициализации, даже если они взяты из кеша.

Чуть более чем полностью, зависит от реализации.

Лишний трафик, замедление полной загрузки (отрендеренный html весит много больше json с данными, а json с данными так или иначе всё-равно придётся дополнительно загрузить).

Только для синхронных запросов, но есть и свои плюсы: SEO и progressive enhancement. И данные никто дополнительно не грузит, их кидают туда же на страницу, но уже после основного html.

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

Чуть более чем полностью, зависит от реализации. Переходы по ссылкам и сабмиты форм без JS еще никто не выпилил из браузеров.

Проблему долгой загрузки нужно решать с другого конца — просто не грузить клиенту 10мб скриптов, чтобы показать простенькую страничку из шапки и одной формы.

Именно этим из занимаются фреймворки из сабжа.

Вы про браузерный кэш или на стороне сервера?

Браузерный, конечно.

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

Насчет интерактивности, я тут частично согласен, но изоморфностью как раз решает эту проблему. Так как благодаря этому, вы без дублирования кода, вполне можете игнорировать часть рендеринга на сервере и грузить эту, высокодинамичную часть, только на клиенте. Например, у вас есть страница с кучей контента и сбоку онлайн чат. Никто не мешает делаеть SSR лишь для контента, а чат подхватывать на клиенте. Без изоморфности это делалось бы несколько более заморочено. Лично я для этого использую супер простой подход — «ожидания»:

// этот кусок данных будет рендерится на сервере
const contents = api.get('/contents');
this.wait(contents);

// а этот только на клиенте, потому что не добавлен в "ожидания"
const chat =  api.get('/chat');


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

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

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

Ну а то, что часть можно рендерить на клиенте, — ну так и вообще всё можно рендерить на клиенте.

Итогда нельзя. Иногда нужно SEO/SMO, клиенты не юзают JS и т.п. И я бы еще понял, если для SSR нужно было бы делать хоть какие-то усилия, но ведь это не так. Вот смотрите мое приложение с SSR:

server.use(app());

А вот оно же, но чисто SPA:
// server.use(app());


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

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

Это и есть ревалидация. И если вы делаете её для точки входа (html), то пользователь видит пустоту. В зависимости от канала связи, это может занять несколько секунд.

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

В одном случае человек видит несколько секунд белый экран, а в другом не видит. О чём тут можно спорить?
Например, о SEO/SMM, о клиентах без JS или нестабильным соединением, которое дропает загрузку скриптов. Да много о чем можно тут спорить. В одном случае, гипотетическая возможность подождать ревалидацию, в другом просто белая страница, без признаков жизни.

Считаете, что подход SPA единственный верный? Ваше право заблуждаться так, как вашей душе угодно.
Так можно просто рендерить на сервере, раз требования это позволяют, и не выеживаться.

Встречный вопрос: А зачем рендерить только на сервере, если можно и на клиенте? ;-)
Sign up to leave a comment.

Articles