Svelte 3: Переосмысление реактивности

Автор оригинала: Rich Harris
  • Перевод
Буквально на днях произошло большое событие для сообщества SvelteJS, да и вообще, как мне кажется, для всего современного фронтенда — долгожданный релиз Svelte 3! Посему, под катом перевод статьи автора Svelte и прекрасное видео с его доклада на YGLF 2019.



Наконец-то он здесь


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

Мы думаем, он вам понравится.

Что такое Svelte?


Svelte — это компонентный фреймворк, похожий на React или Vue, но с важным отличием. Традиционные фреймворки позволяют вам писать декларативный state-driven код, но не без наказаний: браузер должен выполнить дополнительную работу для преобразования этих декларативных структур в манипуляции с DOM, используя техники, такие как virtual DOM diffing, которые проедают имеющийся бюджет кадров отрисовки и добавляют обязанностей сборщику мусора.

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

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

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

Чтобы эта возможность стала реальностью, нам сначала нужно было переосмыслить концепцию, лежащую в основе современных UI фреймворков: реактивность.


Доклад «Переосмысление реактивности» на You Gotta Love Frontend Code Camp 2019

Перемещение реактивности в язык


В предыдущих версиях Svelte, вы должны были сообщить компьютеру, что какая-то часть состояния изменилась с помощью вызова метода this.set:

const { count } = this.get();
this.set({
  count: count + 1
});

Он заставлял компонент реагировать. Кстати говоря, this.set практически идентичен методу this.setState, который использовался в классическом (до хуков) React:

const { count } = this.state;
this.setState({
  count: count + 1
});

Тут есть важные технические различия (как я объясняю в видео выше — React не реагирует), но концептуально это одно и то же.

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

Поэтому мы сделали шаг назад и спросили себя, какой тип API был бы лучшим для нас… и поняли, что лучший API — это отсутствие API. Мы можем просто использовать язык. Обновление значения count и всех вещей, которые зависят от него, должно быть простым:

count += 1;

Поскольку мы являемся компилятором, мы можем сделать это, осуществляя фактическое присваивание за кулисами:

count += 1; $$invalidate('count', count);

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

Новый облик


Не только компоненты получили подтяжку лица. Сам Svelte теперь имеет совершенно новый внешний вид благодаря удивительной дизайнерской работе Achim Vedam, создавшего новый логотип и веб-сайт, который переехал со svelte.technology на svelte.dev.

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

Обновление с версии 2


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

Такое решение далось нам не легко: надеюсь, что, испытав Svelte 3, вы поймете, почему мы сочли необходимым порвать с прошлым.

Все ещё впереди


Каким бы изнурительным ни был этот релиз, мы ещё не закончили. У нас есть масса идей как генерировать код умнее, более компактно, и длинный список пожеланий. Sapper, наш фреймворк для приложений в стиле Next.js, всё ёще находится в процессе обновления для использования совместно со Svelte 3. Проект сообщества Svelte Native, который позволяет писать приложения для Android и iOS на Svelte, продвигается вперед и заслуживает более полной поддержки со стороны ядра.

У нас пока нет множества расширений для редакторов, подсветки синтаксиса, наборов компонентов, devtools и т. д., которые есть у других фреймворков, и мы должны это исправить. И мы действительно хотим добавить первоклассную поддержку TypeScript.

Несмотря на всё это, мы считаем, что сейчас Svelte 3 — лучший способ создания веб-приложений. Потратьте час, чтобы пройти учебник и мы надеемся, что убедим вас в этом. В любом случае, мы хотели бы видеть вас в нашем Discord чате, русскоязычном канале Telegram и на GitHub — добро пожаловать всем, особенно вам.

P/S — Еще немного полезных ссылок


Документация на русском по Svelte 3.
Учебник на русском по Svelte 3.
Примеры на русском по Svelte 3.

За работу над русскоязычным сайтом отдельное и большое спасибо AlexxNB! Гип-гип ура!
Поделиться публикацией

