Pull to refresh

Comments 212

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

Благодарю за критику, замечу, что это всё же перевод. Вам не нравится сам стиль речи автора и моего перевода, или то, что опять часть статьи посвящена противопоставлению Svelte и React?

Думаю стиль автора, но раз вы перевели, то солидарны.
А сравнение выглядит как jQuery vs React, которое большей частью бессмысленно, разные вещи. Показывайте профит, если он есть, без поливания грязью упоминания "конкурентов" и все ок будет.

К сожалению, все кто пытаются рассказывать про Svelte, в той или иной степени опираются на сравнение с традиционными фреймворками. Иначе просто не ответить на вопрос — "А зачем нам ещё один фреймворк?" То, что сравнивают в основном с React, лишь говорит о его популярности и известности. По-моему, заголовок статьи вполне хорошо раскрыт и без излишних оскорблений React в этой области.

К сожалению, все кто пытаются рассказывать про <tech_name>, в той или иной степени опираются на сравнение с традиционными <alt_tech_name>.

Это заблуждение. Ответить на вопрос можно показав результаты бенчмарков или удобство конкретного подхода к задаче. Ну и конечно же рассказав про подводные камни. Без всего этого — это просто публицистика.


Вот пример статьи которая как раз хорошо рассказывает про технологию и рассказчик достаточно прошарен в ней, чтобы не брать конкретные примеры, а оперировать разными подходами и идеологиями из других языков не прибегая к самим яп: Знакомство с Python для камрадов, переросших «язык A vs. язык B» и другие предрассудки.

UFO just landed and posted this here
Т.е. вам нужны «бенчмарки» без сравнения с с традиционными <alt_tech_name>. Или в чём заблуждение?

Для меня есть 2 вида статей о технологии:


  1. A vs B — в таких статьях обязательный бенчмарки и статистика сколько технологии лет, сколько пакетов, какое сообщество. То есть нормальное сравнение. Если тупо бенчей нет => публицистика.
  2. A only — в таких статьях показывается подход к задаче конкретно с помощью этой технологии. Описываются все плюсы и все минусы. Если начинают приплетать сравнение с другими подходами => публицистика.
  3. Публицистика — всё как в добрых старых рекламах: "Мы круче всех, но доказывать мы это не будем, потому что можете сами придти и попробовать. А ваш приход в сообщество резко поднимет нам количество людей в сообществе на 100%" Обычно в таких "статейках" начинают оперировать мнимым удобством на спичках при этом вообще не показывая минусов.

Если кратко, то вы не увидели союза "или" в моём высказывании.

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

В данной статье эти пара абзацев про разное количество строк кода отнюдь не главная мысль. Похоливарить на эту тему можно в предыдущей статье авторства Rich Harris.

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


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

Аргументация про реактивное программирование проседает?


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

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

Я не считаю, что она проседает — поверхностна, да. Но цели углубляться в эту тему в этой статье не было. Для меня структура компонентов Svelte3 сильно лаконичнее и понятнее, чем у любого другого фреймворка. Вот интересно, если бы отписался кто-нибудь, кто не трогал ещё ни Svelte, ни другие топовые фреймворки, со времён JQuery. Какой код ему понятнее?


Если хотите прямо фактов — напишите свой канонически верный вариант на React и посчитаем символы, а не строки. Всё равно букв у вас будет больше, как ни старайтесь. Но, что это докажет вам или мне?


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

кто не трогал ещё ни Svelte, ни другие топовые фреймворки, со времён JQuery. Какой код ему понятнее?

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

UFO just landed and posted this here
Реактивное программирование в Svelte и без этой статью вызывает вопросы. Вроде и понятно почему так (в JS нельзя узнать, что метод мутирует объект). Но все равно неприятно и можно пропустить. В проде народ что-то типа ImmutableJS использует?

Насколько я видел, кто работает со Svelte предпочитают решать эту проблему явным присваиванием. Например array.push(3) пишут как array = [...array,3]. Но я не вижу причин, почему бы не использовать ImmutableJS для этого, если кому-то так удобнее.

UFO just landed and posted this here

Так ведь суть ImmutableJS — что он предлагает неизменяемые объекты? Т.е. все преобразования выдают новый объект, который уже можно присвоить через =.


const { Map } = require('immutable');
const map1 = Map({ a: 1, b: 2, c: 3 });
const map2 = map1.set('b', 50);
map1.get('b') + " vs. " + map2.get('b'); // 2 vs. 50
UFO just landed and posted this here

Почему вам в таком случае "стрёмен" не сам svelte, а использование ImmutableJS в нём?

UFO just landed and posted this here

Исчезающий убийца реакта

В js есть прокси, это убирает проблему setState, разработчики не хотели их вводить из за обратной совместимости, почему в Babel нет я уже и не найду. Замена кода на комп лятор в js похожа на золотой унитаз и сводит на снова в дискуссию компиляторы Vs джиты, где как известно победит aot, и окажет мы, что мы говорим о профилях кода. Ну и к вопросу dom, тоже не совсем понятно надо ли, я думаю, что нет. Компиляторы или интерпретатор должен решать проблемы кода а не тулза. Так что выбирая, лучше улучшать последний а не пытаться развернуть поудобней граф исполнения, а в крайности вообще лучше все в васм перевести да и делов

Почему Svelte постоянно сравнению с React? Я когда вижу в статьях код написанный на Svelte, не сразу отличаю его от Angular и Vue.

Совсем не так. В прошлой статье было сравнение и с Vue тоже. Да и на Youtube есть пара видео.

Почему автор Svelte не добавляет к сравнению Angular с включенной AOT компиляцией и onPush для всех компонентов (желательно еще с отключенныйми zones, от этого костыля Angular собирается уходить постепенно)?
Думаю по нескольким причинам.

Во-первых, Angular играет в другой лиге. Все же это Application Framework, поэтому имеет смысл сравнивать его, например, с Ember. Svelte, React и Vue — это UI фреймворки.

Во-вторых, AoT компиляция в Angular работает только для шаблонов. В итоге компоненты все равно зависят от общего Angular core и не являются полностью stand-alone.

В-третьих, подобное сравнение уже проводилось, когда только были заявлены прекрасные характеристики Ivy. В итоге, сравнение показало что сравнивать бесполезно.
В-третьих, подобное сравнение уже проводилось, когда только были заявлены прекрасные характеристики Ivy. В итоге, сравнение показало что сравнивать бесполезно.
В одном случае он сравнивает по скорости, а в другом по размеру, это не серьезно. Хотя чего можно было ожидать в свитере кроме троллинга.
Сначала вы недовольны тем, что таких сравнений нет. Потом вам присылают что есть, вы недовольны тем что есть. Если вы лучше представляете как нужно произвести сравнение — сделайте его! Будет интересно, тем более что Ivy и Svelte сильно обновились с того времени.
Вы это серьезно? Совсем нет разницы?

<template>
  <div>
    <h1 style="color:red">Hello {{ name }}!</h1>
    <input v-model="name">
    <hr>

    <button v-if="count < 10" @click="count++">
      Clicks {{ count }}
    </button>
    <div v-else>
      <p>Clicks limit overcome</p>
      <button @click="count=0">Drop</button>
    </div>
  </div>
</template>


<h1 style="color:red">Hello {{ name }}!</h1>
<input [(value)]="name">
<hr>

<button *ngIf="count < 10; else elseBlock" (click)="count = count + 1">
  Clicks {{ count }}
</button>
<ng-template #elseBlock>
  <p>Clicks limit overcome</p>
  <button (click)="count=0">Drop</button>
</ng-template>


<h1 style="color:red">Hello {name}!</h1>
<input bind:value={name}>
<hr>

{#if count < 10}
  <button on:click={e => count++}>
    Clicks {count}
  </button>
{:else}
  <p>Clicks limit overcome</p>
  <button on:click={e => count=0}>Drop</button>
{/if}
<h1 style="color:red">Hello {{ name }}!</h1>
<h1 style="color:red">Hello {{ name }}!</h1>
<h1 style="color:red">Hello {name}!</h1>

<input v-model="name">
<input [(value)]="name">
<input bind:value={name}>

<button v-if="count < 10" @click="count++">
<button *ngIf="count < 10; else elseBlock" (click)="count = count + 1">
{#if count < 10} <button on:click={e => count++}>

<div v-else>
<ng-template #elseBlock>
{:else}


Для Вас это действительно принципиальная разница?
Для меня разница очевидна, а что для вас будет разницей тогда?

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

А давайте говорить конкретно, а не абстрактно? Приведите пожалуйста пример «другого подхода» на примере чего-то реального и существующего?

В давние времена приходилось все делать руками, из js лесть в DOM искать нужный элемент и при изменении состояния менять его или создавать новые элементы. Сейчас все это на себя берут Angular/Vue/React. Вот между этими подходами огромная разница. А разница между тем как написать :if или *ngIf уже не существенна лично для меня

Вы тут говорите о принципе построения веб-приложений, а именно event-based approach и state-based approach. Но изначальный комментарий был именно о характере кода. То что вы не можете отличить React/Vue/Angular/Svelte лишь говорит о том, что опыта использования этих фреймворков у вас не очень много. Я прекрасно вижу как отличия в коде, так и особенности использования.
Вы тут говорите о принципе построения веб-приложений, а именно event-based approach и state-based approach

Да, это два принципиально разные подходы, об этом я и говорю, что Svelte никак принципиально не меняет разработку по сравнению с Vue
То что вы не можете отличить React/Vue/Angular/Svelte лишь говорит о том, что опыта использования этих фреймворков у вас не очень много

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

Да, все это UI фреймворки основанные на компонентном подходе и state-based моделе управления. Собственно сейчас это практически стандарт для фронтенда.

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

Сами писали, что не сразу их отличаете:

когда вижу в статьях код написанный на Svelte, не сразу отличаю его от Angular и Vue.

React с его jsx — другой подход.
Knockout, где все запихнули в data-bind — тоже не совсем такой же.
Ещё есть jquery templates, которые выглядят похоже — но основаны не на DOM, а на строковых подстановках со всеми вытекающими особенностями.

Если рассуждать как andreyiq то все это одно и тоже. Вот jquery/mootools — это другой подход, а всякие там ваши ангуляры-реакты — одно и тоже.

А если в процессе работы программы привязка стала не нужна?

Подробнее можете описать задачу?
У меня нет конкретной задачи (точнее, она из другой области — не Web).
Если структура проекта (связи между компонентами) — динамические.
Сейчас компоненты и связь между ними есть, а через какое-то время — «ведомый» компонент (тот, который получает оповещения об изменении свойств) — удаляется. Или просто — его больше не надо оповещать. Структура проекта изменилась.

В скомпилированном проекте такое возможно?
Если компонент уделяется, то все его подписки подчищаются. Это вообще не зависит от компиляции Svelte. Компиляция лишь решает утилитарные задачи и выносит часть вычислений из рантайма.
UFO just landed and posted this here

Автор не ставил целью сравнить все фреймворки в очередной раз. Автор пытался объяснить механизм работы реактивности в Svelte — что для неё не нужны какие-либо чужеродные конструкции, а только то, что есть в самом Javascript.


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

UFO just landed and posted this here

Вы совершенно правы. Можно назвать это Sveltescrypt. С $ это просто сахар, который легко запомнить и использовать. Но синтаксис сам по себе — всё еще валидный JS, и шаблоны проектирования остаются те же. Хотите переменную стейта — просто пишите let var — как вы делаете для создания обычных переменных Javascript, а не используете "чужеродную конструкцию" для этого.

UFO just landed and posted this here

JS не валидный, синтаксис валидный.

UFO just landed and posted this here

Скорее всего это сделано, чтобы имеющийся туллинг для Javascript был готов из коробки, например подсветка синтаксиса на Хабре.
Кроме того — реактивные выражения в Svelte — это не обязательно только присваивание. Можно сделать реактивным любое выражение и даже целый блок:


let varA = 0;
$: {
    console.log(varA);
    console.log(varA*2);
}
// В консоли будут показываться новые значения, всякий раз, когда изменится varA
UFO just landed and posted this here
Отсюда возникает и второй вопрос: почему разработчики гуляют по тем же самым граблям?

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

UFO just landed and posted this here
Ок, вернёмся к нашим баранам.

Ну, не весь имеющийся туллинг же, а по синтаксису. Поэтому для Svelte с первых версий сразу была годная подсветка синтаксиса и притир в любой IDE(особенно, когда компоненты были в *.html файлах ещё). Иначе, в комментариях к статьям про Svelte, только и делали бы, что жаловались на невозможность писать на Svelte где бы то ни было. Сейчас уже экосистема потихоньку обрастает. Есть плагин и для того же ESLint.


Смысл в том, что Svelte — это языки, которые вы уже знаете. HTML, CSS и JS. Т.е. если вы знакомы с этими языками — вы уже знаете 90% Svelte. В каждый из этих языков добавлено немного магии — на изучение которой хватит 15 минут чтения учебника на сайте.

UFO just landed and posted this here

В принципе эта проблема решаема. К примеру для jsx-control-statements есть плагин для eslint. Правда я не уверен, что кто-то делал это для Svelte.

UFO just landed and posted this here

Хе-хе, ну есть же динозавры, у которых не линтеров, ни подсветки синтаксиса, ни прочих удобств. У них тулинг "всегда готов" как пионер.


А если серьёзно, то всегда остаётся какая-нибудь Jet Brains (ну или аналог) со своими парсерами, анализаторами и прочим. Проблема тулинга полноценно решается только для очень крупных игроков (скажем поддержка JSX есть уже в каждой кофемолке). А для несколько менее популярного Vue только пол пути пройдено.


Вот из недавнего — prettier не умеет в новый pipe-operator в smart виде. Очень удобная штука, но пришлось от неё отказаться :(

Вы путаете, там написано было бы:

$: value = 123
UFO just landed and posted this here
Ну вот у вас в первом скрипте уже не валидный JS:
let secondNumber = square(firstNumber);
let firstNumber = 42;


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

Интересный факт — это самая важная часть, которую можно противопоставлять существующим фреймворкам типа Реакта. Всё остальное (включая синтаксис и кол-во строк кода) — сильно вторично.

Супер, спасибо.
Swap Rows прям подозрительно подозрительный. Может потому, что по факту никто не свапит именно строки? Проще на месте одной зарендерить контент второй, и на второй контент первой, не переставляя строки.

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

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

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


Синтетические тесты имеют смысл для сравнения и именно для этого они и существуют.
Естественно, тест на рендеринг 1000 строк никак не отобразится на реальном проекте с 1000 строк, но даст возможность оценить выигрыш перехода от одной технологии к другой. Поскольку просто так (из-за синтаксиса) никто технологии не меняет. Меняют тогда, когда с используемой технологией возникают сложности (как-то с производительностью и эффективностью используемой памяти). Работая с реактом с проектом в котором десятки тысяч строк и около сотни тысяч дом элементов (да, мы используем переиспользование строк (react-virtualize), но это скорее костыль, чем решение), мне этот вопрос куда более интересен, чем синтаксис.

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

Речь именно о другом подходе, а подобные бенчмарки — это как раз и есть микрооптимизации.

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

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

Поскольку просто так (из-за синтаксиса) никто технологии не меняет. Меняют тогда, когда с используемой технологией возникают сложности (как-то с производительностью и эффективностью используемой памяти).

Именно так.

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

Что с TypeScript? Не сыграет ли со Svetle злую шутку то, что Svetle — компилятор? Ведь писать на чистом JS в 2019 году несколько некомфортно, а TypeScript уже чертовски хорош и улучшается семимильными шагами.

… я к тому, что в React с TypeScript все замечательно — строгая типизация, вывод типов, GraphQL, поддержка в IDE и т.д.

Что-то на эту тему делается силами сообщества потихоньку.

Ведь писать на чистом JS в 2019 году несколько некомфортн

Многие пишут и им комфортно. Более того, удивляюсь насколько TS популярнее в РФ, чем за рубежом.
> Если вы не сообщите React, что данные изменились (вызвав this.setState или эквивалентный хук), виртуальный DOM не изменится, и от React не последует никакой реакции (та-дам! ).

Тоже самое будет, если не указать $: в Svelte.

> Представьте, что вы только начали изучать веб-разработку. Какой код был бы для вас менее понятен? Тот, что слева, или тот, который справа?

А если не только начали и работаете в команде? Какой код будет более понятен без чтения доп мануалов?

Ну и отсутствие typescript, конечно, огромный минус…
Тоже самое будет, если не указать $: в Svelte.

Не совсем то же самое. $: просто назначает следующее за ним выражение быть реактивным — по сути это destiny operator. Кроме него есть ещё переменные стейта let somevar;. Тут вообще ничего не надо делать, чтобы при изменении через присваивание их значения отображались на вьюшке. А this.setState вы обязаны вызывать каждый раз, когда собираетесь изменить данные.


А если не только начали и работаете в команде? Какой код будет более понятен без чтения доп мануалов?

А если команда работает на JQuery, а не на React?

А this.setState вы обязаны вызывать каждый раз, когда собираетесь изменить данные.

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

А если команда работает на JQuery, а не на React?

Эммм… и в чем проблема?...JQuery — просто библиотека… подключить ее к React не проблема…

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

(например, не всегда изменение переменной должно приводить к изменению DOM).

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

Не до конца понимаю чем все это отличается от того, как это деалется в React и тем более Vue, где изменение стейта через this.foo также приводит к перерисовке. Давайте говорить конкретно, вы мне пример на React (или чем угодно) и почему вы считаете, что в Svelte нельзя сделать также, а я вам такой же пример на Svelte. Думаю для разработчиков язык кода наиболее доступный и понятный.
Посмотрел на lifecycle Svelte — да, есть знакомые методы: onMount, onDestroy, before/afterUpdate. C ходу не увидел метод, аналогичный render в React, но судя по философии Svelte — «A component is a reusable self-contained block of code that encapsulates HTML, CSS and JavaScript that belong together, written into a .svelte file» — он и не нужен.
Т.е. нельзя в одном файле содержать несколько компонентов или что-то не уловил?

А пример кода такой (чисто для передачи сути):
import * as React from 'react'

export type GraphCounterProps = { percent: number}
export class GraphCounter extends React.Component<GraphCounterProps, {}> {	
	private _color: string[]
	constructor(props: GraphCounterProps) {
		super(props)
		this._color = ['green', 'yellow', 'red', 'red']
	}

	shouldComponentUpdate(nextProps: GraphCounterProps) {
		return (Math.round(this.props.percent / 30) === Math.round(nextProps.percent / 30)) ? false : true
	}

	render() {
		return (
			<span 
				style={{
					color: this._color[Math.round(this.props.percent / 30)], 
					width: 100, 
					height: 20
				}}
			/>
		)
	}
}

C ходу не увидел метод, аналогичный render в React, но судя по философии Svelte

Зачем он, если код исполняется один раз, а не перезапускается на каждое изменение стейта?

Т.е. нельзя в одном файле содержать несколько компонентов или что-то не уловил?

Конечно нельзя. В реакт тоже нельзя, точнее можно, но за это надо по рукам бить больно.

А пример кода такой (чисто для передачи сути):


Тот же пример на Svelte:
<span style="color: {color}" />

<script>
  let colors = ['green', 'yellow', 'red', 'red'],
      percent = 0;

  $: color = colors[Math.round(percent / 30)];

  export { percent };
</script>

<style>
  span { width: 100px; height: 20px; }
</style>


Не увидел никаких проблем, лишь ручные оптимизации, которые Реакт заставляет делать разработчиков, а Svelte хендлит сам.

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

Глупости. Это скорее напасть Vue с его .vue файлами. React то как раз очень поощряет дробление компонент на минимальные функциональные единицы, настолько маленькие что в здравом рассудке их никто выносить в отдельный файл не будет. Это способствую функциональные компоненты, которые по сути представляют из себя обыкновенную pure-function.

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

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

У нас есть модули и импорты, нет никаких причин мешать все в кучу, это видимо от большой любви к раннему PHP.

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


Но это лирика. По факту же, когда я наблюдаю подход "1 компонент = 1 файл" я вижу вовсе не то, о чём говорят сторонники этого подхода. Никаких чудес не случается.


Я вижу длиннющие плохочитаемые плохоподдерживаемые макароны. Это я про Vue. Мне ещё не доводилось встречать примеров кода на Vue которые бы не подходили под это описание. Сколько я не смотрел реальный .vue код это портянки однообразной html-like копипасты в десятки строк. Там где я в React сделал бы 5 компонент в 1 файле с внятным названием и разграничением ответственности vue-воды пишут макароны с копипастой, т.к. подход "1 компонент = 1 файл" этому способствует самым явным образом. В случае использования какого-нибудь material-ui или другой многословной UI либы уровень мусора достигает немыслимых размеров.


Причина этому банальна. Если выносить все мелкие парустрочные сущности, обёртки, группировки и пр. в отдельные файлы, то те самые общие импорты и экспорты начинают занимать большую часть кодовой базы. В добавок к этому с огромным количеством крошечных файлов состоящих почти целиком из бойлерплейта работать гораздо менее удобно, чем с в 3-4-5 раз меньшим количеством файлов по 20-40 строк.


чем меньше функциональная единица, тем меньше работы выполняет Реакт

Обычно чем больше вы дробите, тем медленнее работает приложение. Как минимум начиная с какого-то уровня. Одна из самых странных и нелепых оптимизаций приложений заключается как раз в том, чтобы компоненты инлайнить ({comp(props)}, вместо <Comp {...props}/>). И это правда помогает (чуть-чуть).


То о чём вы говорите это уровень хаоса, когда человек все гребёт в один компонент явно нарушая принцип ограниченной ответственности. Но это дет сад :)

Но это лирика. По факту же, когда я наблюдаю подход «1 компонент = 1 файл» я вижу вовсе не то, о чём говорят сторонники этого подхода. Никаких чудес не случается.

Не повезло вам. Лично я не видел хорошо написанных React компонентов)

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

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

Обычно чем больше вы дробите, тем медленнее работает приложение. Как минимум начиная с какого-то уровня.

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

То о чём вы говорите это уровень хаоса, когда человек все гребёт в один компонент явно нарушая принцип ограниченной ответственности. Но это дет сад :)