Комментарии 288

    0
    Слишком круто звучит, кто-то использовал уже в бою? Какие подводные камни?
      +1
      Маленькая экосистема пакетов. А для новой версии тем более – еще нужно время пока все основные библиотеки обновятся, пока еще даже не все пакеты в официальной организации github.com/sveltejs переехали

      В общем, типичная ситуация курицы и яйца: мало пакетов потому что мало пользователей, а мало пользователей потому что мало пакетов.
        0
        Мы используем в бою начиная с бородатой 1.x.x. Полет нормальный! Причем настолько, что сперва Svelte полностью вытеснил RactiveJS, который мы использовали аж с 2013 года. А теперь по-тихоньку вытесняет Vue — скорее всего все новые проекты будем делать на Svelte 3 вместо него. Сейчас для 2-х проектов используем и Sapper, с ним пока проблем больше, потому что Sapper 3 еще в альфе, но думаю все наладится в ближайшее время.

        p/s Под мы я имею ввиду:

          0
          Насколько проблематично переписать код проекта с React на Svelte?
            0
            Сложно сказать, потому что надо знать насколько код проекта завязан на экосистему реакта. Могу сказать только, что, в целом, Svelte значительно мощнее из коробки, а аналог React компонента на Svelte будет разработать проще и раза в 2 меньше кода.
            +1
            Вас в презентации указали.
            +1
            Какие подводные камни?

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

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

              Кроме того, так как Svelte — это не рантайм фреймворк, он может себе позволить иметь бесконечное кол-во фичей, без неминуемого раздувания бандлов свою пользователей. Фичи, которые не используются, просто не попадут в итоговый код.
                0
                Фичи, которые не используются, просто не попадут в итоговый код.

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


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

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


                Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability.

                Понятно, что это как бы не баг, а фича, но разные проекты требуют разных фич.

                  0
                  Если вы используете все фичи, то они все в бандл и попадут, и тогда де-факто нет разницы с тем, что просто бы загрузили одну js-ку со всем функционалом :)

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

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

                  Это касается только непосредственного вывода строки html виде выражение. Учитывая что на npm +100500 подобных пакетов, не имеет смысл включать их в Svelte, тем более что никаких дополнительных действий для их использования не требуется:

                  <div>{@html sanitize(html)}</div>
                  
                  <script>
                    import sanitize from 'sanitize-html';
                  
                    let html = `<strong>hello world</strong>`;
                  </script>
                  
                    0
                    Это касается только непосредственного вывода строки html виде выражение.

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


                    И все же разница есть. Во-первых, все фичи сразу использовать не получится, а значит есть возможность расти прогрессивно.

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

                      0
                      Речь о том что свелте сам по себе кроме рендера ничего, фактически, не содержит.

                      По сути да, это так. Все же это «UI framework». Хотя конечно есть еще встроенное управление стейтом, но тоже преимущественно для UI. С другой стороны, UI — это львиная доля фронденда. Такие вещи как роутинг или общение с сервером можно легко организовать поверх Svelte с помощью парочки stand-alone библиотек, как pagejs или axios.

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

                      Тут вообще сложно с чем-то не согласиться. Можно только добавить, что Svelte совершенно точно подходит для всего того, для чего подходят React или Vue. Angular все же играет немного в другой лиге.

                        +1
                        Можно только добавить, что Svelte совершенно точно подходит для всего того, для чего подходят React или Vue. Angular все же играет немного в другой лиге.

                        Ну да, если сравнивать с react и vue то разница, конечно, сильно меньше, чем при сравнении с ангуляром, backbone и другими "толстыми" фреймворками.

            0

            Разве не будет ситуаций когда эти $$invalidate ставятся там где совсем не надо? Если уж есть свой компилятор, то почему бы не ввести новое ключевое слово? Например, я когда-то делал плагин для babel который заменял такой код:


            cell firstName = 'Matroskin';
            cell lastName = 'Cat';
            
            cell fullName = firstName + ' ' + lastName;
            
            console.log(fullName);

            на такой:


            const cellx = require('cellx');
            const firstName = new cellx.Cell('Matroskin');
            const lastName = new cellx.Cell('Cat');
            
            let fullName = new cellx.Cell(() => firstName.get() + ' ' + lastName.get());
            
            console.log(fullName.get());

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

              +3

              При создании Svelte была задача иметь полностью валидный синтаксис Javascript, поэтому нет никаких чужеродных вкраплений. Да, тут есть моменты, когда привычные конструкции языка работают весьма неожиданно, но при этом, на мой вкус, очень логично.
              Полагаю, что $$invalidate проставляется только для переменных, которые задействованы в шаблонах, либо в реактивных объявлениях(aka вычесляемые свойства), а это не видится мне сложной задачей.

                0
                только для переменных, которые задействованы в шаблонах

                да, тоже подумал об этом после отправки сообщения. Тогда всё норм, единственно что переменная может использоваться в шаблоне, но быть внутри условия, которое сейчас неактивно. Тогда $$invalidate сработает, но вряд ли там что-то страшное (изменение DOM) произойдёт.

                  +3
                  Ответ на главный вопрос жизни, вселенной и всего такого — undefined

                  Как красиво! Можно даже сказать, философски

                    –2
                    Это так и надо?
                      +1
                      Конечно, это же пошаговый учебник. Если будете не только смотреть код, но и читать описание и кнопочки всякие там нажимать, то пойдете почему так.
                    +1
                    Не до конца осознал кейс, когда $$invalidate может проставляться там где не надо, вот мы пишем изменение какой-то переменной:

                    count += 1;
                    


                    Раз к ней было выполнено присвоение, нужно пересчитать DOM и реактивные переменные, связанный с ней. Поэтому дописываем сюда $$invalidate. Более того, внутри как бы еще проверяется, изменилась ли переменная по-настоящему и если нет, то ничего не происходит, поэтому, по идее, сам по себе вызов $$invalidate очень дешевый — мы точно знаем что нужно чекать и в какой момент времени.
                      0
                      Выше уже разобрались, что $$invalidate ставится только для переменных используемых в шаблоне и реактивных объявлениях. Всё норм)
                        0

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

                          0
                          Меняйте стейт не связанный с шаблоном, а потом в нужный момент выставляйте связанный. Вообще не люблю синтетические кейсы. Одно дело когда для каких-то бенчмарков придумывают, а другое дело если в диалоге.
                      –5
                      Удивительная выдержка у Рича — 37 минут говорит о том, что люди должны понимать уже через 5 минут после знакомства с Реактом. Желаю Svelte остановить это костыльное безумие.
                        +5
                        Либо меня не поняли, либо как раз поняли и обиделись. Я говорил о том, что перевычислять дерево каждый раз и искать изменения — это костыльнейшее решение, которое можно было придумать и написать на коленке как Proof of Concept лет 10 назад. Если я не ошибаюсь, уже в AngularJS была настоящая декларативность. Почему же большинство выбирало изначально костыльное решение, строит поверх ещё ворох костылей и упорно защищает это уродство? Все babel-плагины: JSX, react-css-modules, hooks.macro — это же всё маленькие шажки, пытающиеся сделать императивный React хоть немного декларативным. И даже Vue — продолжение всё тех же идей. Разве не очевидно, что нужно строить нормальное декларативное решение с самого низа?
                          0
                          Если интересно, есть и более радикальные идеи как комилировать реакт в императивный код: github.com/sokra/rawact

                          А вот обзывать React «костылями» и «уродством» не стоит. Люди используют его в продакшене и довольны, а что вы можете предложить им взамен?
                            0
                            Если интересно, есть и более радикальные идеи как комилировать реакт в императивный код: github.com/sokra/rawact

                            rawact можно скорее «помянуть» чем упоминать. маловероятно что эту штука когда-либо будет готова взять на себя компиляцию совершенно любого кода на React.

                            Люди используют его в продакшене и довольны, а что вы можете предложить им взамен?

                            Очевидно же, Svelte ;-)
                              +2
                              Вот, здесь уже можно поговорить и обсудить плюсы и минусы обоих технологий.

                              А в исходном комменте треда был обычный наброс «фреймворк Х – костыль». Так что дело тут не в обидчивости сообщества а в отсутствии конструктива.
                                0
                                Да, пожалуй. Мне конечно больше импонирует подход как на видео))
                              +4

                              Смотря в каком смысле "предложить". Как я уже сказал, настоящая декоративность, если я не ошибаюсь, существовала в Knockout и Angular. Можно было развивать эти идеи. Я думаю, что большинство просто повелось на мнимую простоту Реакта. Для первых шагов было проще понять, как он работает. Но конечная задача все равно гораздо более сложная. И в реальном мире Реакт обрастает кучей всего, что делает этот подход таким же сложным, как Ангуляр, но совершенно тупиковым. Вынос рендера в вебворкер для внесения десятка изменений в DOM этому подтверждение.


                              А ещё я всем рекомендую посмотреть, как устроен View-слой в уже много лет как полумертвом DerbyJS. Например, там нет костыльного key-property. Когда вы изменяете массив в моделе, на уровне шаблона уже понятно, какие изменения нужно внести в DOM. Зачем ещё что-то сопоставлять по ключу? Хорошая программа (в данном случае фреймворк) строится от интерфейса, а не интерфейс подстраивается под то, как программисту удобнее его реализовать. Имитация декларативности через императивщину — это именно второй случай. Заморачиваться с парсингом декларативного языка долго — проще перезапускать функцию рендера. Но в итоге все равно люди обвешались babel-плагинами.


                              Большое спасибо за ссылку.

                                +2
                                «настоящая реактивность» в первом ангуляре? при этом 40к вотчеров на странице.
                                На%$й эту вашу «настоящую декларативность» в первом ангуляре.
                                  +1

                                  Я не очень понял, что именно вам не нравится в 40к вотчерах. Проблема Ангуляра была ровно такая же, как и Реакта, только в Model слое, а не View. Ангуляр диффал данные, Реакт — виртуальный DOM. И то, и другое очевидно будет тормозить. Но дифф данных — это более хорошая архитектура. Потому что было несколько способов решить проблемы, оставив тот же подход в View. А Реакт — это шаг назад, потому что рано или поздно его все равно придётся выкинуть и сделать нормальную декларативность.

                                    0
                                    Я не очень понял, что именно вам не нравится в 40к вотчерах.

                                    В 40к вотчеров мне не нравится 40 тысяч вотчеров. Это тормозит и это убого.

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

                                    Какая нахер «нормальная деклративность» в браузере?? CSS? Удачи.
                                      0

                                      Зачем же вы создание 40к вотчеров? Если у вас столько компонентов, то чем это отличается от Реакта, который также будет тормозить?


                                      В чем проблема обеспечить настоящую декларативность шаблонов с помощью джаваскрипта в браузере?

                                  0

                                  Реактивные подписки, может быть, и есть идеологически более верное решение, но являются ли они решением проблем пользователей? По большому счету, мы пишем на высокоуровневом Javascript в котором происходит очень много всего лишнего, но оправдывает ли это переписывание на ассемблер (WebAssembly в частности)? В большинстве случаев – нет. То же самое и со Svelte.


                                  Но в итоге все равно люди обвешались babel-плагинами.

                                  О чем вы говорите? В стандартом пресете, который используется большинством разработчиков, я вижу только плагины для ES-next синтаксиса и JSX, никакой магии для оптимизации.

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

                                      Так-то любой декларативный код будет скомпилирован в императивный)

                                        +1
                                        Пожалуй не любой. Например, есть такие штуки к LitElement, который использует lit-html на template literals и несмотря на то, что для использования тех же декораторов ему все равно нужен препроцессинг, его шаблоны никак не компилируются/транспилируются и остаются условно декларативными в рантайме:

                                        import { LitElement, html, property } from 'lit-element';
                                        
                                        export class HelloWorld extends LitElement {
                                          @property() name = 'World';
                                        
                                          render() {
                                            return html`<p>Hello, ${this.name}!</p>`;
                                          }
                                        }
                                        


                                        Тот же JSX, конечно же транспилируется в JS вызовы, но в итоге эти вызовы и сам механизм VDOM нельзя назвать низкоуровневыми.

                                        Поэтому в моем тезисе важно все, Svelte — это именно высокоуровневое и достаточно декларативное написание компонентов с последующей компиляцией их в низкоуровневый и императивный код.
                                          +1
                                          Да уж, за абстрактными словами вы имели ввиду конкретные вещи.) Теперь я вас понял.
                                        +4
                                        <button on:click={handleClick}>
                                            Clicked {count} {count === 1 ? 'time' : 'times'}
                                        </button>

                                        Это не декларативный код. Не обманывайте, ни себя, ни окружающих.

                                          +1

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

                                            –1
                                            Наличие программной логики. А вот привязка обработчика события вполне себе декларативна.
                                              0

                                              Привязка декларативна, я имел ввиду сам обработчик. Что за "программная логика"?

                                                0
                                                Да, ваш пример не 100% декларативный, но ведь где-то эта логика должна находиться, правда? Мы можем переписать пример, сделав шаблон более декларативным:

                                                <button on:click={handleClick}>
                                                    Clicked {count} {btnText}
                                                </button>
                                                
                                                <script>
                                                  let count = 0;
                                                
                                                  $: btnText = count === 1 ? 'time' : 'times';
                                                
                                                  function handleClick() {}
                                                </script>
                                                


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

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

                                                    0

                                                    А почему вы уверены, что выражение в скобках может быть любым кодом? DerbyJS, например, парсит джаваскрипт в скобках как декларативное выражение. Вплодь до того, что count + 1 можно присвоить значение 2 и count станет равным единице

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

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

                                                      Да и вообще, можно назвать это не логикой, а просто гибким шаблоном, на «for/if/switch» в шаблоне же никто не жалуется и тут тот же «if» (тем более изменение данных не происходит, чисто представление даннных).
                                                        0
                                                        Дак это же наоборот хорошо

                                                        Мы вроде как не обсуждали вопрос, что хорошо, а что плохо.


                                                        Что за преимущества?

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


                                                        Svelte по видимому получает список зависимостей.

                                                        Речь о прикладном коде. Для компилятора-то любой АСТ — не более чем декларации.


                                                        И это решаемо.

                                                        Каким образом, если у вас в шаблоне зашита конкретная логика вычисления?


                                                        Да и вообще, можно назвать это не логикой, а просто гибким шаблоном

                                                        Как ни называй, суть не меняется.


                                                        на «for/if/switch» в шаблоне же никто не жалуется

                                                        Жалуется. Банальный пример: вам нужно в зависимости от флага переставлять две части шаблона местами.

                                                          –1

                                                          Вот как раз на for/if/switch жалуются, декларативно будет map, match, branch, да просто isOpen && div или тернарик

                                                            0
                                                            В примере выше как раз тернарник использовался, но это все равно не достаточно декларативненько по мнению уважаемого vintage.
                                                          +3
                                                          К описаным вами сомнительным преимуществам декларативности когда в шаблоне не может быть js-выражений добавляется существенный минус — необходимость именования — если раньше можно было указать нужное выражение прямо в шаблоне то теперь придется придумать имя и по этому имени вынести в другое место нужное выражение. А необходимость именования создает точку ручной синхронизации — каждый раз меняя это имя нужно не забыть переименовать в шаблоне (или наоборот). А если потом было решено убрать кусок шаблона то нужно не забыть убрать в другом месте лишние именованные выражения которые были вынесены из шаблона.
                                                          Именование хорошо когда оно убирает логическое дублирование кода (когда изменение потребует ручной синхронизации кода в разных местах). В остальных случаях лишнее именование чего либо не было приводит только к усложнению. Например необходимость именовать экшены в редаксе против возможности изменить состояния по месту как mobx-е, или необходимость именовать классы и выносить стили в отдельные местах против возможности указать нужные стили инлайном рядом с тегом или необходимость именовать отдельные роуты в rest-e против возможности вызвать функцию как в rpc. Все это добавляет лишнюю косвенность которая увеличивает количество мест изменения кода в git diff-e а это значит что увеличивается количество неявных связей (программисту нужно держать в голове все места которые требуют изменений при добавлении или изменении/удалении такой-то фичи)
                                                            +2

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

                                                              –2

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


                                                              Если раньше можно было писать всё в одной процедуре, то теперь приходится придумывать имена методам.


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




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

                                                                –1

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

                                                        0
                                                        Дмитрий имеет ввиду, что на 100% декларативным может быть что-то вроде $mol treeview:

                                                        $my_hello $mol_view
                                                        	sub /
                                                        		<= Name $mol_string
                                                        			hint \Name
                                                        			value?val <=> name?val \
                                                        		<= message \
                                                        


                                                        vintage Напишите решение этого примера на treeview для общего развития? Ну и чтобы Balek уже не смог спать спокойно по ночам, зная что такие вещи существуют в нашем мире.
                                                    +1

                                                    Так тут же дело в абстрактной идеологии. Грубо говоря, сложность программы на Реакте — O(n), хотя проблема решается за O(1). И это заложено в самой архитектуре.

                                                      0

                                                      Это в идеальном вакууме.
                                                      В реальности обязательно встретятся разработчики которые намудрят с $: синтаксисом (например) и убьют всю производительность.
                                                      В реакте хватает систем «защиты от дурака» и предупреждений, а как с этим дела обстоят в Svelte? (хотя это скорее вопрос к PaulMaly)

                                                        +1
                                                        Я говорю о том, что очень много усилий вкладывается в развитие тупиковой идеи Virtual DOM diff. Если бы последние пять лет сообщество вкладывалось в развитие настоящей реактивности, то были бы защиты от дурака. И, скорее всего, они были бы лучше тех, что есть сейчас. Потому что декларативный код даёт больше возможностей для автоматического анализа, оптимизации и т.п.
                                                          0

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


                                                          С другой стороны, пример rawact показывает, что и API react достаточно декларативное для таких оптимизаций, если будет надо. А будет ли надо? Вот не факт, потому что по моему опыту проблемы обычно скрывались в Redux и аналогичных стейт-контейнерах, а не в VDOM. Чинить надо там где сломалось, а не там где это кажется легко

                                                            +1

                                                            Видимо у нас очень разные определения тупиковости. Потому что мне время (первые минут 30) уже все показало. Например, когда для оптимизации, нужно в shouldComponentUpdate внести то, что и так очевидно из render-функции. Или необходимость указывать key-property при рендере массива. Или перечислять значения вторым аргументом в useCallback. Эти проблемы нужно решать в фундаменте, а не плагинами к бабелю. Тогда будет архитектура, а не набор костылей.

                                                              0
                                                              Потому что мне время (первые минут 30) уже все показало

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


                                                              В докладе Rich Harris показал один утрированный пример. Много ли пользователей с этим столкнутся? Не факт, я написал довольно много развесистых реакт-компонентов и ни одного shouldComponentUpdate. И без этих приёмников все работает нормально и поэтому костылями мне не кажется

                                                                0
                                                                По-моему пример с filtred и useMemo не такой уж и утрированный.
                                                            0
                                                            Если бы последние пять лет сообщество вкладывалось в развитие настоящей реактивности, то были бы защиты от дурака.

                                                            Сообщество вкладывалось в развитие настоящей реактивности с 2010 года, когда вышел AngularJS, Knockout и Ember. Мне, например, трех лет эквилибристики с scope.$apply хватило, чтобы понять, что «настоящая реактивность» – это как минимум не тривиальная задача.
                                                              0

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

                                                                0
                                                                Да, если кратко. Если чуть точнее – указывать, что нужно перепроверить данные на изменение.
                                                                Ну и наличие оберток на половину стандартных функций вроде fetch/setTimeout/setInterval, чтобы этого не делать в ответ на AJAX-запрос/таймаут.
                                                                  0
                                                                  В Knockout вам тоже приходилось это указывать?
                                                                    0
                                                                    C Knockout, я не работал дальше туториала. Если там этой проблемы нет, то жаль что взяли первый ангуляр на тот проект, а не его.
                                                                      +1
                                                                      Конечно нет. Реализаций реактивности — много разных вариантов.
                                                                        +1
                                                                        И у всех свои минусы.
                                                            0
                                                            Раз уж меня упомянули))

                                                            В реальности обязательно встретятся разработчики которые намудрят с $: синтаксисом (например) и убьют всю производительность.

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



                                                            В реакте хватает систем «защиты от дурака» и предупреждений, а как с этим дела обстоят в Svelte?

                                                            Никак, Svelte просто хорошо работает:



                                                              0
                                                              Не убедили. «Svelte просто хорошо работает» звучит примерно как «у нас никогда не бывает багов».

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

                                                                Согласен, именно так и звучит.))) Но не знаю как еще кратко высказать ту мысль, которую автор Svelte высказывал почти 40 минут. Можно еще наверное так, единственный способ сделать что-то быстрым и надежным — избавиться от всего лишнего. В этом смысле сравнение моторов Теслы и ДВС, имхо, очень показательно.

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

                                                                Тут все просто, что-то работает не так как надо, смотрим итоговый код, находим узкое место, пишем issue или PR. Мне кажется это одна из ключевых фишек Svelte. Так как рантайма практически нет (да вот он весь в приципе), то остальное это кодогенерация для каждого конкретного случая и ее всегда можно легко прочитать, понять как работает и придумать как сделать, чтобы работало лучше. В отличии от черных ящиков в рантайме, куда ты передаешь на вход что-то и адская машина VDOM пыхтит и пытается делать свое дело для каждого кейса на свете.
                                                    0
                                                    Обращал внимание, что те кто пишут на React довольно обидчивые ребята. Не обращайте внимания.
                                                      0
                                                      ;-)
                                                        +4
                                                        Интересно, как бы Вы отреагировали, если бы кто-то без всяких обоснований назвал Svetle “костыльным безумием”? Мне это напоминает старый анекдот: “всем хорош Иван Васильевич. Только не любит, когда его по голове бьют”…
                                                          0
                                                          Это происходит постоянно, даже в это треде ниже. Вообще если вы посмотрели видео, автор Svelte прекрасно иллюстрирует в чем костыльность React и VDOM в целом. Если вам нравится как это работает — дело ваше. Svelte имеет другой взгляд на довольно очевидные вещи и показывает отличные результаты.
                                                            0
                                                            Я к тому, что минусы, скорее всего, за голословную категоричность, а “обидчивость” — свойтсво человека защищать свой основной инструмент от необоснованных (с его точки зрения) нападок.

                                                            P.S. Если задача — что-то донести до оппонента, то голословные выпады точно не достигнут цели….
                                                              0
                                                              Тут я согласен. Нужно обосновывать. И не так, что «вот мне кажется должно работать так как я привык писать», а «почему это работает не очень оптимально и лучше сделать так».
                                                              –1
                                                              показывает отличные результаты.

                                                              Real world example please.
                                                              Типа, вот тут реакт тормозит, а свилт решает.
                                                                +1

                                                                Посмотрите видео.

                                                                    –1
                                                                    Любопытно, что по вашей же ссылке есть информация, что эти тесты производительности устарели, уже есть за 2019-й год. Почему вы решили привести более старые и менее актуальные данные? Может потому, что разница в скорости оказалась не такой выдающейся, как хотелось бы?
                                                                      0
                                                                      Может потому что мне этот вопрос задают далеко не первый раз и эта ссылка у меня сохранена ещё с того года?

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

                                                                      Вижу Vue и Angular обновились и немного подтянулись, но там просто какая-то старющая версия Svelte и уже есть планы обновить прилагу до Svelte 3. Тогда и будем смотреть.
                                                                        0
                                                                        Прошу прощения, но мы смотрим по одной и той же ссылке? Потому что я вижу React + Mobx по производительности получил 91 балл, ровно столько же, сколько и Svetle. Так что откуда взялось ваше “всё также тормозит” — совсем не понятно.

                                                                        Про размер кода — согласен, разница существенная.
                                                                          0
                                                                          Да, сорян, по привычки искал React в конце списка, ну и нашел там React + Redux c 80 баллами.

                                                                          Вообще, первый пункт всегда был немного tricky. Все проекты располагаются на разные серверах, а меряем мы FMP. Получается очень многое зависит от сервера и от сети. Например, я сам проверил на тех же настройках Lighthouse: и получилось что реализация на React + Mobx получила 69 баллов, а на Svelte 81 балл:





                                                                          Вполне возможно, что если вы запустите у себя, значения будут другие. Однако очень сомневаюсь что есть вариант, когда React/Mobx получит больше чем Svelte.

                                                                          Кроме того, есть ведь и другие метрики. В данном сравнении это LoC и Size, но еще есть потребление памяти и время запуска, которое у Svelte находится на уровне VanillaJS реализаций.

                                                                          На самом деле Svelte не старается быть абсолютно лучшим во всем среди всех, потому что это во-первых это невозможно, во-вторых большинство benchmark'ов — это притянутые за уши кейсы и микрооптимизации. Однако Svelte стремиться быть достаточно хорошим во всем, например, не просаживать память за счет оптимизаций перформанса и т.д., а быть «зелененьким» по всем показателям.
                                                                  0

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

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

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

                                                                    Мы первый раз попробовали Svelte на проекте виджета для сайтов, где полностью готовый виджет должен был весить в 5 раз меньше, чем один только React. А также на Smart TV, где VDOM либы довольно быстро посаживают память на дешевых моделях (коих абсолютное большинство рынка).
                                                                      0
                                                                      Это взвешенный подход. Просто создаётся впечатление, что некоторые люди пытаются представить фреймворк Х “серебряной пулей” (или панацеей). И вот такой категоричный подход может вызывать отторжение у большей части аудитории. Гораздо лучше просто акцентировать сильные стороны и указывать области, в которых этот фреймворк лучше подходит, чем категорически заявлять, что он является превосходным во всём…
                                                                        +1
                                                                        Я вообще ни разу не фанат переписывания всего и вся на новую свистелку. У нас, например, есть легаси проекты на Ractive и Vue, которые мы понаписали за 5 лет существования студии. Ни мы, ни заказчики не планируем их переписывать на Svelte 3.

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

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

                                                                        Могу сказать, что это сделать довольно просто. Я даже статью на эту тему писал.
                                                                  +1
                                                                  Полностью согласен со всеми, кто обвинил меня в резкости. Обычно стараюсь сдерживаться. Но в этой теме меня особенно задевает не то, какой Реакт плохой, а общественная слепота. Повторю, что сказал в первом комментарии: архитектурные проблемы Реакта должны быть очевидны любому программисту с самого первого знакомства. Рич их разжёвывает 30 минут, а в комментариях несколько человек продолжают отвечать, что я «без всяких оснований» ругаю Реакт. Почему это происходит?
                                                                +1
                                                                Просто никому не нравится когда что-то о чём хорошее мнение поливают грязью, даже если за этим стоят реальные факты. Можно же избегать клише типа «костыльный», особенно если есть, что сказать по делу. Лучше сравнивать и показывать какое ваше решение хорошее.
                                                                  –1
                                                                  Согласен, когда React появился и начал поливать грязью AngularJS, Backbone и Jquery, ребята оттуда тоже были не очень довольны. Все это конечно не красиво и вообще фу. Я думаю надо приводить факты, а уж люди пусть сами решают.
                                                              0
                                                              Похоже что под «настоящей декларативностью», ты понимаешь «как-то автомагически понимать что надо изменить в DOM».

                                                              Ну, пусть так. Тогда задача сводится к вопросу: «как, имея функцию f(x) = y, автомагически получить функцию f(delta(x,x')) = delta(y, y')». Называется это «incremental computing», подробнее тут: en.wikipedia.org/wiki/Incremental_computing

                                                              Если эту проблему решить в общем виде, мир станет другим. Например, materialized views в базах данных могли бы автомагически и недорого обновляться, решив почти все проблемы с перформансом на бекенде. Да чего далеко ходить — сам браузер мог бы гораздо эффективнее перерисовывать страничку при изменениях.

                                                              Но пока ученые бьются над частичными решениями этой проблемы, в JS-сообществе есть молодые, оптимистичные, и активные ребята, которые такие: «Я гений! Можно ж просто переменным isDirty ставить при записи в них, и все будет ок»! И самое страшное — они успевают написать целые фреймворки, с сайтами про них, конференциями про них. При этом — даже не удосужившись понять почему этот подход не будет работать, даже не попробовав погуглить что говорит по этому поводу наука. Даже не разобравшись почему факапнулись backbone и Angular — с точно такой же концепцией. Даже не попробовав даже на этом фреймворке написать что-то сложнее примеров и todo!

                                                              А потом другие молодые, поверившие им люди, начинают писать аппы, попадают на какие-то кейсы сложнее примера с count, начинают трахаться с этой автомагией, раскуривают все внутренности и хитрости фреймворка, героически проблемы решают. И только пройдя этот диалектический цикл, они понимают где и как их кинули.
                                                                +1

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

                                                                  +1
                                                                  потому с лёгкостью обновляемые инкрементально.

                                                                  Никто еще не придумал никакого хорошего способа "с легкостью инкрементально" обновлять шаблоны. Все время всплывают какие-то недостатки.

                                                                    +1

                                                                    Что вас не устраивает в существующих решениях? Даже если брать старый Ангуляр, там были проблемы с Model, но что было не так с View-слоем? Или чем вас не устраивает Svelte?

                                                            0
                                                            Svelte как то может отслеживать ф-ии?
                                                            <script>
                                                            	let name = 'test';
                                                            	const double = () => name + name;
                                                            </script>
                                                            <input type="text" bind:value={name}> {double()}
                                                            
                                                              +3

                                                              Да, конечно, код даже короче, чем вы написали:


                                                              <script>
                                                                  let name = 'test';
                                                                  $: double = () => name + name;
                                                              </script>
                                                              <input type="text" bind:value={name}> {double()}
                                                                +3

                                                                Вообще в реактивные объявления можно пихать всё, что угодно, например:


                                                                <script>
                                                                    let count = 0;
                                                                    $: console.log(count)
                                                                </script>
                                                                <button on:click="{() => count += 1}">+1</button>

                                                                Будет в консоль выводить значение count при его изменении

                                                                  +2
                                                                  Тут даже функция не нужна:

                                                                  <script>
                                                                    let name = 'test';
                                                                    $: double = name + name;
                                                                  </script>
                                                                  
                                                                  <input type="text" bind:value={name}> {double}
                                                                  

                                                                  REPL
                                                                    0
                                                                    А как сделать отслеживание «внешней» ф-ии, типа получения данных из стора и т.п.
                                                                    Так не работает:
                                                                    $: now = Date.now();
                                                                      +1

                                                                      $: отслеживает лишь изменение переменных из состояния компонента, входящих в соответствующие выражения. Очевидно в Date.now() нет таких переменных. Её вызывать надо, чтобы получить от неё что-то.
                                                                      Т.е. ваш пример выглядит примерно так:


                                                                      <script>
                                                                          let time = 0;
                                                                          setInterval(()=>time=Date.now(),1000);
                                                                      </script>
                                                                      
                                                                      {time}

                                                                      Про работу со стором и функциями в нём лучше расскажет документация

                                                                        0
                                                                        Тут нечего отслеживать, поэтому и не работает. Реактивные декларации работают, естественно, только со известным стейтом.
                                                                        0
                                                                        const getData = () => 'x';
                                                                        $: double = () => getData() + getData();
                                                                        

                                                                        Так тоже не работет, видимо в голове нужно будет держать где «computed», а где обычные ф-ии.
                                                                          +2
                                                                          Извините, но я никак не могу въехать какой кейс вам нужен. Функции это такие штуки, которые надо вызывать. Вызвал функцию — она вернула значение. Какой смысл следить за объектом функции, что там может измениться? При необходимости можно следить за переменной, которой эта функция где-то возвращает своё значение.
                                                                            0
                                                                            Тут тоже ничего не изменяется, почему double должен как-то изменяться? Svelte использует push-подход и не пересчитывает зазря значения.
                                                                              0
                                                                              Тут тоже ничего не изменяется, почему double должен как-то изменяться?
                                                                              Оно как минимум должно запускаться, но нет.
                                                                              Мы можем просто использовать язык
                                                                              Просто взять и вставить «кусок js» не получится, если у меня вызывается какая-то библиотека в коде, то нужна адаптация.
                                                                                +2

                                                                                Не должно там ничего запускаться. В $: должна быть хотя бы одна из переменных стейта. По определению. Тут же умный компилятор не увидел ни одной переменной в выражении и просто не стал включать в бандл ненужный код. Если бы вставили в разметку {double} то компилятор бы ещё и предупредил, что такой переменной нет. $: — это не переменная, чтобы присваивать ей значения функций, это конструкция для перезапуска выражения при изменении входящих в него переменных стейта.

                                                                                  0
                                                                                  Я понимаю как работает эта часть Svelte, я говорю про другое — если просто взять и вставить рабочий кусок js в svelte — он не заработает*, как мне показалось вначале (когда в некоторых других фреймворках оно работает).

                                                                                  какой тип API был бы лучшим для нас… и поняли, что лучший API — это отсутствие API. Мы можем просто использовать язык
                                                                                  Поэтому «просто использовать язык» — нужно с оговоркой, т.к. это все же «апи».

                                                                                  Но в целом идеи фреймворка очень интересные, посмотрим насколько он станет популярным, думаю первый его конкурент — vue (по типу отслеживания).
                                                                                    +1
                                                                                    Почему не заработает то? Вам почему-то захотелось вставлять именно в `$:`. Может конкретизируете свой пример с реальным кейсом? Попробуем разобраться.
                                                                                      0
                                                                                      Я не знаю, что вы имеете ввиду под «взять и вставить рабочий кусок js», но попробовал набросать пример Timeago компонента:

                                                                                      <script>
                                                                                        import { simple as format } from 'timeago-simple';	
                                                                                        export let date = new Date();
                                                                                      </script>
                                                                                      
                                                                                      <h1>Updated {format(date)}</h1>
                                                                                      

                                                                                      Рабочий пример

                                                                                      Это похоже на «взять и вставить рабочий кусок js»?
                                                                                        0
                                                                                        Я про ф-ии которые зависят от контекста, или вы в js только чистые ф-ии пишите?
                                                                                        let a = 1;
                                                                                        const b = () => a + 1;
                                                                                        // const c = () => b() + 1;
                                                                                        $: c = b() + 1;
                                                                                        
                                                                                        Очень простой и очевидный пример где функция зависит от контекста («c» зависит от «a» через «b»). Но Svelte это не может осилить, когда тот же ангуляр (да и реакт*) без проблем (как и в нативном JS).

                                                                                        Или вот ещё пример который не работает:
                                                                                        <script>
                                                                                        let user = {name: 'linux'};
                                                                                        let user2 = user;
                                                                                        </script>
                                                                                        <input type="text" bind:value={user.name} />
                                                                                        <h1>Hello {user.name}!</h1>
                                                                                        <h1>Hello {user2.name}!</h1>
                                                                                        
                                                                                        Тут нужно вручную привязку делать чтобы заработало (опять же в ангуляр и реакт нет этой проблемы).

                                                                                        Не объясняйте, я знаю почему это не работает (и как исправить), это «болевые точки» всех фреймворков основанных на «observable», я как раз поэтому и привел эти (не единственные) примеры.
                                                                                        И это негативно сказывается в больших проектах. Но все равно Svelte заслуживает что-бы его попробовать.
                                                                                          0
                                                                                          Я про ф-ии которые зависят от контекста, или вы в js только чистые ф-ии пишите?

                                                                                          Я все же не пойму, почему этот код должен работать? Функцию b никто не вызывает. Да и вообще не понятно, зачем вы тут используете $: он нужен не для таких вещей.

                                                                                          Очень простой и очевидный пример где функция зависит от контекста («c» зависит от «a» через «b»).

                                                                                          А вы вот так попробуйте:

                                                                                          let a = 1;
                                                                                          let b = () => a + 1;
                                                                                          $: c = b() + 1;
                                                                                          

                                                                                          Все же const, есть const. Зачем его делать реактивным, если он не может измениться?

                                                                                          Ну а ежели надо, чтобы при изменении a, пересчитывалась b, а за ней и c, тогда опять же так:

                                                                                          let a = 1;
                                                                                          $: b = () => a + 1;
                                                                                          $: c = b() + 1;
                                                                                          

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

                                                                                          Но Svelte это не может осилить, когда тот же ангуляр (да и реакт*) без проблем (как и в нативном JS).

                                                                                          Не знаю что там в Angular (кстати вы про 2 или 1? ), но в React никакой «без проблем» и в помине нет. Это код просто будет запускаться каждый раз, поэтому сорян, но это нам не нужно.

                                                                                          Или вот ещё пример который не работает:

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

                                                                                          <script>
                                                                                            let user = {name: 'linux'};
                                                                                            $: user2 = user;
                                                                                          </script>
                                                                                          <input type="text" bind:value={user.name} />
                                                                                          <h1>Hello {user.name}!</h1>
                                                                                          <h1>Hello {user2.name}!</h1>
                                                                                          


                                                                                          Мне почему-то кажется вы видео из статьи не посмотрели. Рич там примерно на таком же примере объясняет почему let user2 = user; в JS не может связать 2 переменные. Нету в JS destiny оператора, ну хоть тресни. А в Svelte по-сути есть.

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

                                                                                          Все по той же причине — код будет исполняться заново каждый раз. Собственно Рич Харрис в видео из статьи как раз про это и говорил, а также объяснял зачем мы придумали $:. Лично на мой взгляд если выбирать — исполнять один и тот же код на каждый пчих или написать $: вместо просто let (ваш пример), то для меня выбор очевиден.

                                                                                          это «болевые точки» всех фреймворков основанных на «observable», я как раз поэтому и привел эти (не единственные) примеры.

                                                                                          Сори, но я не увидел «боли». Вы привели сравнение постоянно вычисляемого кода на React/Angular и «лениво» вычисляемого кода на Svelte. Все ваши примеры совершенно просто решаются, поэтому никакой боли не вызывают совершенно.
                                                                                            0
                                                                                            Тут c не зависит от a через b потому что b не зависит от a.
                                                                                            Зависит — запуситие такой пример на js или любом другом языке — увидите что значение «c» меняется в зависимости от «a». Вообще это очевидно, вы просто пытаетесь оправдать фреймворк.

                                                                                            тогда нужно писать так:
                                                                                            Вот, нужно «адаптировать» и как я уже писал выше:
                                                                                            если просто взять и вставить рабочий кусок js в svelte — он не заработает*
                                                                                              0
                                                                                              Зависит — запуситие такой пример на js или любом другом языке — увидите что значение «c» меняется в зависимости от «a».

                                                                                              Если один раз запустить, то да, но что-то я не видел, чтобы JS умел отслеживать свойства и строить зависимости.

                                                                                              Вообще это очевидно, вы просто пытаетесь оправдать фреймворк.

                                                                                              А мне кажется, что вы приводите довольно странные примеры. И что? Только вы не пишете, в конструктивном ключе, типа, «а как сделать такое», а сразу считаете что что-то должно работать, только потому что вам так кажется.

                                                                                              Вот, нужно «адаптировать» и как я уже писал выше:

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

                                                                                                0
                                                                                                Если один раз запустить, то да, но что-то я не видел, чтобы JS умел отслеживать свойства и строить зависимости.
                                                                                                c() можете несколько раз запустить, все ранво завист от «a», это же не перменная.
                                                                                                А в DOM должно рендерится актуальное значение, для этого фреймворк и нужен.

                                                                                                А решил все ваши кейсы с минимальными изменениями
                                                                                                Вы подтвердили, что «js код без изменений может не заработать», я не знаю почему вы продолжаете спорить.
                                                                                                  0
                                                                                                  c() можете несколько раз запустить, все ранво завист от «a», это же не перменная.

                                                                                                  А кто будет перезапускать c(), в кокой момент и по какой причине?

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

                                                                                                  Так и есть, все всегда актуально.

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

                                                                                                  Вы так и не раскрыли, что значит «js без изменений». Типа взяли и копипаснули произвольный код откуда-то слева и решили что он должен работать так, как не свойственно js-у? Ну да, так работать не будет. Вы наверно мысли те как в Реакт, мол вот это код будет перезапускаться каждое изменение стейта:
                                                                                                  <script>
                                                                                                    let name = 'test';
                                                                                                    const double = () => name + name;
                                                                                                  </script>
                                                                                                  <input type="text" bind:value={name}> {double()}
                                                                                                  


                                                                                                  но почему он должен, если это все не обернуто в функцию?

                                                                                                  Если это просто js на странице (откройте консольку и закиньте его в верстку) сколько раз он отработает и будет ли пересчитана разметка и double при изменении name? Да нет конечно.

                                                                                                  Вы можете закинуть любой js код, но должны четко понимать, что так как это не обернуто в функцию, код будет исполнен единожды. Svelte не работает как React, а для отслеживания зависимостей и придумали $:.

                                                                                                  Я не понимаю с чем вы тут спорите.
                                                                                              0
                                                                                              а также объяснял зачем мы придумали $:
                                                                                              Не вы его придумали — это обычный «computed» который есть во многих фреймворках.

                                                                                              Лично на мой взгляд если выбирать — исполнять один и тот же код на каждый пчих или написать $: вместо просто let (ваш пример), то для меня выбор очевиден.
                                                                                              «Красота требует жертв», хотя там и жертв то нет при правильном подходе, вообщем минусы есть в каждом фреймворке — вы просто выбираете те минусы которые для вас менее важны.
                                                                                                0
                                                                                                Не вы его придумали — это обычный «computed» который есть во многих фреймворках.

                                                                                                Я имею ввиду на уровне нового апи, если вы не поняли. Собственно да, это аналог computed свойств из Svelte 2.

                                                                                                «Красота требует жертв», хотя там и жертв то нет при правильном подходе, вообщем минусы есть в каждом фреймворке — вы просто выбираете те минусы которые для вас менее важны.

                                                                                                А что за такой «правильный подход»? В реакт? Не думаю. Пока не вижу чем я жертвую, когда пишу $: — очень удобно и декларативно.
                                                                            +1
                                                                            Поздравляю всех причастных!
                                                                            С некоторого времени с интересом наблюдаю.
                                                                              0
                                                                              Спасибо! :)
                                                                              +1
                                                                              По описанию прям вкуснятина. Обязательно попробую на днях. Скорее всего перепишу раздел настроек в своем расширении для браузера, а то с Vue есть варнинги в Firefox.
                                                                                0
                                                                                без лишних затрат и сложности использования прокси или аксессоров. Это просто переменная.
                                                                                Зато добавился закулисный вызов функции и компилятор. К инкременту. Если он внутри цикла, лишний код будет в каждой итерации.

                                                                                let name = 'test';
                                                                                <input type="text" bind:value={name}>

                                                                                Объявление переменной может отсутствовать или в нем может быть опечатка.
                                                                                Будет читаться из window.name со всеми вытекающими.

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

                                                                                Поскольку changed/$$.dirty в svelte инициализируется не с нулевым прототипом, такие проверки будут протекать, например, обновлять переменную constructor, когда не надо.

                                                                                Очень сырой фреймворк. Ради минималистичности можно было как раз оставить set() и сделать явный update(), выкинув все остальное, а не наоборот.
                                                                                  0
                                                                                  Зато добавился закулисный вызов функции и компилятор. К инкременту. Если он внутри цикла, лишний код будет в каждой итерации.

                                                                                  По моему опыту и судя по многочисленным тестам и сравнениям, бандлы на Svelte получаются в целом в 2-3 раза меньше, чем на фреймворках Большой Тройки. Мой собственный опыт можно описать еще проще — когда я заканчиваю писать проект на Svelte, размер итогового кода все еще меньше или сопоставим с размером только лишь фреймворка, типа Vue/React (про Angular вообще лучше промолчать).

                                                                                  Исходя из этого, не думаю что это проблема.

                                                                                  Объявление переменной может отсутствовать или в нем может быть опечатка.
                                                                                  Будет читаться из window.name со всеми вытекающими.

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

                                                                                  Поскольку changed/$$.dirty в svelte инициализируется не с нулевым прототипом, такие проверки будут протекать, например, обновлять переменную constructor, когда не надо.

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

                                                                                  Очень сырой фреймворк. Ради минималистичности можно было как раз оставить set() и сделать явный update(), выкинув все остальное, а не наоборот.

                                                                                  Тут я с вами совершенно не согласен, но с вашим мнением спорить не буду. Кстати, метод set таки остался (для любителей и внутренних нужд), только теперь он называется $set и использовать можно только снаружи.

                                                                                    0
                                                                                    Если он внутри цикла, лишний код будет в каждой итерации.
                                                                                    Исходя из этого, не думаю что это проблема.
                                                                                    ecmaeology имел ввиду скорость выполнения, например этот код:
                                                                                    for(let j=0;j<100;j++) i++;
                                                                                    превращается в
                                                                                    for(let j=0;j<100;j++) { i++; $$invalidate('i', i); }

                                                                                    что медленее в на порядок (порядки), но в данном случае это не существенно, вообще похоже нужно отделять переменные которые летят на view от внутренних переменных + computed тоже, нужно держать в голове какие переменные чем являются, ну или префиксы им делать.
                                                                                      0
                                                                                      что медленее в на порядок (порядки), но в данном случае это не существенно, вообще похоже нужно отделять переменные которые летят на view от внутренних переменных + computed тоже, нужно держать в голове какие переменные чем являются, ну или префиксы им делать.

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

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

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

                                                                                      В реактивном фреймворке реактивность написана невнимательно или некомпетентно.
                                                                                      Если хочется скорости и компактности, выкинуть и писать нормальный JS. Хочется фреймворк — react/vue/angular/другое. Но мнение, конечно, может быть любое.
                                                                                        0
                                                                                        Когда к простейшей операции, особенно в цикле, добавляется неявный вызов функции, речь идет не о размере файла.

                                                                                        По вашему засинкать стейт и DOM — это простейшая операция? Очень интересно, зачем тогда все эти VDOM? Давайте уж конкретнее тогда.

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


                                                                                        Нет, мой код вот:

                                                                                        <script>
                                                                                          let name = 'test';
                                                                                          $: double = name + name;
                                                                                        </script>
                                                                                        
                                                                                        <input type="text" bind:value={name}> {double}
                                                                                        

                                                                                        А это:
                                                                                        if (changed.name) {
                                                                                          set_data(t1, ctx.name);
                                                                                        }
                                                                                        

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

                                                                                        В реактивном фреймворке реактивность написана невнимательно или некомпетентно.
                                                                                        Если хочется скорости и компактности, выкинуть и писать нормальный JS. Хочется фреймворк — react/vue/angular/другое. Но мнение, конечно, может быть любое.

                                                                                        Уверен вы большой специалист по реактиности и написали кучу фреймворков. Куда уж всем нам до вас. Покажете свои решения?

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

                                                                                          –2
                                                                                          По вашему засинкать стейт и DOM — это простейшая операция
                                                                                          Простейшая операция — инкремент.

                                                                                          Не мой код
                                                                                          Думаю, всем окружающим очевидно, какой комментарий относится к какому куску кода. Не вижу смысла еще раз объяснять вам лично.

                                                                                          По поводу Svelte — работает прекрасно, баги бывают крайне редко. Говорить вы можете сколько хотите, но мы Svelte практикой проверяем и она говорит об обратном.
                                                                                          Сайт вашей конторы говорит, что там лапша из смеси голого JS и jQuery.
                                                                                            0
                                                                                            Простейшая операция — инкремент.

                                                                                            Если это изменение должно быть засинкано в DOM, то операция становится в разы сложнее, а если нет, то $$invalidate выстреливает вхолостую. Опять же тесты и практика не подтверждают ваши слова:



                                                                                            Думаю, всем окружающим очевидно, какой комментарий относится к какому куску кода. Не вижу смысла еще раз объяснять вам лично.

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

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

                                                                                            'name' is not defined (5:11)

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

                                                                                            Кроме того вот это ваше высказывание не совсем корректно:

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

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

                                                                                            Сайт вашей конторы говорит, что там лапша из смеси голого JS и jQuery.

                                                                                            Фу, как не красиво. Чтобы вы знали, этому сайту уже больше 5-ти лет и визуально он до сих пор довольно актуален. За это время он ни разу не менялся, потому что не было необходимости — заказов итак хватает. Однако как раз сейчас идет переезд на Svelte/Sapper и перевод на английский, ибо думаем активнее выходить зарубеж.

                                                                                            Ваших инновационных и «компетентных» проектов мы видимо не увидим тут.
                                                                                              –1
                                                                                              Если это изменение должно быть засинкано в DOM, то операция становится в разы сложнее
                                                                                              textNode.nodeValue = count
                                                                                              Невероятная сложность.

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

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

                                                                                              Svelte этого не делает, потому что это делает бандлер. Не уверен, что вообще существует кейс, когда код компонента будет просто выброшен в глобал
                                                                                              Баг совсем не в том. И слово бандлер не спасет. Вот такой «компонент» svelte:

                                                                                              <script>
                                                                                              let namе = 'test';
                                                                                              $: double = name + namе;
                                                                                              </script>
                                                                                              <h1>{name}</h1> {double}

                                                                                              Подключается так:

                                                                                              import App from './App.svelte';
                                                                                              export default new App({
                                                                                                target: document.body
                                                                                              });

                                                                                              Он скомпилируется и будет читать заголовок из window.name. Проброс через переменные верхнего уровня компонента — архитектурная ошибка того же начального уровня, что и остальные.

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

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

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

                                                                                                Для теста вполне сойдет, так же как и другие benchmark'и и сравнения, которые доступны в интернетах.

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

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

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

                                                                                                Баг совсем не в том. И слово бандлер не спасет. Вот такой «компонент» svelte:

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

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

                                                                                                Да, я вижу вы теотерик и практика для вас лишь миф.

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

                                                                                                Ошибки есть везде. 484 открытых issue в React, 192 в Vue и 2370 в Angular. И что это за показатель? Видите проблему — откройте issue, ее исправят, а вам скажут большое спасибо. Так работает open-source.
                                                                                                  0
                                                                                                  Внутри Svelte примерно это и делает
                                                                                                  Вместо одной проверки и присваивания он запускает сгенерированную портянку, которая линейно сканирует все отслеживаемые переменные и свойства на изменения. Если отойти от уровня примеров и завести в компоненте простенькие структуры, при изменении свойства объекта, «фреймворк» опять же целиком инвалидирует объект (похоже что и вызываемая при инвалидации функция сравнения некорректна, всегда возвращает true для объекта или функции) и тоже запускает портянку.

                                                                                                  Вставленная инвалидация:
                                                                                                  obj.prop = 'value'; $$invalidate('obj', obj);

                                                                                                  Функция сравнения:
                                                                                                  function safe_not_equal(a, b) {
                                                                                                    return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
                                                                                                  }

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

                                                                                                  вы теотерик и практика для вас лишь миф
                                                                                                  Раз уж продолжаете настаивать
                                                                                                  Мы используем
                                                                                                  На практике, пока не удавалось, хотя мы активно используем
                                                                                                  По моему опыту
                                                                                                  мы всегда внимательно относимся
                                                                                                  тесты и практика
                                                                                                  Практика — это непосредственно моя, моей компинии
                                                                                                  на практике таких багов не бывает
                                                                                                  вы теотерик и практика для вас лишь миф
                                                                                                  Ненормально частые упоминания «практики», не сопровождаемые конкретикой, вызывают подозрения, что у вас какие-то серьезные проблемы с практикой. И вот эти высокомерные указания комментаторам темы (volch/jsmitty/lega) то нажимать кнопочки, то смотреть материалы и преждевременные предположения, что именно они чего-то не поняли, с чем-то незнакомы или не разобрались.

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

                                                                                                  Точно хотите гнуть такую линию дальше?

                                                                                                  Видите проблему — откройте issue, ее исправят, а вам скажут большое спасибо. Так работает open-source.
                                                                                                  Если что-то является решетом, от архитектуры до реализации, зачем такое использовать.
                                                                                                    +1
                                                                                                    Вместо одной проверки и присваивания он запускает сгенерированную портянку, которая линейно сканирует все отслеживаемые переменные и свойства на изменения.

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

                                                                                                    Для примера, возьмем ваш пример из первого сообщения, но для наглядности добавил еще и вывод:

                                                                                                    <script>
                                                                                                      let name = 'test';
                                                                                                    </script>
                                                                                                    
                                                                                                    <input type="text" bind:value={name}>
                                                                                                    <h1>{name}</h1>
                                                                                                    


                                                                                                    Для вашего удобства даже завел REPL.

                                                                                                    Читаем код и отмечаем основные моменты:

                                                                                                    1. При создании компонента с помощью хелперов над DOM API создаются все нужные элементы и вешается обработчик события oninput на поле:

                                                                                                    input = element("input");
                                                                                                    t0 = space();
                                                                                                    h1 = element("h1");
                                                                                                    t1 = text(ctx.name);
                                                                                                    attr(input, "type", "text");
                                                                                                    dispose = listen(input, "input", ctx.input_input_handler);
                                                                                                    

                                                                                                    Все это дешево, максимально просто и эффективно.

                                                                                                    2. Весь скоуп компонента на самом деле выгдядит так:

                                                                                                    function instance($$self, $$props, $$invalidate) {
                                                                                                    	let name = 'test';
                                                                                                    
                                                                                                    	function input_input_handler() {
                                                                                                    		name = this.value;
                                                                                                    		$$invalidate('name', name);
                                                                                                    	}
                                                                                                    
                                                                                                    	return { name, input_input_handler };
                                                                                                    }
                                                                                                    


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

                                                                                                    3. Когда запускается микротаска, выполняется следующий код (внимание, это вся необходимая работа с DOM):

                                                                                                    if (changed.name && (input.value !== ctx.name)) input.value = ctx.name;
                                                                                                    if (changed.name) {
                                                                                                      set_data(t1, ctx.name);
                                                                                                    }
                                                                                                    


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

                                                                                                    set_data — это такое же DOM API хелпер:

                                                                                                    set_data(text, data) {
                                                                                                      data = '' + data;
                                                                                                      if (text.data !== data) text.data = data;
                                                                                                    }
                                                                                                    


                                                                                                    А теперь уж совсем для простоты, работает это так:

                                                                                                    1) Вводим значение в поле для ввода
                                                                                                    2) В конце тика последнее значение ввода пишется в data заранее сохраненного элемента.
                                                                                                    3) PROFIT

                                                                                                    Я не знаю что может быть проще и эффективнее. Тут даже querySelector не делается, не говоря уже о пересоздании всех структур в React и render/reconcile VDOM.

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

                                                                                                    Абсолютно нормальная проверка или вы предлагаете бегать вглубь объекта и проверять все его свойства? Если вы не в курсе в JS нет способа понять, что какое-то свойство внутри объекта, изменилось.

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

                                                                                                    Ой, да что вы говорите))) Тогда я вас добью окончательно. Если в том же REPL вы выставите опцию immutable: true (которую кстати мы всегда используем), то проверка станет еще проще:

                                                                                                    function not_equal(a, b) {
                                                                                                      return a != a ? b == b : a !== b;
                                                                                                    }
                                                                                                    

                                                                                                    Приколите, а мужики то не знали что так можно, да?

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

                                                                                                    Практика — это то чем я занимаюсь применительно к Svelte. Уверен, в данном треде, к сожалению, не многие могут говорить с точки зрения практики о сабже. Вы и многие другие, можете только теоретизировать и хаять со стороны, а я и моя команда пишем на Svelte уже почти 2 года реальные проекты, поэтому именно «практика» то, чем я могу поделиться, в отличии от вас. Вы в данном случае не более чем теоретик. Когда напишете хотя бы парочку проектов на Svelte, тогда и пишите разгромную статью как все плохо работает и какие есть проблемы. От тех, кто уже попробовал Svelte я лично пока жалоб не слышал.

                                                                                                    И вот эти высокомерные указания комментаторам темы (volch/jsmitty/lega) то нажимать кнопочки, то смотреть материалы и преждевременные предположения, что именно они чего-то не поняли, с чем-то незнакомы или не разобрались.

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

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

                                                                                                    Я вам выше писал, что кое-что из этого я не считаю проблемой, кое-что еще требует исследования и возможно issue. Но в целом, это не более чем ваши придирки. 2К issue в трекере Angular почему-то не делают его «сырым» по вашему мнению.

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

                                                                                                    Вы вырываете из контекста код и потом тычите им, как будто все видели то, что видели вы. Более того, со странными формулировками, типа «лишний код будет в каждой итерации» Что за лишний код? Почему он лишний? Я вот так и не нашел, где в каждой иттерации добавляется какой-то лишний код. Давайте уж тогда пример, а не просто бла-бла. Тогда и будет говорить предметно, а пока только «если бы да кабы».

                                                                                                    Что-то вы как раз не демонстрируете даже базовых практических знаний. Тогда становится понятно, зачем нужен генератор JS.

                                                                                                    А вы не демонстрируете даже базовых навыков адекватности. Кто вы, что вы из себя представляете, никто не знает. Про половину коллег из треда хоть что-то известно. Можно с ними соглашаться или нет, но каждый, кто высказывается тут конструктивно, имеет опыт, в том числе в open-source. А где ваши проекты? Нет, не видели. Зато слышали что все вокруг идиоты. Может быть, какие-то доклады/труды/статьи? 1 штука на Хабре и та «без комментариев». На Хабре с этого года, а где раньше были? Вы может школьник-троль какой-то? Тогда все в целом становится на свои места.

                                                                                                    Точно хотите гнуть такую линию дальше?

                                                                                                    О да, могу гнуть вас дни на пролет.

                                                                                                    Если что-то является решетом, от архитектуры до реализации, зачем такое использовать.

                                                                                                    Ну так, свою реализацию в студию. Ну или хотя бы что-то чужое, что вы считаете рабочим. Посмотрим, разберем по полочкам. К сожалению, но умничать со стороны всегда проще.
                                                                                                      0
                                                                                                      Если изменения происходят чаще 60 раз в секунду (а это многие мышиные события, например), то делать рендеринг на каждое событие — не эффективно. Обновление зависимых состояний (в том числе и рендеринг) нужно делать по requestAnimationFrame. Но текущая модель реактивности Svelte такое сделать не позволяет. Чтобы это стало возможным и не приводило приложение в неконсистентное состояние, кроме инвалидации при изменении, нужно добавить ещё и ревалидацию при чтении.
                                                                                                        0
                                                                                                        Удивительная штука, знаете. Казалось бы, логически вы правы, но ведь оно все работает.

                                                                                                        Тут ведь как получается, одни выдвигают гипотезы и пытаются стоить производительные решения на Virtual DOM, другие выдвигают другие гипотезы и делают штуки вроде Incremental DOM. В этом же время, у Svelte другая гипотеза, а что если просто убрать все лишние абстракции и тупо использовать DOM?

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

                                                                                                        Я это называю «augmented intelligence for web apps» — когда человек делает то, что у него хорошо получается на высоком уровне абстракции, а машина делает то, что хорошо получается у нее.

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

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

                                                                                                        Вот фигня какая.
                                                                                                          +1
                                                                                                          По поводу, requestAnimationFrame, так и есть. Микротаски конечно же запускаются асинхронно, а не сразу как произошли изменения в стейт.

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

                                                                                                            0
                                                                                                            Почему же? Асинхронные только изменения в DOM, а не стейт. Не уверен что в AngularJS были микротаски.
                                                                                                              0

                                                                                                              Ну а остальные вычисления (все эти "автораны" в ${}) получается будут зазря отрабатывать синхронно. Модель реактивности с "ячейками" позволяет откладывать вычисления на неопределённый срок, пока кому-то не потребуется результат.

                                                                                                                0
                                                                                                                Модель реактивности с «ячейками» позволяет откладывать вычисления на неопределённый срок, пока кому-то не потребуется результат.

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

                                                                                                                Не исключаю, что в $mol какие-то вещи внутри реализованы лучше чем в Svelte, хотя и концепт разный совсем. Лично для меня основная проблема $mol — это присловутый DX. В этом смысле Svelte для меня выглядит значительно проще и понятнее, но это, сами понимаете, на любителя.
                                                                                                              0
                                                                                                              Тут шоу куда веселее: стейт тоже обновляется асинхронно.

                                                                                                              svelte.dev/repl?version=3.1.0&gist=38667c3b7f224c1187e0dbb6238bee52

                                                                                                              PaulMaly почини мой gist, если я еще не понял как объяснить мысль svelte.
                                                                                                              Предположение было такое, что sheep всегда держит актуальное состояние i.
                                                                                                                0
                                                                                                                Поправил немного, для более корректной работы: https://svelte.dev/repl?version=3.1.0&gist=5eb0ed7cce0b4debbafca33921a9ab8a

                                                                                                                По-моему это поведение никак не связано со Svelte. В каждую итерацию setInterval кэшируется значение sheep. Во внешнем коде значение sheep изменилось, но внутри коллбека нет. Когда через секунду коллбек вызывается заново, туда просачивется новое значение sheep. За это время значение i внутри коллбека меняется 5 раз. Поэтому значение в консоле мы видим 5 значений i на одно значение sheep.

                                                                                                                Чтобы убедиться в этом, можем написать еще один лог:
                                                                                                                svelte.dev/repl?version=3.1.0&gist=4187edba9cbf8270c2d1919c7f453b22
                                                                                                                  0
                                                                                                                  Хмм, ну вот тут переосмысленная реактивность еще хитрее прошлых подходов.

                                                                                                                  В условном mobx \ vue не надо ждать requestAnimationFrame чтобы computed пересчитался
                                                                                                                  (понятно, что я могу вооружиться геттерФункцией + memoize one + ее вызовом в $: ($: чтобы не тащить логику в шаблон). И добиться такого же поведения в svelte, но это уже весьма неудобно.
                                                                                                                    0
                                                                                                                    В условном mobx \ vue не надо ждать requestAnimationFrame чтобы computed пересчитался

                                                                                                                    Вы что-то путаете по-моему. Асинхронные в Svelte только обновления DOM. Собственное точно также как и в Vue. Это сделано вот почему:

                                                                                                                    import App from './App.svelte';
                                                                                                                    const app = new App({ target });
                                                                                                                    
                                                                                                                    app.foo = 1; // мы не хотим чтобы DOM обновился сразу
                                                                                                                    app.bar = 2; // а потом еще раз
                                                                                                                    


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

                                                                                                                    app.set({ foo: 1, bar: 2 });
                                                                                                                    


                                                                                                                    То что вы описали с setInterval — это просто обычное поведение JS-а.
                                                                                                                      –1

                                                                                                                      Тут речь про такой кейс:


                                                                                                                      class Store {
                                                                                                                          @mem val = 1
                                                                                                                          @mem get qube() { return val ** 3 }
                                                                                                                      }
                                                                                                                      
                                                                                                                      const store  = new Store
                                                                                                                      console.log( store.qube ) // 1
                                                                                                                      store.val = 2
                                                                                                                      console.log( store.qube ) // 8
                                                                                                                        0
                                                                                                                        Но это можно сделать на js без всяких фреймворков.
                                                                                                                          0
                                                                                                                          Можно подумать фреймворки не на js пишутся.
                                                                                                          0
                                                                                                          Абсолютно нормальная проверка или вы предлагаете бегать вглубь объекта и проверять все его свойства? Если вы не в курсе в JS нет способа понять, что какое-то свойство внутри объекта, изменилось.

                                                                                                          А можете пояснить как cd для структур работает? Вот я передал объект в пропсы, объект поменялся, запустилась ваша invalidate, но ее же теперь надо запустить для всех полей во вложенных компонентах? Это как все осуществляется?

                                                                                                            +1

                                                                                                            Немного абстрактно напишу, как я себе это представляю, так как я предпочитаю под капот не лазить. Работает да и ладно… (С настоящей машиной также поступаю =))
                                                                                                            invalidate помечает, что изменился объект, не нужно метить все поля по отдельности.
                                                                                                            Например, при сборке компонента компилятор нашёл, что в разметке и в коде внутри <script> из всего объекта используется только поле obj.name. Так при инвалидации obj Svelte и проверяет только изменилось ли значение obj.name, весь объект целиком его не интересует.

                                                                                                              0

                                                                                                              Ну так, получается, если объект изменился, то тогда все дерево компонент, которое от него зависит будет проверяться обычным цд как в ангуляре?

                                                                                                                +2
                                                                                                                Не знаю как в ангуляре, но проблемы со своей колокольни не вижу. Проверка — это одна операция присваивания и одна операция строгого сравнения — суперсупердёшево. Если инвалидировать каждое свойство отдельно — то это уже половина этой работы будет выполнена.
                                                                                                                  –1

                                                                                                                  Ну это как-то в данном случае не особо согласуется с "точечными изменениями где надо" и все такое.

                                                                                                                    +1
                                                                                                                    Отнюдь, Svelte точно знает «где надо» — благодаря статическому анализу при компиляции, а всё что выше это не про «где», а про «когда».
                                                                                                                      –1
                                                                                                                      Отнюдь, Svelte точно знает «где надо»

                                                                                                                      Откуда? Вот я взял и написал obj1[field1] = obj2[field2] и потом использовал первое поле в шаблоне, никакого способа определить статически это не существует.

                                                                                                                        0

                                                                                                                        Почему? У вас первое поле в шаблоне(или присваивание ему в коде) — что тут сложного при компиляции найти эти моменты и вставить в бандл соответствующие проверку изменения obj.field1 и действие при инвалидации obj?


                                                                                                                        <script>
                                                                                                                            let obj = {
                                                                                                                                field1: "property #1",
                                                                                                                                field2: "property #2"
                                                                                                                            }
                                                                                                                        
                                                                                                                            setTimeout(()=>obj['field1']=obj['field2'],3000);
                                                                                                                        </script>
                                                                                                                        
                                                                                                                        {obj.field1}

                                                                                                                        REPL

                                                                                                                          –1
                                                                                                                          что тут сложного при компиляции найти эти моменты

                                                                                                                          При компиляции этих моментов еще нет. Искать просто нечего.


                                                                                                                          setTimeout(()=>obj['field1']=obj['field2'],3000);

                                                                                                                          Ну у вас литералы, а если так:


                                                                                                                          setTimeout(()=>obj[this.someButtonClicked ? 'field1' : 'field2']=obj[this.someButtonClicked ? 'field2' : 'field1'],3000);
                                                                                                                            +1

                                                                                                                            А что изменится то?


                                                                                                                            <script>
                                                                                                                                let obj = {
                                                                                                                                    field1: "property #1",
                                                                                                                                    field2: "property #2"
                                                                                                                                }
                                                                                                                            
                                                                                                                                let someButtonClicked = true;
                                                                                                                            
                                                                                                                                setTimeout(()=>obj[someButtonClicked ? 'field1' : 'field2']=obj[someButtonClicked ? 'field2' : 'field1'],3000);
                                                                                                                            </script>
                                                                                                                            
                                                                                                                            {obj.field1}

                                                                                                                            REPL


                                                                                                                            Компилятор знает, что obj -это часть стейта, поэтому он ищет в коде и в разметке все места где грубо говоря объекту или его свойству что-то присваивают и в бандле добавляет после присваивания сначала ; — а потом $$invalidate('obj', obj);. Посмотрите вкладку JS Output в REPL.

                                                                                                                              –1
                                                                                                                              А что изменится то?

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


                                                                                                                              Компилятор знает, что obj -это часть стейта, поэтому он ищет в коде и в разметке все места где грубо говоря объекту или его свойству

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

                                                                                                                                +1
                                                                                                                                По всем ходить не надо, а только по тем кто был инвалидирован. Места, где объект инвалидируется вычисляются при компиляции.

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

                                                                                                                                Вы код же видели? Он же работает. Компилятору не надо знать, какое поле меняется, ему надо знать, что объект меняется.
                                                                                                                                  –1
                                                                                                                                  По всем ходить не надо, а только по тем кто был инвалидирован.

                                                                                                                                  Так вы не знаете, кто был инвалидирован. Поменяли какое-то поле obj — с-но, абсолютно любая переменная в темплейте из поддерева могла измениться, нет никакого способа узнать, какая именно.
                                                                                                                                  Значит, вам надо перебирать все эти переменные и проверять, изменились они или нет. Другие варианты отсутствуют.


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

                                                                                                                                  Толку от этого знания? Обновлять-то ноду, которая биндится на поле, а не на объект.
                                                                                                                                  Ну либо перерисовывать все поддерево на каждый чих (именно ради того, чтобы этого не делать, в реакте и вкостылили вдом).

                                                                                                                                    +1
                                                                                                                                    Так вы не знаете, кто был инвалидирован.

                                                                                                                                    Инвалидирован был объект. При проверке отсекаются другие объекты стейта, которые не были инвалидированы.


                                                                                                                                    Значит, вам надо перебирать все эти переменные и проверять, изменились они или нет.

                                                                                                                                    Так мы же, вроде, уже это обсудили сильно выше. Да все поля объекта, встречающиеся в данном контексте переберем.


                                                                                                                                    Помните я писал про "суперпупердешёвые" операции:


                                                                                                                                    if (changed.obj) && t2_value !== (t2_value = ctx.obj.field1) set_data(...);

                                                                                                                                    При этом проверка свойства объекта по ресурсоёмкости ровно такая же ничтожная, как и проверка обычной переменной в стейте. Гораздо более ресурсоемкий рендер точечно произойдет по команде set_data() при истинности вышеуказанного выражения.

                                                                                                                                      –1
                                                                                                                                      Так мы же, вроде, уже это обсудили сильно выше. Да все поля объекта, встречающиеся в данном контексте переберем.

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


                                                                                                                                      Или все же под "контекстом" подразумевается именно только текущий шаблон, и тогда в описанном вами условии заведомо true и с-но постоянно происходит перерендер всей страницы? Какой из этих двух вариантов?

                                                                                                                                        +1
                                                                                                                                        и тогда в описанном вами условии заведомо true

                                                                                                                                        не понял, почему true?


                                                                                                                                        • changed.obj — смотрим менялся ли объект — либо true либо false
                                                                                                                                        • t2_value !== ctx.obj.field1 — смотрим не равно ли прошлое значение текущему значению поля объекта — либо true либо false

                                                                                                                                        то есть надо будет гонять цд по факту по всему дому, по всем стопицотыщам нод

                                                                                                                                        Извините, я не знаю что такое "цд". Но нигде гонять мы не будем ни в DOM, ни по нодам, ни даже по объекту changed. Итерирование вообще сильно дороже выходит, чем аналогичное количество булевых if-ов.


                                                                                                                                        При каждом тике просто запускается проверка всех "суперпупердешёвых" условий, подавляющее большинство из которых отваливается ещё на его части (changed.obj) — оно не просто так в скобочках.


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

                                                                                                                                          –1
                                                                                                                                          Итерирование вообще сильно дороже выходит, чем аналогичное количество булевых if-ов.
                                                                                                                                          Но ведь количество булевых if-ов не аналогичное, не так ли?
                                                                                                                                            +1

                                                                                                                                            А вот я не готов реально сравнивать одну итерацию по объекту с одним булевым сравнением. Как я выше написал, я под капот лазить боюсь, знаний хватает только на уровень абстракции фреймворков. Но логика подсказывает, что одна итерация это минимум операция сравнения и операция присваивания(не считая действий внутри цикла). Вроде бы то же самое, что делает Svelte в if-ах.
                                                                                                                                            Но я думаю, есть причина почему создатели Svelte не итерируются по changed, а используют if-ы. Может быть итерации даже более дорогостоящие, чем я себе представляю. Мне на самом деле было бы интересно в этом разобраться, надеюсь, как и вам.

                                                                                                                                              –1
                                                                                                                                              А вот я не готов реально сравнивать одну итерацию по объекту с одним булевым сравнением
                                                                                                                                              Ок, ну и не будем. Вообще такие вещи можно делать через массив, в который добавляются изменения, цикл по массиву недорогой.
                                                                                                                                              Против if-ов будет играть как минимум их количество и то, что они будут часто промахиваться мимо кэша и дергать два прототипа.
                                                                                                                                                +1
                                                                                                                                                Вообще такие вещи можно делать через массив, в который добавляются изменения

                                                                                                                                                Мне вот тоже кажется, что логичнее делать перебор по changed (тем более если бы это был массив, а не объект). Он бы большую часть времени пустой был, если на сайте нет чего-то постоянно меняющегося. Но у контрибьютеров Svelte свое видение. И не дураки, чай. Стало бы понятнее, наверное, если расковырять как Svelte работает. Или хотя бы спросить их на эту тему. Я уверен у них есть железные аргументы.

                                                                                                                                                0
                                                                                                                                                И как мне кажется причина эта очень простая — кроме проверки самого changed, у нас могут быть еще дополнительные проверки для того, чтобы «решить» что DOM манипуляция действительно нужна. Поэтому общий обход по объекту changed не исключит необходимости иметь if/switch внутри этого обхода, но при этом в итоге будет не только дороже, но и визуально хаотичнее.
                                                                                                                                              0
                                                                                                                                              не понял, почему true?

                                                                                                                                              Ну объект поменялся.


                                                                                                                                              При каждом тике просто запускается проверка всех "суперпупердешёвых" условий

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


                                                                                                                                              Вы видимо не понимаете о чем речь. Вот есть у вас компонент foo в котором есть объект obj который прокидывается пропсом в темплейте:


                                                                                                                                              <bar yoba={obj}></bar>

                                                                                                                                              и вы меняете поле в этом obj: obj.field1 = 'yoba'.
                                                                                                                                              У компонента bar тоже есть темплейт и там что-то биндится. В этм теплейте — тоже вызываются какие-то компонеты (в них другие и т.д.) и в них тоже что-то биндится.
                                                                                                                                              Так вот — как только вы изменили поле внутри obj (или сам obj), то любая забинженная внутри темплейта bar или внутри какого-либо другого темплейта (рекурсивно и до самого конца) переменная могла измениться. Вы никак не можете заранее скзаать какая — могла любая.
                                                                                                                                              И у вас два варианта:


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

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


                                                                                                                                              так какой из этих вариантов в svelte реализован?

                                                                                                                                                +1

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


                                                                                                                                                1. Вариант точно нет, Svelte не бегает по DOM в рантайме.
                                                                                                                                                2. Похоже на него, за исключением того что именно портяга if-ов и сгенерирована. Я всё еще не могу понять, почему нельзя их написать при компиляции. Тут очень просто же всё — если переменная в стейте (let name; или let obj;) и если она где-то есть в разметеке ({name} или {obj.foo}) — добавляем if. Это не при запуске скрипта делается, это делается компилятором при анализе текста файла компонента.Таким образом получается набор if-ов для каждого отдельного компонента. Знать где и сколько будет или не будет нод в рантайме вообще не важно — подход Svelte.

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

                                                                                                                                                  0
                                                                                                                                                  Я всё еще не могу понять, почему нельзя их написать при компиляции.

                                                                                                                                                  Потому что они неизвестны при компиляции.


                                                                                                                                                  Тут очень просто же всё — если переменная в стейте

                                                                                                                                                  Если у нас целый объект, то мы не знаем, какие его поля в стейте — а какие нет. Кроме того — мы не знаем, на какие ноды биндятся эти поля, так что даже если бы мы знали, например, что изменилось поле Х — то этого не достаточно для апдейта dom. Надо еще знать, в какую ноду этот Х данные сует (и таких может быть не одна).


                                                                                                                                                  если компонент не рендерится в текущем тике, то набор его if-ов, соответственно, не пробегается

                                                                                                                                                  Так чтобы узнать рендерится он или нет в текущем тике, надо узнать, изменились или нет биндинги :)

                                                                                                                                                    +1

                                                                                                                                                    Объясните же мне наконец, зачем нам нужно знать структуру объекта. Я вас уже просил — откройте REPL из моих примеров и посмотрите JS Output. Ну и вот я еще один пример набросал — тут ну вообще во время компиляции про структуру объекта ничего не известно, неправда ли?


                                                                                                                                                    <script>
                                                                                                                                                        let obj = {};
                                                                                                                                                        let n = 5;
                                                                                                                                                        for(let i=0; i<10; i++){
                                                                                                                                                            obj['field'+i] = 'test'+i
                                                                                                                                                        }
                                                                                                                                                    </script>
                                                                                                                                                    
                                                                                                                                                    {obj['field'+n]}

                                                                                                                                                    REPL


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

                                                                                                                                                      0
                                                                                                                                                      Ну и вот я еще один пример набросал — тут ну вообще во время компиляции про структуру объекта ничего не известно, неправда ли?
                                                                                                                                                      Тут весь «obj» будет инвалидирован, не важно что вы там поменяли.
                                                                                                                                                      Т.е. берется корневое имя переменной, например если вы меняете только «obj.user.status.name», то инвалидируется весь «obj», поэтому ваш пример будет нормально работать.
                                                                                                                                                        0
                                                                                                                                                        А он всегда корневой будет инвалидирован, да. Но инвалидирован в случае Svelte не означает поиск измененных полей в объекте или же беганье по DOM/VDOM. Он вообще практически ничего не делает, просто говорит «хей, похоже эта часть стейта как-то изменилась. может надо обновить DOM?»

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

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

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

                                                                                                                                                      Разве шаблон нам не говорит об этом?

                                                                                                                                                      Так чтобы узнать рендерится он или нет в текущем тике, надо узнать, изменились или нет биндинги :)

                                                                                                                                                      Именно это делает $$invalidate, говорит рантайму «хей, похоже эта часть стейта как-то изменилась. может надо обновить DOM?»

                                                                                                                                                        –1
                                                                                                                                                        А нам нужно знать структуру объекта до компиляции, чтобы обновить DOM?

                                                                                                                                                        Не нужно, если вы делаете cd, перерендериваете все поддерево или просто игнорируете это изменение. В противном случае — нужно.


                                                                                                                                                        Именно это делает $$invalidate, говорит рантайму «хей, похоже эта часть стейта как-то изменилась. может надо обновить DOM?»

                                                                                                                                                        Но у вас инвалидируется весь объект. То есть invalidate говорит рантайму: "хей, где-то на вашем сайте что-то поменялось!"
                                                                                                                                                        Чтобы это что-то поменять, вам надо либо найти точку изменения теперь (и для этого надо перебрать все биндинги, т.к. измениться мог любой), либо перерендерить весь сайт, либо ничего не делать. Какой из вариантов — вариант svelte?

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

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

                                                                                                                                                          Теперь по-существу.

                                                                                                                                                          1) Нужно ли знать структуру объекта до компиляции, чтобы обновить DOM? Рассмотрим пример:

                                                                                                                                                          // Компонент
                                                                                                                                                          
                                                                                                                                                          <h1>{obj.foo}</h1>
                                                                                                                                                          <h2>{obj.baz.baz2}</h2>
                                                                                                                                                          
                                                                                                                                                          <script>
                                                                                                                                                              export let obj = {};
                                                                                                                                                          </script>
                                                                                                                                                          
                                                                                                                                                          // Использование
                                                                                                                                                          
                                                                                                                                                          <Component {obj} />
                                                                                                                                                          
                                                                                                                                                          <script>
                                                                                                                                                            import Component from './Component.svelte';
                                                                                                                                                            let obj = {
                                                                                                                                                              foo: 1,
                                                                                                                                                              bar: 2,
                                                                                                                                                              baz: {
                                                                                                                                                                 baz1: 3,
                                                                                                                                                                 baz2: 4
                                                                                                                                                              },
                                                                                                                                                              qux: 5,
                                                                                                                                                              // сколько угодно еще полей
                                                                                                                                                            };
                                                                                                                                                          </script>
                                                                                                                                                          

                                                                                                                                                          Вопрос: нужно ли нам знать о всех +100500 полях объекта, чтобы обновить DOM компонента? Ответ: не нужно.

                                                                                                                                                          Теперь про это:

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

                                                                                                                                                          2) Как собственно обновить DOM точечно, не чекая всего и вся? Давайте попробуем представить, что мы просто пишем код примера выше:

                                                                                                                                                          const target = document.body;
                                                                                                                                                          const obj = { ... };
                                                                                                                                                          
                                                                                                                                                          let t1_value = obj.foo, 
                                                                                                                                                            t2_value = obj.baz.baz2;
                                                                                                                                                          
                                                                                                                                                          const h1 = document.createElement('h1'),
                                                                                                                                                            t1 = document.createTextNode(t1_value),
                                                                                                                                                            h2 = document.createElement('h2'),
                                                                                                                                                            t2 = document.createTextNode(t2_value);
                                                                                                                                                          
                                                                                                                                                          target.appendChild(h1);
                                                                                                                                                          h1.appendChild(t1);
                                                                                                                                                          target.appendChild(h2);
                                                                                                                                                          h2.appendChild(t2);
                                                                                                                                                          

                                                                                                                                                          Грубо, но как-то так в целом. Теперь, в каком-то момент мы понимаем что объект изменился (присловутый $$invalidate), а точнее изменились какие-то его поля. Точно знать какие именно поля изменились нам не нужно, так же как чекать все эти поля.

                                                                                                                                                          Как бы мы написали обновление DOM, если бы писали не рантайм абстракцию на все случаи жизни, а делали все по месту, точно в зависимости от текущего кода (внимание $$invalidate в Svelte лишь отмечает какой кусок стейта изменился, пример ниже утрирован для простоты)?

                                                                                                                                                          function invalidate(changed) {
                                                                                                                                                            if (changed.obj && t1_value !== (t1_value = obj.foo)) {
                                                                                                                                                               t1.data = t1_value;
                                                                                                                                                            }
                                                                                                                                                            if (changed.obj && t2_value !== (t2_value = obj.baz.baz2)) {
                                                                                                                                                               t2.data = t2_value;
                                                                                                                                                            }
                                                                                                                                                          }
                                                                                                                                                          ...
                                                                                                                                                          obj.baz.baz2 = 10;
                                                                                                                                                          obj.qux = 11;
                                                                                                                                                          invalidate({ obj: true });
                                                                                                                                                          

                                                                                                                                                          Итак, в итоге мы сделали изменение вложенного поля объекта, который присутствует в DOM и еще одного, который там не используется. Получили точечное изменение DOM только для соответствующего элемента. Так как значение obj.foo не поменялось, эта часть DOM осталась без изменений. Несмотря на то, что поменялся obj.qux, никаких dirty checking или reconcile на это изменение не происходит.

                                                                                                                                                          Теперь расмотрим кейс, когда этот же объект прокидывается дальше, в следующий компонент. Собственно тут даже рассматривать нечего. Все будет тоже самое, только условная функция invalidate для вложенного компонента будет другая. Но принцип работы будет тот же — компонент получает «сигнал», что объект как-то изменился и проверяет изменились ли значения ТОЛЬКО тех полей, которые используются в той части DOM, за которую он отвечает. Если значения не поменялись, тогда ничего не происходит.

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

                                                                                                                                                          Мы компилятор, мы не обязаны играть по общим правилам.

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

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

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


                                                                                                                                                            Нужно ли знать структуру объекта до компиляции, чтобы обновить DOM?

                                                                                                                                                            Некорректный вопрос, т.к. мы не можем знать структуру объекта до компиляции. правильно спросить: "надо ли знать структуру объекта?". Для точечных изменений без cd — да, надо. Если вы не обновляете дом, или используете cd или рендерите все целиком — не надо.


                                                                                                                                                            Точно знать какие именно поля изменились нам не нужно, так же как чекать все эти поля.

                                                                                                                                                            Тогда откуда вы узнаете, какие ноды надо обновлять? Или вы просто обновляете все ноды? Или вы вообще ничего не обновляете?


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


                                                                                                                                                            Получили точечное изменение DOM только для соответствующего элемента.

                                                                                                                                                            Нет, не получили. Что если в вашем шаблоне obj.baz.baz2 не упоминалось а упоминалось во вложенном шаблоне? Тогда соответствующей проверки в $$invalidate не будет. Где она будет тогда?


                                                                                                                                                            Собственно тут даже рассматривать нечего. Все будет тоже самое, только условная функция invalidate для вложенного компонента будет другая. Но принцип работы будет тот же — компонент получает «сигнал», что объект как-то изменился

                                                                                                                                                            Ну вот вы прокинули obj.baz внутрь другого компонента, он не менялся, invalidate на нем нет, а obj.baz.baz2 — поменялся. Что дальше?

                                                                                                                                                              0
                                                                                                                                                              Это замечательно, но анализ шаблонов ноды не обновляет :)

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

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

                                                                                                                                                              В рантайме Svelte просто проверят заранее сгенерированные условия и выполняет заранее подготовленые DOM манипуляции. Собственно я вам совершенно конкретно написал что происходит и там нет никаких лишних вычислений.

                                                                                                                                                              Некорректный вопрос, т.к. мы не можем знать структуру объекта до компиляции. правильно спросить: «надо ли знать структуру объекта?». Для точечных изменений без cd — да, надо. Если вы не обновляете дом, или используете cd или рендерите все целиком — не надо.

                                                                                                                                                              Если под cd вы подразумеваете простую проверку типа:

                                                                                                                                                              if (changed.obj && t1_value !== (t1_value = obj.foo))
                                                                                                                                                              


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

                                                                                                                                                              Тогда откуда вы узнаете, какие ноды надо обновлять?

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

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

                                                                                                                                                              Или вы просто обновляете все ноды?

                                                                                                                                                              Нет, svelte не обновляте все ноды.

                                                                                                                                                              Или вы вообще ничего не обновляете?

                                                                                                                                                              Svelte обновляет только то, что нужно.

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

                                                                                                                                                              Я вам написал достаточно примеров, чтобы вы сами ответили на свой вопрос. Так какой из подходов использует Svelte по-вашему и почему вы так думаете?

                                                                                                                                                              Нет, не получили. Что если в вашем шаблоне obj.baz.baz2 не упоминалось а упоминалось во вложенном шаблоне? Тогда соответствующей проверки в $$invalidate не будет. Где она будет тогда?

                                                                                                                                                              В Svelte нет никаких вложенный шаблонов, только компоненты. Поэтому я вообще не понял о чем вы.

                                                                                                                                                              Ну вот вы прокинули obj.baz внутрь другого компонента, он не менялся, invalidate на нем нет, а obj.baz.baz2 — поменялся. Что дальше?

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

                                                                                                                                                              Еще раз, Svelte ни каким образом не интересуется общей структурой объекта и не отлавливает изменения в каждой его части.

                                                                                                                                                              Итак, попробую представить то, что вы написали в виде примера:

                                                                                                                                                              <Component baz={obj.baz} /> <!-- прокинули -->
                                                                                                                                                              
                                                                                                                                                              <script>
                                                                                                                                                                import Component from './Component.svelte';
                                                                                                                                                                
                                                                                                                                                                export let obj = {};
                                                                                                                                                                ...
                                                                                                                                                                obj.baz.baz2 = 10; // поменяли в какой-то момент
                                                                                                                                                                invalidate({ obj: true }); // инвалидируется всегда весь объект
                                                                                                                                                                ...
                                                                                                                                                              </script>
                                                                                                                                                              


                                                                                                                                                              Так как какую бы часть объекта мы не поменяли, инвалидируется весь объект. Ну и далее по ходу там примерно такой код (внимание песевдокод):

                                                                                                                                                              if (changed.obj) {
                                                                                                                                                                c1.$set({ baz: obj.baz }); // с1 - вложенный компонент
                                                                                                                                                              }
                                                                                                                                                              


                                                                                                                                                              Отмечу что это если иммутабильность не включена. Если включена (мы обычно ее включаем), то дальше код ясно дело не пойдет, пока не сменится ссылка на объект obj.baz.

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

                                                                                                                                                              Component.svelte

                                                                                                                                                              <p>{baz.baz1}</p>
                                                                                                                                                              
                                                                                                                                                              <script>
                                                                                                                                                                 export let baz = {};
                                                                                                                                                              </script>
                                                                                                                                                              


                                                                                                                                                              Отгадайте сколько манипуляций в DOM произойдет во вложенном компоненте, если в родительском компоненте поменялось свойство obj.baz.baz2? Правильный ответ — ноль. Сколько вычислений произойдет? Правильно — ноль.