Грести в один компонент не надо. Также как грести несколько компонентов в один файл. Компоненты должны иметь смысл, а 1-2х строчные компоненты редко имеют смысл, кроме отсечки рендеринга. Компоненты как раз и нужно разделять согласно single responsobility. Если никакой responsobility нет вообще, если компонент — это просто кусок шаблона, то и смысл в таких компонентах? Раньше это вообще называлось partial и даже не было полноценным шаблоном.

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

Я понял вашу мысль. В корне с ней не согласен. Вот прямо по всем пунктам. Но спорить не буду.

Право ваше и спор тут не поможет конечно.

Я только уточню, 1-2 строчные функции тоже зло?

Функции это про функции, компоненты — это больше про классы. То что в Реакт компоненты прекратили в функции — это не очень здоровая идея.

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

Потому что функция — это то, что вызывается с аргументами и возвращает результат, каждый раз исполняя логику внутри. Компонент — это то, что инкапсулирует стейт, логику работы с ним, а также может инстанциироваться множество раз. То есть это больше похоже на класс. Именно от того что в Реакт компоненты вдруг стали функциями и ростут все проблемы с производительностью, когда все содержимое компонента вынуждено инициализироваться каждый раз на каждое изменение входных данных. Это просто с точки зрения понимания, но совершенно не эффективно. Именно поэтому в Реакт есть костыли вроде useMemo, useCallback, useReducer, React.PureComponent, shouldComponentUpdate и так далее.

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

Кроме того, я даже физически не могу представить себе компонент из 2-х строчек в Svelte. В Реакт могу, потому что он неполноценных феймворк, без работы со стилями. Например, если представить что у нас есть компонент ссылки:

<a {href} {title} class="link">{text}</a>


Типа в одну строчку, но даже он не будет таким, потому что компонент без стилей не имеет смысла:

<a {href} {title} class="link">{text}</a>

<style>
  a { color: red; }
  a:focus { outline: 2px solid red; }
</style>

И вот он уже не однострочный и требует отдельного файла.
То что в Реакт компоненты прекратили в функции — это не очень здоровая идея.

Возможно. Тут есть о чём поспорить. Но именно в этом и заключается react-way.


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

Редкий компонент stateful. Почти все как раз stateless. Ну если писать идеоматично.


Именно поэтому в Реакт есть костыли вроде useMemo, useCallback, useReducer, React.PureComponent, shouldComponentUpdate и так далее.

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


Типа в одну строчку, но даже он не будет таким, потому что компонент без стилей не имеет смысла:

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


И вот он уже не однострочный и требует отдельного файла.

Не требует :) Если вышестоящий компонент состоит из 3-4 включений подобных однострочных под-компонент, то размазав их по файловой системе, вы только усложните жизнь тому, кто будет их поддерживать.


По сути говоря тут вопрос между: 5 файлами крошечного размера и 1 файлом в 10-30 строк. Работать со вторым гораздо удобнее. Что и показывает реальная практика Vue. Вместо того чтобы выносить подобные вещи в отдельные компоненты они всё инлайнят как есть в вышестоящий компонент и получают лапшу.


И вот в этом мне как раз симпатизирует React-way. Всё есть функция. Функции с телом больше 5 строк — это хороший повод задуматься о разделении её на несколько. Такая же картинка и с компонентами, ибо они тоже функции с чётко заданной ролью.


Писать таким во Vue пока нельзя :( Точнее можно, это это сильно против шерсти. С третьей версии обещают ввести. Посмотрим во что это выльется.


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

Возможно. Тут есть о чём поспорить. Но именно в этом и заключается react-way.

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

Редкий компонент stateful. Почти все как раз stateless. Ну если писать идеоматично.

Наоборот, редкий компонент stateless, чаще всего все же stateful. А если он все же stateless, то обычно это так называемые leaf-компоненты или dumb-компоненты, как это любят называть в реакте. Правда если уж у них вообще нет стейта, то такие компоненты даже компонентами назвать сложно. Это скорее шаблоны или partials, если совсем ко класике. Просто у современных фреймворков нет иных выразительных средств, поэтому все лепят компонентами. Но вот есть например lit-html:

const template = data => html`
  <h1>Hello ${data.title}</h1>
  <p>Hello ${data.description}</p>
`;

render(template(state), document.body);

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

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

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

Очень спорный момент. У меня почти все компоненты не имеют собственных стилей.

Значит у вас не совсем полноценные и плохо переносимые компоненты. Я еще понимаю когда люди сверху крутят всякие styled-components (хоть это и адуха).

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

Если нужно, можно и глобальные стили юзать. Это ухудшает переиспользуемость и переносимость, но совершенно не мешает подходу с компонентыми стилями. Даже используя ShadowDOM можно позволить внешним стилям работать внутри компонента.

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

Ничего дублировать не надо. Законченный компонент не может быть без стилей иначе он не законччен. Поэтому это не просто «мода», а компонентный подход, который в Реакт, как мне кажется, все же недоработан.

Не требует :) Если вышестоящий компонент состоит из 3-4 включений подобных однострочных под-компонент,

Я же написал вам пример компонента. Он уже не однострочный, а ведь там еще 20 строк стилей. Да и разметка наврядли такая простая. Вы предлагаете все эти 3-4 20-ти строчных компонента помещать в тот же файл, что и вышестоящий компонент? Чудно как-то.

Да, я понял, что вы пишете компоненты без стилей. Только исходя из того, что я написал выше, это либо не компоненты вовсе, а шаблоны или partials. Либо это какие-то недоделанные компоненты.

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

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

По сути говоря тут вопрос между: 5 файлами крошечного размера и 1 файлом в 10-30 строк.

Если бы вы писали полноценные компоненты, то у вас не было бы 1-2 строчных компонентов просто по определению. А значит один общий файл был бы не 10-30 строк на 5 компонентов, а уже 100-150 строк.

Работать со вторым гораздо удобнее. Что и показывает реальная практика Vue.

У нас реальная практика Vue с выхода 2-й версии и это не так. SFC — это лучшее что есть во Vue и всегда было.

Вместо того чтобы выносить подобные вещи в отдельные компоненты они всё инлайнят как есть в вышестоящий компонент и получают лапшу.

Так делают видимо те, кто пришел с реакт и любит лапшу. За это тоже надо бить по рукам. Благо Svelte изначально уберегает от этого.

И вот в этом мне как раз симпатизирует React-way. Всё есть функция. Функции с телом больше 5 строк — это хороший повод задуматься о разделении её на несколько. Такая же картинка и с компонентами, ибо они тоже функции с чётко заданной ролью.

То есть если у вас чисто HTML-макет больше 5-ти строк на одну логическую единицу, то вы ее все равно дробите на компоненты? Странно, обычно стейт компонента около 5-и строк занимает, плюс всякие там JSX примочки типа обязательного рут-элемента (+2 строчки). Ну-ка я попробую:

function Component(props) {
  return <>
    <h1>Hello ${props.title}</h1>
    <p>Hello ${props.description}</p>
  </>;
}

Хм, уже 4 строки. Получается еще одна и надо на дополнительный компонент делить?

Писать таким во Vue пока нельзя :( Точнее можно, это это сильно против шерсти. С третьей версии обещают ввести. Посмотрим во что это выльется.

Да, ох уж эти китайцы. Понахватают всего дурного и тянут в рот…

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

Насколько я знаю реактивность в Knockout реализована с помощью observerables, а в Svelte с помощью компиляции и топологического порядка исполнения. Какая связь в таком случае?

Судя по всему самые большие у нас с вами разногласия касаются стилей (да и бог с ними), и терминов (patrials, templates, ...). Чтобы не путать вас дальше, буду стараться использовать вашу терминологию.


Вот согласной вашей терминологии во Vue мне не хватает этих самых partials, чтобы избегать излишней лапши и дробить эти здоровенные куски html на внятные именованные параметризированные блоки, без создания груды лишних файлов. То что они будут stateless меня нисколько не смущает. Меня смущает сам факт того, что я не понимаю как это сделать. Вероятно я что-то упустил в документации.


Отсюда вопрос, раз уж вы упомняли, что у вас позитивный опыт с Vue и SCF, что там с partials? Беглый поиск меня привёл к тому, что до 0.12 там они и правда были. Как эту проблему решают теперь?


У меня нет никаких претензий к подходу "1 файл = 1 компонент", при удовлетворении двух пунктов: поддержка именованных переиспольуземыех параметризированных stateless блоков (partials?), вашей формулировки того что такое компонент. Наличие двух stateful компонент в одном файле и в React я считаю антипаттерном.


Теперь касательно спора Svelte vs React. Я не готов тут спорить, т.к. о Svelte я знаю чуть больше, чем ничего. Пара статей и видео презентация. Ваш аргумент про то, что это не observable вполне справедлив, ошибочка вышла, sorry.

Вот согласной вашей терминологии во Vue мне не хватает этих самых partials, чтобы избегать излишней лапши и дробить эти здоровенные куски html на внятные именованные параметризированные блоки, без создания груды лишних файлов. То что они будут stateless меня нисколько не смущает. Меня смущает сам факт того, что я не понимаю как это сделать. Вероятно я что-то упустил в документации.

Думаю способ это сделать по-другому делить приложение на компоненты. Потому что например у нас такой проблемы просто нет или она просто настолько редкая, что я не могу вспомнить. Может пример есть какой-то?

Отсюда вопрос, раз уж вы упомняли, что у вас позитивный опыт с Vue и SCF, что там с partials? Беглый поиск меня привёл к тому, что до 0.12 там они и правда были. Как эту проблему решают теперь?

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

Наличие двух stateful компонент в одном файле и в React я считаю антипаттерном.

Ок, тут мы сошлись. Тогда может попробуем какой-то пример разобрать. Глядишь я с вами и соглашусь.

Ваш аргумент про то, что это не observable вполне справедлив, ошибочка вышла, sorry.

Принято.

Может пример есть какой-то?

Например вот такой компонент. Взял первое что под руку подвернулось. Груда html. Много-много разметки. По разметке разбросано много-много относящихся только к UI аттрибутов. В итоге код на много экранов. Стейт значение всего 1.


Что можно сделать даже не вникая в код? Ну разбить эти куски на отдельные "partials" с внятными именами. И тогда получаем иерархическую структуру где каждое звено лаконично и удобочитаемо. Когда частности не мешают читать целостную картинку и при этом доступны под рукой.


Как такое сделать во Vue? Создать 10 файлов?

Конкретно в вашем файле я вижу лишь один компонент и один фрагмент (drawer), повторяющийся аж два раза.


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

С 86 по 164 строку мы видим груду html-like лапши. Которую тяжело читать и с ней тяжело работать. Сколько раз там дублируется drawer значения не имеет. Вместо эти 80 строк визуального мусора я ожидаю увидеть суть. А нюансы (груды аттрибутов и всякие обёртки) можно вынести на следующий уровень иерархии (partials)?


В конце концов мы же не пишем так обыкновенный код. А компоненты так пишут. В случае Vue особенно часто их пишут именно так (но искать пример для вью мне было лень).


В рамках терминологии PaulMaly вся эта лапша должна быть единым компонентом, т.к. компонент должен быть stateFul. Дескать нельзя выносить stateLess части в отдельные компоненты.


Решение — выносим все эти части в stateLess "partials" и тогда код <ResponsiveDrawer/> становится легко-читаемым и с ним становится удобно работать. Проблема — partials из Vue выпилили.

Почему вы "ожидаете увидеть суть" в Svelte, но при этом миритесь с "визуальным мусором" в React?

но при этом миритесь с "визуальным мусором" в React?

Не понял, о чём вы. Приведённый выше пример кода — пример html-like лапши. Не надо так писать :) Really. Не надо с этим "мириться". React позволяет писать по-другому.


Про Svelte я кстати не писал. Вполне вероятно что там есть "partials" и такая проблема не стоит вообще. Это во Vue их нет.

В рамках терминологии PaulMaly вся эта лапша должна быть единым компонентом, т.к. компонент должен быть stateFul. Дескать нельзя выносить stateLess части в отдельные компоненты.

Не не, это я вашу терминологию натягивать с подхода «все есть компонент», а более правильную, «не все есть компонент, а что еще и шаблон/partial». Мое же решение вашей проблемы — это иной подход к декомпозиции компонентов в принципе.
Как я и написал выше, нужно просто по-другому сделать декомпозицию приложения. Глядя на ваш файл, сразу видно, что сделать что-то не так с этим. Почему у этого компонента одновременно отрисовывается appbar, navbar и контент? Это что компонент страницы? А в названии почему-то будто это компонент Drawer.

Я бы декомпозировал примерно так, если сходу:

<div class="root">
  <BasicAppBar 
    title="Responsive drawer" 
    on:click={e => open = !open}
  />

  <EmailDrawer {open} />

  <main>
    <svelte:component this={Content} />
  </main>
</div>

<script>
  export let open = false,
            Content = null;
</script>

<style>
  .root { ... }
  main { ... }
</style>


Правда ведь компонент страницы стал выглядить и читаться значительно проще?

Но теперь у вас это "компоненты", хотя они и stateLess. И как бы вы не дробили, вы дойдёте до:


<IconButton
    color="inherit"
    aria-label="Open drawer"
    edge="start"
    onClick={handleDrawerToggle}
    className={classes.menuButton}
>
    <MenuIcon />
</IconButton>

По-хорошему такое надо вынести в отдельный компонент. Но ведь оно же stateLess. Вы выше писали:


А если он все же stateless, то обычно это так называемые leaf-компоненты или dumb-компоненты, как это любят называть в реакте. Правда если уж у них вообще нет стейта, то такие компоненты даже компонентами назвать сложно. Это скорее шаблоны или partials, если совсем ко класике.

И мы снова вернулись к partials. В примере выше практически все эти 80 строк это stateLess.


Всякие там -aria аттрибуты, разметка og:graph, нюансы вёрстки часто вынуждают писать груды объёмного stateless html.


И в случае Vue я вижу что народ не парится и всё постит в 1 файл с тонной подобного мусорного кода. Приходится сильно много парсить глазами, чтобы понять что тут почём. И важные вещи вроде -v директив теряются в этой горе мусора.


В partials их не вынести, за их отсутствием. В отдельные файлы тащить каждый такой нюанс — сильно усложнить жизнь в поддержке (такое по 100 раз на дню переделается, с грудой крошечных файлов работать неуодобно, git очень плохо умеет в переименовывание и "наследование" файлов, постоянная проблема с именованием, тонны импортов и экспортов, особенно дублирование общих зависимостей, и т.д.). Добавить к этому что даже vsCode для js всё ещё космически далёк от уровня полноценных IDE для статически типизированных языков и мы получаем боль.


В итоге пока я писал на вью (очень непродолжительное время, vue разочаровал меня не только в этом) я перешёл на string-templates в js файлах. Вместо "partials" писал компоненты которые явным образом приходилось ставить в components: { UserPanelHeader, ... }. Вскоре я выяснил что разработка за пределами .vue файлов это вообще не vue-way и никто всерьёз её поддержкой заниматься не хочет.

Похоже вы меня немного не верно поняли. Бывает.

Но теперь у вас это «компоненты», хотя они и stateLess. И как бы вы не дробили, вы дойдёте до:

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

И мы снова вернулись к partials. В примере выше практически все эти 80 строк это stateLess.


Нет не вернулись. Мы все еще говорим о том, что если композиция произведена верно, никаких 1-2 строчных недокомпонентов быть не должно. Также как не должно быть таких вот монстров из вашего примера.

Чтобы было понятно дальше, в своих проектах на Svelte делим компоненты на 3 вида: components (leaf/dumb/pure компоненты, переиспользуемые и переносимые), views (компоненты реализующие конкретную логическую единицу приложения, smart, не переносимые обычно), layouts (компоненты лейаутов).

Так вот компоненты IconButton, List, Divider, ListItem — это все компоненты. Компоненты BasicAppBar, EmailDrawer — это вьюхи, которые внутри юзают компоненты и другие вьюхи, и содержат логику этой части приложения. Ну а компонент из моего примера — это лейаут. Все четко и по полкам, никаких 1-2 строчных компонентов, никаких огромных кусков html.

И в случае Vue я вижу что народ не парится и всё постит в 1 файл с тонной подобного мусорного кода. Приходится сильно много парсить глазами, чтобы понять что тут почём. И важные вещи вроде -v директив теряются в этой горе мусора.

Далеко не все так делают, вам видимо не везло.

В итоге пока я писал на вью (очень непродолжительное время, vue разочаровал меня не только в этом) я перешёл на string-templates в js файлах.

Есть подозрение что вы пришли туда уже после опыта с React и декомпозировали приложение схожим для него образом. Но во Vue и Svelte надо делать не так.

Вскоре я выяснил что разработка за пределами .vue файлов это вообще не vue-way и никто всерьёз её поддержкой заниматься не хочет.

Да, Vue как бы поддерживает и классы, а-ля ангуляр и из реакт с JSX, но в основном все пишут SFC, потому что это удобно.

Ок, пускай это будет leaf-component. Тогда моя позиция проста: я не вижу смысла выносить мелкие однообразные leaf-компоненты в отдельные файлы, т.к. с такой разбухшей кодовой базой мне становится слишком тяжело работать. Почему? Выше в крадце описал. А других альтернатив декомпозиции Vue мне не предоставляет.


И мне пока не попадалось на глаза кодовой базы, где был бы вынос leaves в отдельные файлы. В лучшем случае так.


Не исключено, что в хороших компаниях именно так и пишут. Было бы интересно посмотреть.

<template>
  <div class="md-table-pagination">
    <template v-if="mdPageOptions !== false">
      <span class="md-table-pagination-label">{{ mdLabel }}</span>

      <select-page-size 
        v-model="currentPageSize" 
        @changed="setPageSize"
        pageOptions="mdPageOptions"
      <md-field>

    </template>

    <span>{{ currentItemCount }}-{{ currentPageCount }} {{ mdSeparator }} {{ mdTotal }}</span>

    <prev-button @click="goToPrevious()" :disabled="mdPage === 1"/>
    <next-button @click="goToNext()"/>
  </div>
</template>

Примерно об этом говорю. Вынос prev-button, next-button, select-page-size из основного тела шаблона, куда-нибудь рядом. Чтобы и идти недалеко на "нюансами", и не разбухал основной шаблон.

Так сделайте для них общий компонент кнопки как частный случай кнопки с иконкой. Он скорее всего еще где-то пригодится:

<md-button class="md-icon-button {classes}" {disabled} on:click>
  <md-icon>{icon}</md-icon>
</md-button>

<script>
  export let icon = '',
             disabled = false,
             classes = '';
</script>

И юзайте:

<IconButton 
  icon="keyboard_arrow_left"
  on:click={goToPrevious} 
  disabled={mdPage === 1} 
/>
<IconButton 
  icon="keyboard_arrow_right" 
  on:click={goToNext} 
/>

Там где игра действительно стоила свеч (какие-нибудь универсальные переиспользуемые UI обёртки) — я так и делал. Но таких мест было довольно мало. Чаще всего куски были более-менее уникальными.


Честно говоря мне надоело спорить :( Мы переливаем из пустого в порожнее без всякого на то смысла. Суть: мне паталогически не хватает partials во Vue. На мой вкус и цвет SCF в нём это зло ровно до тех пор, пока "именованные параметризированные stateless блоки" туда не вернут. А до тех пор я считаю что такой подход приводит к в той или иной степени разбухшему говнокоду, на который после React смотреть без слёз нельзя. Привет php из 90-х.


Надеюсь в Svelte "partials" есть.

А до тех пор я считаю что такой подход приводит к в той или иной степени разбухшему говнокоду, на который после React смотреть без слёз нельзя. Привет php из 90-х.

Так вроде React — это как раз потомок php из 90х?

Надеюсь в Svelte «partials» есть.

Неа, нету)))) И как я писал выше, видимо не часто это нужно, раз я даже не могу придумать кейс. Вы мне тоже кейс так и не дали. Даже если он есть, но очень редкий, можно для такого редкого кейс создать один дополнительный файлик. Это не страшно.

Плюс для некоторых кейсов, можно сделать что-то вроде:

<template bind:this={tpl}>
  <h1>Hello {name}</h1>
</template>

{@html welcome}

<script>
  let name = 'world', 
      tpl;

  $: welcome = name && tpl && tpl.innerHTML;
</script>
Я наверное выскажу крамольную мысль. Но наверное все топ-фреймверки примерно равны по своим выразительным возможностям. Кроме пожалуй backbone+marionette которые можно ценить преимущественно за то что «они были первыми».

Если говорить о ключевых преимуществах Реакт, я на первое место ставлю как раз то, что компонент может быть классом. А это означает что на Реакте можно очень просто заниматься метапрограммированием — то есть не ручным кодированием компонентов, а генерированием компонентов, например, на основании схемы данных или же самих данных. Наверное именно поэтому в Реакт уже появилась библиотека по удобству близкая к Django при помощи которой можно очень быстро создавать админки marmelab.com/react-admin-demo Что-то внешне визуально похожее есть и на Vue, но там разработка на два порядка сложнее получается.

Если говорить о svelte, то я недавно обратил внимание на next-подобный фреймверк sapper см. svelte.dev/blog/sapper-towards-the-ideal-web-app-framework
Я наверное выскажу крамольную мысль. Но наверное все топ-фреймверки примерно равны по своим выразительным возможностям.

Именно так и по большей части этим всех «заразил» именно реакт. Хорошо ли это? Мое мнение не очень. Ангуляр еще пытается как-то бороться с этой модой. Все же у него есть модули и сервисы. Хотя модули вроде выпиливать будут…

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

Кстати, после компиляции компоненты Svelte это ES6 классы со всеми вытекающими, а исходный код компонентов, который в SFC, это и есть чистой воды метапрограммирование. Я правда так не понял причем тут генерация админки на основе данных.

Наверное именно поэтому в Реакт уже появилась библиотека по удобству близкая к Django при помощи которой можно очень быстро создавать админки marmelab.com/react-admin-demo Что-то внешне визуально похожее есть и на Vue, но там разработка на два порядка сложнее получается.

На самом деле, формулировка «в Реакт уже появилась» скорее требует «еще только». Потому что первая такая админка от тех же чуваков появилась для AngularJS в далеком 2014 году: ng-admin-book.marmelab.com

Если говорить о svelte, то я недавно обратил внимание на next-подобный фреймверк sapper

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

Про генерацию админок я ничего в своем посте не говорил. Просто был у меня один прототип (я даже сам не хотел этого делать т.к. не из тех кто пишет «свою cms» Задача была такая сделать cms которая была бы лучше чем все что было уже написано до меня и на это отводилось две недели плюс 4 часа на изучения Реакт) И там я как раз опирался на ту особенность что можно на основании данных конструировать компоненты на лету. Насколько я понимаю не все фреймерки позволяют сделать это. Например на riotjs я не смог это повотрить — быстро уперся в ограничения выразительных возможностей фреймверка. Хотя как правило это и не требуется в большинстве проектов.
Посмотрел на админку на Angular. Судя по коду проекта example кодить приходится все равно много. Хотя и разработчик (скорее фирма а не человек) тот же.

Тот тот. Тогда просто про реакт никто не слышал))
И там я как раз опирался на ту особенность что можно на основании данных конструировать компоненты на лету. Насколько я понимаю не все фреймерки позволяют сделать это. Например на riotjs я не смог это повотрить — быстро уперся в ограничения выразительных возможностей фреймверка. Хотя как правило это и не требуется в большинстве проектов.

Прям с нули конструировать компоненты в рантайме? Да, наверное Svelte так не умеет. Правда я и на реакт это не представляю как. Можете пример дать простой?
Постараюсь найти как я это делал.
Простого или хорошего примера нет. Могу привести фрагмент кода из приложения 3-летней давности которое было первым для меня на Реакте и не пошло дальше рабочего прототипа. Не пошло потому что я написал за две недели движок для cms и он был вполне себе рабочий. Но админка была также рабочая но я ее не успел как следует продумать. Вцелом я тогда просто для себя понял что у Реакта это достаточно интересная могла бы быть тема компонентами которые можно задавать конфигурацией и генерировать налету. Вот такой фрагмент где это происходило. Очень конечно примитивный и некрасивый.
...
   // Компоновка из двух блоков (1 левый + 1 правый)
          if (Component.defaultProps && Component.defaultProps.isHalf) {
            if (LeftHalf !== null) {
              let LocalLeftHalf = LeftHalf
              let localLeftHalfData = leftHalfData
              var component = React.createElement(() => <section className='l-two-blocks' key={key++}>
                <LocalLeftHalf {...localLeftHalfData} key={key++}/>
                <Component {...block.data} key={key++}/>
              </section>);
              LeftHalf = null;
              return component;
            } else {
              LeftHalf = Component;
              leftHalfData = block.data;
              return;
            }
          }
...

Ок, а что конкретно из этого не получилось реализовать в Riot? Смотрю с точки зрения Svelte, вроде как все можно.
Я просто опишу задачу. Сайт набирался из кубиков — реально и раннее созданных компонентов с несколькими видами компоновки 1) однин компонент на ширину экрана 2) два комнонента рядом 3) один вертикальный компонент слева и два справа (один под другим) 4) аналогично один вертикальный компонент справа и два слева один под другим. Риот был тогда еще в первой версии (или тоько перешел на вторую) и, да, все это необходимо было сделать серверным рендерингом. А Риот на тот момент позволял такие манипуляции только на клиенте.

Вцелом Риот сейчас уже в 4-й версии наверное все возможно. Был существенно переработан. Наконец появилась возможность гидрации. так что может быть там это и можно будет сделать.
В спор касательно природы реактивности Svetle вступать не хочу, т.к. довольно долго работал с Knockout и знаю, что всё не так просто и радужно, как кажется на первый взгляд.

Knockout — довольно старая библиотека, полная архитектурных костылей. Пожалуйста, перестаньте судить по Knockout о всех других реактивных инструментах.

mayorovp, ну тут как сказать, попробовав в деле Vue2 я стал думать о KnockoutJS лучше. В KnockoutJS один ko.computed может зависеть от других ko.computed. Во Vue2 под капотом всё сводится к перекладыванию observable-leaves (что делает реализацию некоторых сложных кейсов почти невозможной). Плюс knockoutJS из коробки даёт довольно богатый инструментарий. Vue2 же даёт нам только сами компоненты. Отдельный топик работа с массивами.


Но судя по всему, во Vue3 будет много вкусных нововведений.

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

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


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

Нет, Вы суть не уловили… гораздо лаконичнее и я мог написать…
Суть в том, сколько раз компонент «перерисуется» при изменении percent от 0 до 100?
В моем случае обновление DOM («перерисовка» компонента) произойдет всего 4 раза.
Я не замерял сколько раз перерисуется компонент, но это ровно такой же код, который написали вы. У вас перерисовка блокируется операцией сравнения в shouldComponentUpdate, так?

А Svelte просто не перерисовывает DOM, если реальное значение стейта не изменилось. Понимаете? Сразу из коробки. Он внутри знает предыдущее значение color, которое является эквивалентом вашего Math.round(this.props.percent / 30), посчитаного последний раз. Далее при изменении percent или colors, Svelte автоматически пересчитывает color (эквивалент вашего Math.round(nextProps.percent / 30)) и сравнивает предыдущее значение color с новым вычисленным. Если значение реально не поменялось, то никаких перерисовок не будет. Иными словами внутри он делает что-то вроде:

changed.color = prevColor !== color;


Это вообще все вычисления необходимые для отрисовки DOM. Одно строгое сравнение. Без rerender+reconcile, без shouldComponentUpdate. Далее сама манипуляция примерно такая:

if (changed.color) {
   span_1.style.color = color;
}


Где span_1 — это заранее закэшированный элемент. То есть даже querySelector по DOM не делается.
UFO just landed and posted this here
Конечно же shallow equal))) Зачем Svelte deep equal?
UFO just landed and posted this here

"Так же" в смысле полученного результата — да. "Так же" в смысле проведенной работы — нет.


Svelte знает, что изменение color ведет к изменению span_1.style.color и ни к чему более. Реакт же вызовет render(), построит vDOM, сравнит его со старым, и только после этого узнает что кроме span_1.style.color менять ничего не нужно.

Реакт же вызовет render()

В том то и дело, что не вызовет — именно для этого используются shouldComponentUpdate или PureComponent.

Если color изменился — то ещё как вызовет.

Не важно, что изменится. Если shouldComponentUpdate вернет false (а он вызывается перед render), то render не произойдет.

Ау, если нам требуется изменить DOM (color-то изменился!), то какой смысл возвращать false из shouldComponentUpdate?

color — не есть часть стейта! Меняется только percent! При его изменении не всегда нужно обновлять DOM!

Хорошо, уточняю: если percent изменился так, что теперь требуется обновить DOM — то ведь shouldComponentUpdate должен вернуть true?

И что из этого следует?

Речь тут идет о самом процессе апдейта DOM, если вы не уловили. Во-первых, просто так заюзать в вашем примере React.PureComponent все равно не получится. Описал почему тут.

Но это не так важно. Вот вы написали вручную проверку значений в shouldComponentUpdate. Да теперь Реакт компонент НЕ будет обновлять DOM на абсолютно каждое изменение percent (понять бы вообще почему он в принципе когда-либо должен так делать, ведь кажется логичным не менять DOM если нет изменений).

Но как только проверка сработает и shouldComponentUpdate вернет true, реакт расправит крылья и как гордый сокол полетит клевать все, что попадется ему на глаза. А именно отрендерит дубликат всего vdom этого компонента и возможно подкомпонентов (зависит от того как они реализованы) и пошагово будет сравнивать все ноды/аттрибуты/значения, чтобы в итоге просто поменять цвет текста в span.

В этом примере, это не так заметно. Он всего лишь построит vdom из одной ноды с одним аттрибутом, пересчитает значения цвета (еще раз кстати), потом всего лишь соберет стили из объекта, заново применит их. Потом пошагово сравнит предыдущее дерево с новым получившимся. Сперва проверит span, потому его аттрибуты, потом выяснит какой из них изменился, потом на основе этого знания определит какую DOM операцию произвести. Просто чтобы поменять цвет.

И все это против:

if (changed.color) {
   span_1.style.color = color;
}

Добрался до Svelte. Поиграл в песочнице. Интересная штука.


Сгенерированный код Svelte напоминает очень хорошо оптимизированный ручной dom-mutate-код. Там случаем нет подводных камней или ограничений когда "зависимости" устроены особенно сложным образом?


Насколько я понимаю тут вся магия заключается в том, что он вместо того чтобы рендерить шаблон целиком, рендерит только интерактивные его части и тут же сверяет их с прежним значением. Во многом напоминает этот самый vDom в React, но с меньшим количеством лишних телодвижений. А отличие от observable в том, что нет тяжеленных обвязок вокруг каждой переменной, нет сложностей с нетривиальным обновлением графа данных, и нет сильно усложнённого дебага.


На первый взгляд такой подход кажется очень перспективным. ИМХО.

Сгенерированный код Svelte напоминает очень хорошо оптимизированный ручной dom-mutate-код.

Именно так. Поэтому я называю это «писать vanillajs приложение без необходимости писать на vanillajs» )))

Там случаем нет подводных камней или ограничений когда «зависимости» устроены особенно сложным образом?

Можете попробовать. Если найдете такой кейс то велком в ишус и будем править.

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

Я бы не сказал что напоминает vdom. В Svelte абсолюно отсутствуют как деревья, так и реконсияция оных. А все DOM манипуляции для каждого кейс заранее подготовлены. Не вижу никакой связи с работой vdom.

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

Да, только статический анализ на этапе комплиции и топологический порядок.

На первый взгляд такой подход кажется очень перспективным. ИМХО.

Ждем вас в наших рядах: t.me/sveltejs ;-)
В Svelte абсолюно отсутствуют как деревья

В #for я вижу циклы. Чем вам не деревья?


так и реконсияция оных.

Ну проверка changed.{anything} очень схожа с той самой реконсиляцией. Те же яйца, только сбоку. В React асимптотика решения зависит от числа DOM-звеньев, в Svelte от числа реактивных вставок. Второе, на первый взгляд, должно быть быстрее (не ручаюсь).


Не вижу никакой связи с работой vdom.

^^^ А теперь? :)

^^^ А теперь? :)

Не-а)))

В #for я вижу циклы. Чем вам не деревья?

Хотя бы тем, что циклы плоские.)))

Ну проверка changed.{anything} очень схожа с той самой реконсиляцией. Те же яйца, только сбоку.

Я вот такой плохой человек, поэтому люблю говорить на примерах:

<div class="foo">
  <h1>Hello world</h1>
  <p class="text">Lorem ipsum</p>
  <form action="/login" method="post">
    <input type="email" placeholder="Enter email">
    <input type="password" placeholder="Enter password">
    <button>Login</button>
    <button type="reset">Clear</button>
  </form>
</div>

Вот такой компонент на React и Svelte (пишу на svelte, думаю сможете в уме на реакт портировать). И вот такой код:

// react
this.setState({
   email: 'example@mail.com'
});

//svelte
email = 'example@mail.com';

Сколько операций сравнения сделает React с его vdom? Более 20ти по грубым подсчетам и это только реконсиляция.

Сколько операций должно быть выполнено? Ноль. Сколько делает Svelte? Ноль
Сколько операций в DOM должно быть сделано? Ноль

Добавим динамики:

...
<input value={email} type="email" placeholder="Enter email">
...

Сколько операций сравнения сделает React с его vdom? Все также более 20-ти.
Сколько реально требуется? Одну.
Сколько сделает Svelte? Одну.
Сколко манипуляций в DOM? Одна.

Только в случае с реактом, насколько я понимаю, будет также выполнена операция получения реального DOM элемента (querySelector), а в Svelte просто:

if (changed.email) {
  input0.value = ctx.email;
}


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

Разница более чем существенная, а ваше обобщение «мол все одно» слишком уж масштабное.
Хотя бы тем, что циклы плоские.)))

Не очень понял вас. #for в #for не создаст вложенного цикла?


Сколько сделает Svelte? Одну.

Svelte сделает столько сравнений сколько у вас {}. В этом и параллель. Я выше об этом и писал. Асимптотика зависит от разных вещей. Вариант со Svelte быстрее. Можете условно считать что у Svelte вместо vdom vexpressions. Аналог реконсиляции находится там где проходят проверки на changed.{anything}

Не очень понял вас. #for в #for не создаст вложенного цикла?

Может я не понял, но в Svelte нет #for. Есть #each но какое отношение это имеет в деревьям vdom все равно не ясно.

Svelte сделает столько сравнений сколько у вас {}. В этом и параллель. Я выше об этом и писал.

Просто это не так)) Видимо пример придется все же продолжить, чтобы вы разобрались.

Добавим еще чуть динамики:

...
<h1>Hello {email}</h1>
...

Сколько операций сравнения Реакт? Все еще более 20-ти.
Сколько операций сравнения надо? Одну.
Сколько сделает Svelte? Одну.
Сколько операций в DOM? Две.

Можете условно считать что у Svelte вместо vdom vexpressions. Аналог реконсиляции находится там где проходят проверки на changed.{anything}

Вы серьезно думаете что вот это аналог реконсиляции vdom?:

if (changed.email) {
  set_data(t1, ctx.email); // внутри хелпера: t1.data = ctx.email
  input0.name = ctx.email;
}

Ну тогда получается что все фреймворки работают по сути как AngularJS. У всех есть своеобразная форма change detection. Все одно и тоже. Зачем тогда нам с AngularJS вообще было слезать? Писали бы на нем и радовались жизни )))))
Вы серьезно думаете что вот это аналог реконсиляции vdom?

Ну да. А что вас в этом смущает?


Все одно и тоже

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


Я столкнулся уже как минимум с 4 разными способами обеспечить "реактивность". У Svelte довольно оригинальный подход.

Ну да. А что вас в этом смущает?

Эм, ну тогда ладно)

С чего вы вообще взяли, что я считаю это всё одинаковым?

Хм, ну даже не знаю… Может быть поэтому?:

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

Svelte ничего не рендерит перед проверкой, только после. Реакт сперва рендерит vdom, потом проверяет, потом рендерит dom.

Во многом напоминает этот самый vDom в React, но с меньшим количеством лишних телодвижений.

Тогда можно было написать, «Svelte во многом напоминает вообще все что только можно, потому что у всех есть аналог cd». Да и вообще, человечество еще не придумало способа сравнить что-то, кроме как сравнить, то есть все очень похоже и напоминает друг друга))))

Я столкнулся уже как минимум с 4 разными способами обеспечить «реактивность». У Svelte довольно оригинальный подход.

Вот тут вы правы, просто без компиляции и мета-программирования это не получилось бы. Поэтому столько упора делается на то, что svelte — это компилятор.
Svelte ничего не рендерит перед проверкой, только после. Реакт сперва рендерит vdom, потом проверяет, потом рендерит dom

Да, да, всё так. Мне стоило вычитать тот комментарий перед отправкой. Sorry что запутал.


Тогда можно было написать, «Svelte во многом напоминает вообще все что только можно

Отнюдь. Судите сами: он совсем не напоминает KnockoutJS или Vue. Там ведь нет никаких сравнений. Мы просто обновляем значение, и, после этого, уведомляем всех подписчиков. Какой ценой — отдельная песня, но суть вещей другая.


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


что svelte — это компилятор

Вспомнился Imba. Тоже компилятор.

Отнюдь. Судите сами: он совсем не напоминает KnockoutJS или Vue. Там ведь нет никаких сравнений. Мы просто обновляем значение, и, после этого, уведомляем всех подписчиков. Какой ценой — отдельная песня, но суть вещей другая.

Опять же не уверен как это в KnockoutJS, но в Vue все тот же vdom, что и в реакт. Разница лишь в том, что Vue кладет изменение в очередь и обновляет их в конце текущего тика, то есть изменени просходят асинхронно, а не синхронно как в React. Сам принцип Vdom при этом никак не меняется.

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

Последовательно «по всем значениеям» это очень далеко от «последовательно по всему дереву».

Вспомнился Imba. Тоже компилятор.

Да есть такой: twitter.com/Rich_Harris/status/1065992585095929857

Кстати да, Vue использует vDom. Совершенно вылетело из головы. Несмотря на то, что у них observer под капотом. Не знаю, что их побудило к этому, но наверное на то были причины. В knockout же мы имеем множество функций вида val => domNode.setAttribute('title', val), которые вызываются при изменении значения observable. А у Vue, да, гибридный подход. Совсем забыл про это. Надо будет нарыть — зачем оно там.


Последовательно «по всем значениеям» это очень далеко от «последовательно по всему дереву».

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


Да есть такой: twitter.com/Rich_Harris/status/1065992585095929857

У него тут неплохой результат кстати. Надеюсь это не тот самый бенчмарк который они учудили ранее (там совершенно отвратно написанные React и Vue решения, которые ну просто никак не могут не тормозить).

Может я не понял, но в Svelte нет #for. Есть #each но какое отношение это имеет в деревьям vdom все равно не ясно.

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

UFO just landed and posted this here

Ну так percent-то по условию изменился...

Я бы не сказал, что точно также, но да, там хак с shouldComponentUpdate для таких простых случаев уже не актуален, но насколько я помню там есть конкретные ограничения на его использование и нельзя просто взять и сделать все реакт компоненты React.PureComponent. В Svelte это просто так работает, потому что он в принципе не пытается все рендерить.

Ну и опять же, как в примеру выше применить React.PureComponent? Он же сам имплементирует shouldComponentUpdate, но только для стейта и пропсов. То есть придется вводить такой же color, как я ввел в примере на Svelte и тогда везде императивно связывать percent (пропс) и color (внутренний), то есть при каждом изменении percent заново вычислять color. Как по-другому то? В реакт же нет реактивности. Получается мы избавимся от ручной проверки в shouldComponentUpdate, но получим какой-нить componentWillReceiveProps. Короче все равно не то.
В Svelte пропагандируется one-file-component. То есть стили, код и шаблон все в оном файле. При таком подходе сразу отрубается множество полезных инструментов статического анализа кода, форматирования и тд.
Чем же лучше react/angular/flutter & co, где шаблон хорошо разбавлен кодом (или наоборот)? Уж лучше один файл но в нём отдельно шаблон и код, чём php-style 15-ти летней давности, пусть и с улучшенным синтаксисом.
UFO just landed and posted this here
Прошу прощения. Видимо, мне просто попался такой фрагмент кода на angular — со вставками markup, и я экстраполировал на весь фреймворк.
В angular действительно шаблоны можно инлайнить в код компонента как строку, но это опциональная возможность. Как правило шаблоны там в отдельных файла что хорошо. А вот Svelte насколько я понимаю не позволяет использвать 3-files-component модель разработки которая по моему мнению предпочтительна.
А вот Svelte насколько я понимаю не позволяет использвать 3-files-component модель разработки которая по моему мнению предпочтительна.

Позволяет, можно делать так, после установки специального препроцессора:

<template src="template.html"></template>
<script src="script.js"></script>
<style src="style.css"></style>

Только обычно это не нужно и не удобно. Если компонент радумается, что хочется разделить его, то скорее всего был нарушен принцип single responsibility и компонент следует отрефакторить.
Если компонент радумается, что хочется разделить его, то скорее всего был нарушен принцип single responsibility и компонент следует отрефакторить.
Разделение ведь нужно не потому что файл раздувается, а чтобы самый различный туллинг мог работать с файлами. Но если на то пошло, то как раз все мешать в один файл и есть нарушение принципа single responsibility. Что в Vue что в Svelte какая-то нездоровая мода.
Разделение ведь нужно не потому что файл раздувается, а чтобы самый различный туллинг мог работать с файлами.

Тулинг можно доработать. Все фреймворки требуют кастомного туллинга в любом случае: в React изначально не было туллинга для jsx, во Vue для SFC, в Angular тоже полно кастомных вещей, те же декораторы и TS. Все это в какой-то момент времени требовало доработки туллинга. Отказывать в удобстве разработки из-за временного несовершенства туллинга довольно глупо.

Но если на то пошло, то как раз все мешать в один файл и есть нарушение принципа single responsibility. Что в Vue что в Svelte какая-то нездоровая мода.

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

Если вы придерживаетесь другого мнения — я написал выше как можно разделить на отдельные файлы.
> React изначально не было туллинга для jsx, во Vue для SFC

Как раз по той же причине по которой и у свелти, все эти поделки пропагандируют SFC, а React еще доверху намешал кода с шаблонами в своем JSX (фирменнный PHP спагетти-стиль 15 летней давности).

> Все фреймворки требуют кастомного туллинга в любом случае

Это не так. Если все в отделных файлах, то доработки никакие не нужны, тулы просто сканирут файл и все.
Я бы не сказал что React пропагандируют SFC. У них была попытка реализации, но неудачная. Реальные SFC только у Vue и Svelte.

Это не так. Если все в отделных файлах, то доработки никакие не нужны, тулы просто сканирут файл и все.

Я писал про фреймворки. Давайте уже без «воды». Назовите фреймвок, который не требует костомного туллинга?
Я писал про фреймворки. Давайте уже без «воды». Назовите фреймвок, который не требует костомного туллинга?
Когда у тебя код во внешних файлах типового формата, то типовые тулы будут работать вне зависимости от фреймворка потому что это ведь просто JS/TS/CSS/SCSS/HTML/итд файлы которые не нужно кастомным образом выколупывать из SFC для анализа или какой-либо post обработки.

Просто нужно понимать что исходный код не требует некой логической группировки (SFC) и даже наоборот лучше делить код на мелкие части (даже например просто банально потому что будет меньше вероятность конфликтов при мерже). Но группировка может быть нужна потребителю кода или при дистрибуции кода и вот там уже имеет смыслы делать некую логическую группировку и компоненты.
Когда у тебя код во внешних файлах типового формата, то типовые тулы будут работать вне зависимости от фреймворка потому что это ведь просто JS/TS/CSS/SCSS/HTML/итд


Что есть типовой формат и почему TS/SCSS вдруг стали типовыми? Для них сразу тулзы были написаны? А раз нет, тогда почему вы считаете что SFC не станет точно также типовым. Да и сейчас уже SFC в Svelte это тоже вполне себе типовой формат, HTML называется. За исключением языка шаблонов HTMLx, все остальное вполне себе поддается стандартному для HTML файлов туллингу.

файлы которые не нужно кастомным образом выколупывать из SFC для анализа или какой-либо post обработки.

Ничего «выколупывать» самому и не надо. Есть препроцессоры, которые как раз делают это за нас.

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

Не согласен тут. Значительно удобнее работать с компонентом как с единой единицей. Нужно вынести отдельно? Писал выше как.
Да и сейчас уже SFC в Svelte это тоже вполне себе типовой формат, HTML называется. За исключением языка шаблонов HTMLx, все остальное вполне себе поддается стандартному для HTML файлов туллингу.

Лично меня очень интересует именно TS-тулинг. То есть такая штука, которая подскажет мне, у какой переменной какие свойства имеются.


И вот его-то в Svelte и нету...


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

Лично меня очень интересует именно TS-тулинг. То есть такая штука, которая подскажет мне, у какой переменной какие свойства имеются.

И вот его-то в Svelte и нету…

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



Да, не густо, но ребята из русскоязычного сообщества пилят поддержку например вот такой штуки:

marketplace.visualstudio.com/items?itemName=ardenivanov.svelte-intellisense

Это уже поинтереснее.
php-style 15-ти летней давности
JSX пропагандируемый реактом и есть 15-ти летней давности спагетти-код-стайл, видимо потому что в FB изначально было много PHP кодеров и дос сих пор таковые диктуют правила игры имея огромные рычаги маркетингового влияния.
UFO just landed and posted this here
То есть полная компиляция высокоуровневого декларативного кода в низкоуровневый императивный код — это ничего нового в контексте JS фреймворков? Выкидывание из рантайма большей части тяжелых операций, таких как render/reconcile в vdom, тоже? Можете рассказать, где еще используется тот же принцип?
UFO just landed and posted this here
То есть вы ушли от ответа, почему вы утвердаете, что Svelte не привносит ничего нового?

Код на любом языке может быть как более высокоуровневым, так и более низкоуровневым для этого языка. Речь не про сам язык, а про то как писать код на нем. Прямые манипуляции в DOM очевидно более низкоуровневое использование JS, чем декларативное изменение состояние с последующей синхронизацией с DOM.
UFO just landed and posted this here
Ок, я согласен, действительно, я достаточно стар поэтому сравниваю «низко/высокоуровневость» целиком языками (помните С/С++/Asm?) а не в рамках одного языка, что как вечно замечено также вполне приемлемо.

Верю вам на слово, что вы старее меня))) Однако, я в свое время тоже 4 года писал на С/С++ и все же стараюсь отделять мух от котлет.

Относительно компиляции, в той или иной мере это все современные фреймфорки делают (SFC в Vue, и даже если взять тот же jsx в реакте — здесь тоже нужна компиляция)

Боюсь что вы путаете компиляцию и транспиляцию. Никакой JSX и даже SFC во Vue и близко не делают то, что делает Svelte. Первый по сути превращает декларативные определения <Component /> в императивные вызовы React.createElement(). Второй всего лишь другой вид записи new Vue(options).

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

Интересное умозаключение. Поделитесь на чем оно основано? Jquery — это низкоуровневая библиотека-обертка над императивными манипуляциями в DOM, которая склоняла нас писать в event-based стиле. Svelte — это высокоуровневый компилятор SFC в ванильные компоненты без зависимостей, который склоняет к использованию реактивного декларативного state-based программирования. Я бы хотел узнать цепочку рассуждений, которая склонила вас полагать, что Svelte ближе к Jquery, нежели к React/Vue/Angular.
У Svelte, равно как и множества других реактивных фреймворков, есть большой недостаток — это динамическое (пере)создание элементов при обновлении их содержимого. К примеру, даже сравнительно статический фрагмент из банального &lth1>Hello {name}&lt/h1> превращается в такой код:
c() {
	h1 = element("h1");
	t0 = text("Hello ");
	t1 = text(name);
	t2 = text("!");
},

m(target, anchor) {
	insert(target, h1, anchor);
	append(h1, t0);
	append(h1, t1);
	append(h1, t2);
},

Вопрос — зачем? Если элемент статический и долгоживущий — почему на этапе компиляции не создать его один раз и потом не менять только содержимое, храня только ссылку на единожды созданный элемент?

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

Собственно сам browser намного быстрее всё отрендерит и построит из html, чем из js-кода, изменения только контента намного быстрее чем полное пересоздание элементов.

Пока же, увы, тенденция такова что темплейты в html просто тупо транслируются в js, фактически убивая всё то хорошее ради чего был создан собственно html (попробуйте ради интереса сделать в свелте &ltdiv>static text&ltdiv> — получите тоже кусок js).

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

m — это операция mount, она выполняется только 1 раз. Смотрите функцию update, там всё именно так как вы хотели!

Если переменная name изменяется, элемент будет пересоздаваться — весь, снова и снова — в этом я и вижу проблему.

Нет, не будет:


        p(changed, ctx) {
            if (changed.name) {
                set_data(t1, ctx.name);
            }
        },

Если вы сомневаетесь по поводу set_data — вот её реализация:


export function set_data(text, data) {
    data = '' + data;
    if (text.data !== data) text.data = data;
}
UFO just landed and posted this here
Ok, хорошо — но остается всё же массивный объем кода для создания даже статики. Банальный
<div>static text</div>
создается посредством js:
div = element("div");
div.textContent = "static text";
т.е. для сравнительного большого темплейта будет куча кода. А куча кода это куча кода — даже если он выполняется один раз.

Зачем такой огород если можно просто скормить браузеру собственно html с нужными вставками?

Банальный <div>static text</div> на самом деле не так уж прост. Браузер создаст все те же DOM-элементы внутри, что и мы сами руками, но при этом у нас не будет возможности переиспользовать div и обновить только textContent.


Еще есть вот такой доклад, например, в котором рассказывается об этом больше: https://habr.com/en/company/oleg-bunin/blog/310868/

Если он статический, зачем его переиспользовать?

Совсем нет. Существует ссылка на текстовую ноду — в нашем случае t1. Эта нода и обновляется, нет необходимости заново рисовать весь компонент:


...
if (changed.name) {
    set_data(t1, ctx.name);
}
...

PS: долго писал… уже объяснили

Я рад, что кто-то смотрит на скомпилированный код, прежде чем теоретизировать по поводу работы Svelte. Тот фрагмент кода, что вы указали, выполняется один раз при инициализации экземпляра данного компонента. Далее работа ведётся уже точечно с нужными нодами, обычно с текстовыми(напомню, что сам текст в элементе — это отдельная нода). Эти функции просто сокращения нативных функций Javascript для прямой работы с DOM: append(h1,t0) это не что иное, как h1.appendChild(t0).
Если использовать в лоб node.innerHTML('...'), то потом всё равно придется распарсивать DOM, чтобы получить ссылки на ноды(иначе как работать фреймворку?). Поэтому используется метод document.createDocumentFragment() — тоже достаточно производительный и все ссылки имеются сразу.
Ещё можно использовать SSR с гидратацией. Это Svelte тоже умеет.

чтобы получить ссылки на ноды(иначе как работать фреймворку?)

getElementById() же, нет? Темплейт в слегка переработанном виде отдаётся браузеру, где надо расставляются id, по этим id один раз (при инициализации) берутся объекты, а дальше меняется только то что должно, без репарсинга. Компилятор ведь всё равно разбирает темплейт, так что создать эффективный код не должно быть проблемой.

Для любых контейнеров где внутри нет HTML достаточно будет менять innerText, а не innerHTML, можно даже делать это более эффективно, если «добавить воды»:
<div>Hello, {name}!</div>

транслируется в что-то типа:
<div>Hello, <span id="var-name" ></span></div>

после чего меняется только innerText в #var-name (адрес которого берется один раз).

И в любом случае, браузер гораздо быстрее и эффективнее разберет фрагмент html чем вы «вручную» будете его создавать в js посредством манипуляции DOM. Проведите эксперимент — создайте динамически (js) таблицу с большим количеством элементов, а потом её же но уже через установку innerHTML — разница будет ощутима.

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

Это зависит от приложения, часто бывает так что изменяемый контент составляет сравнительно небольшую часть по отношению к статике. Яркий пример — некоторые dashboards, где собственно статика (стили, маркап) занимают 70-80%.

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

. Проведите эксперимент — создайте динамически (js) таблицу с большим количеством элементов, а потом её же но уже через установку innerHTML — разница будет ощутима.

Не поленился — провёл. Вставка 1000 Div. Мои результаты: innerHTML — 4ms, fragment — 9ms. Вы правы — разница более 2 раз не в пользу fragment. Но есть пара моментов:


  1. Бенчмарк не учитывает последующую работу с getElementById() в случае innerHTML
  2. После фрагмента у нас уже есть ссылки на все ноды в документе и не надо выдумывать ничего с getElementById() — что тоже заняло бы какое-то время.
  3. 9 мс это реально очень-очень-очень мало.
getElementById() можно вызвать только один раз — потом переиспользовать результат (элемент-то статичен).

И да, 9 ms это конечно мало — но и элементов всего 1000. А если их 1000 и в каждом ещё по два десятка вложенных (если это табличка с расчётом на модификацию значений пользователем)?

А теперь представьте что это выполняется не на топовом железе а на средненьком мобильном или просто нетбуке — эти 9 ms легко могут превратиться во все 100 ms.

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

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

UFO just landed and posted this here
Разметка нужна не только для редактирования, если это сложная таблица с несколькими колонками, вероятно с иконками, разными шрифтами или цветами — вот вам уже минимум десяток элементов на строку.

А вот насчёт 1000 строк — это зависит. К примеру, когда я просматриваю события системы мониторинга или журналы — то бывает и по 10 тыс. строк, это гораздо удобней чем листать по 100. Опыт показывает что отдача браузеру маркапа (созданного либо на сервере либо в самом js) существенно ускоряет рендеринг.

Я думаю если появится такой «вумный» компилятор-фреймворк который всё оптимизирует примерно так как я описываю (код только там где невозможно обойтись html) — он очень быстро захватит мир.
UFO just landed and posted this here
Наличие кастомного viewport, как минимум, лишает возможности использовать поиск средствами браузера, так что с этой точки зрения от пагинации он не отличается.

В случае же если хочется их смотреть оффлайн — всё равно придётся вытащить всё сразу, все 10 тыс, так почему бы сразу их и не показать, благо скроллинг и поиск встроены и шустрее любой реализации на js?

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

Да или просто первая страница яндекса — всё влезает на один экран, но там только одого js уже 500 кб (причём минимизированного) — вот о чём речь.

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

Может, вы привыкли смотреть страницы на чём-то с процом типа i8700 и 32GB памяти, но есть масса людей у которых всего 2G (из них половина сожрана системой, и ещё четверть всякой служебной фигнёй) и нечто вроде атома/арма — там всё это вызывает большую боль.

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

UFO just landed and posted this here
Есть предположение, что это скрипты яндексовской рекламы и фреймворки тут ни при чём.

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

Гора элементов с кучей классов и атрибутов не имеет никакого отношения к фреймворкам.

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

Вы хотите обвинить меня в том, что я пишу неоптимизированные приложения?

Извините, ничего личного — речь шла об абстрактном «вы».

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

Какая бизнес-логика? Это UI, клиентская часть — там не должно быть бизнес-логики, разве что минимальная валидация. Задача браузера — это быстро и эффективно отображать UI, с учётом динамического изменения элементов — всё. Любой js который к нему отправляется должен решать только эту задачу, не более. Конечно, SPA/WebApp слегка другой вопрос, но фреймворки в основном используются не для SPA, и логика всё равно на стороне сервера.
UFO just landed and posted this here
Скорость, размер…
А есть сравнение с Preact?
Он компактый и шустрый. Интересно, насколько тяжел Svelte в случае десятка компонент?
Только в отличии от Svelte, Preact практически ничего не умеет. Сравнивать функционал этих двух инструментов сложно.
Возможно пропустил, а как с отладкой обстоят дела? Или придётся отлаживать скомпилированный код?

Sourcemaps имеются — всё в порядке.


Скриншот

image

UFO just landed and posted this here

Такого нет. Покажите, пожалуйста, кейс для примера. Может оно и не надо =)

UFO just landed and posted this here

А, ну так в Svelte то же самое же. Любому атрибуту можно задавать javascript выражение. Просто это вроде не называется привязкой.


<div ... aria-selected={option.selected} ... </div>
UFO just landed and posted this here
Такой вопрос, а почему бы не сделать расширение для TypeScript или его форк для решения ваших задач? Так бы вы сэкономили время
Потому что это два разных инструмента, решающих совершенно разные задачи. Кроме того, ограничения TS не позволили бы на его основе сделать то, что хочется.
Есть шанс, что появится альтернатива Ember-like условному рендерингу, циклам и прочему? Имхо подобные конструкции в виде директив выглядят более читаемыми, не создавая лишние вложенности.

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

В Ember разве не пропатченые Handlebars? А в нем условия и циклы больше похожи на Svelte. Вот во Vue/Angular да, директивы.
Sign up to leave a comment.

Articles