Хайп по Svelte после недавнего релиза 3 версии фреймворка всё-таки имеет место быть, чему свидетельствуют сильно возросшее комьюнити и огромное количество вопросов как в официальном чате, так и в нашем рускоязычном telegram-канале. Всё больше разработчиков украдкой или всерьёз присматриваются к этой технологии и задумываются о её применении в своих новых проектах. Для этих разработчиков и всех прочих интересующихся темой максимально эффективного написания кода, Rich Harris, автор и идеолог фреймворка, опубликовал статью о том, как Svelte помогает разработчику минимизировать усилия при создании современных реактивных web-приложений, перевод которой я и предлагаю ниже.


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


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


На самом деле, широко известно, что, с увеличением кодовой базы приложения, время разработки проекта и количество багов растут даже не с линейной, а с квадратичной зависимостью. Этим можно объяснить наше подсознательное поведение, когда пулл-реквесту на 10 строк мы с лёгкостью уделим такой уровень внимания, который редко достаётся коду размером более 100 строк. А как только код становится слишком длинным, и перестаёт помещаться на одном экране, когнитивные усилия, необходимые для его понимания, значительно возрастают. Мы пытаемся исправить ситуацию путём рефакторинга и добавлением комментариев — действия, которые почти наверняка приводят к ещё бо?льшему количеству кода. Это порочный круг.


Мы все немного одержимы, верно? Мы следим за производительностью приложения, размером бандла и всего прочего, что мы можем хоть как-то измерить, но мы редко обращаем внимание на объём кода, который пишем.


Читаемость кода — это важно


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


for (let i = 0; i <= 100; i += 1) {
    if (i % 2 === 0) {
        console.log(`${i} — чётное`);
    }
}

… во что-то неудобоваримое:


for (let i = 0; i <= 100; i += 1) if (i % 2 === 0) console.log(`${i} — чётное`);

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


Да, я говорю о Svelte


Сокращение объёма кода, который нужно писать, является очевидным преимуществом Svelte. Чтобы проиллюстрировать это, давайте посмотрим на очень простой компонент, реализованный на React, Vue и Svelte. Сначала версия Svelte:


<script>
    let a = 1;
    let b = 2;
</script>

<input type="number" bind:value={a}>
<input type="number" bind:value={b}>

<p>{a} + {b} = {a + b}</p>

Посмотреть в действии


Как мы сделаем то же самое в React? Скорее всего, это будет выглядеть примерно так:


import React, { useState } from 'react';

export default () => {
    const [a, setA] = useState(1);
    const [b, setB] = useState(2);

    function handleChangeA(event) {
        setA(+event.target.value);
    }

    function handleChangeB(event) {
        setB(+event.target.value);
    }

    return (
        <div>
            <input type="number" value={a} onChange={handleChangeA}/>
            <input type="number" value={b} onChange={handleChangeB}/>

            <p>{a} + {b} = {a + b}</p>
        </div>
    );
};

И, наконец, в Vue:


<template>
    <div>
        <input type="number" v-model.number="a">
        <input type="number" v-model.number="b">

        <p>{{a}} + {{b}} = {{a + b}}</p>
    </div>
</template>

<script>
    export default {
        data: function() {
            return {
                a: 1,
                b: 2
            };
        }
    };
</script>

Иначе говоря, требуется 442 символа в React и 263 символа в Vue, чтобы достичь чего-то, что в Svelte занимает 145 символов. Версия React буквально в три раза больше!


Подсчёт символов я выполнил путем копирования кода в буфер обмена и запуском команды pbpaste | wc -c в терминале


Такая сильная разница скорее исключение — из моего опыта, компонент React обычно примерно на 40% больше, чем его эквивалент на Svelte. Давайте теперь взглянем на особенности Svelte, которые позволяют компактнее излагать наши идеи.


Элементы верхнего уровня


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


В Vue разметка должна быть размещена внутри элемента <template>, который, на мой взгляд, тут лишний.


Привязки


В React мы должны самостоятельно обрабатывать события полей ввода вроде <input>:


function handleChangeA(event) {
    setA(+event.target.value);
}

Это не просто весьма скучная конструкция, занимающая место на экране, это ещё и дополнительная часть кода, где могут появиться ошибки. Концептуально, значение текстового поля привязано к значению a и наоборот, но это отношение не выражено чётко — вместо этого у нас есть два тесно связанных, но физически отдельных фрагмента кода (обработчик события и свойство value={a}). Кроме этого, мы должны помнить, что необходимо принудительно привести строковое значение в числовое с помощью оператора +, иначе 2 + 2 будет равно 22 вместо 4.


Как и в Svelte, у Vue есть свой способ выразить привязку — атрибут v-model, но и тут мы должны быть внимательны и использовать v-model.number, несмотря на то, что берём значение из <input type="number">.


Стейт


В Svelte обновление локального состояния компонента происходит с помощью простого оператора присваивания:


let count = 0;

function increment() {
    count += 1;
}

В React мы используем хук useState:


const [count, setCount] = useState(0);

function increment() {
    setCount(count + 1);
}

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


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


Забудем про шаблонный код


Это лишь малая часть возможностей Svelte, которые помогают с минимальными усилиями создавать UI приложения. Есть ещё много других — например, реактивные объявления, которые по своей сути выполняют работу функций useMemo,useCallback и useEffect из React без лишнего многословного шаблонного кода (который при этом сильно нагружает сборщик мусора созданием инлайновых функций и массивов при каждом изменении состояния приложения).


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


Полезные ссылки


Документация на русском по Svelte 3
Учебник на русском по Svelte 3
Примеры на русском по Svelte 3
Русскоязычный канал Telegram

Комментарии (254)


  1. storm_r1der
    12.05.2019 00:38
    +1

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


    1. nrgian
      12.05.2019 00:51
      +2

      Серьезно, тяжело разобрать свой код с хорошими комментариями?


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

      А вот если к этому проекту (или к этой части в большом проекте) ты возвращаешься спустя 4 месяца — то даже свой собственный код воспринимается так же тяжело как и чужой.


      1. storm_r1der
        12.05.2019 00:56
        -3

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


        1. Get-Web
          12.05.2019 14:43

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


        1. playermet
          12.05.2019 14:51

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


    1. tcapb1
      12.05.2019 04:39
      +2

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

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


      1. buriy
        13.05.2019 22:44

        В статье это очень плохо объяснено. Уж извините, но по мне, объяснение в духе «используйте Basic, а не Java, потому что „Hello world“ на Basic пишется в одну строчку, а в Java — в 10» отдаёт глупостью…
        А всё потому, что на языке программирования и фреймворке мы пишем не «Hello world»-ы, а многокомпонентные приложения из тысяч строк кода, и взаимодействие кода с браузером клиента, удобство описания и взаимодействия компонентов, упаковка кода для клиента, отладка (на девелоперской, серверной и клиентской стороне!)… все эти вещи очень сильно влияют на разработку. А здесь даже до уровня «как написать if» не добрались, что уж говорить даже про модульные компоненты. Дело не в компромиссах из реальной жизни… А лишь в компромисах между «hello world» и реальным кодом.
        Авторы, как вы собираетесь эти var a=… упаковывать и импортить вообще? Компоненты в React и Vue — именно этот вопрос решают. Их может быть несколько на один файл, им можно настроить области видимости. Первый попавшийся пример из интернета: github.com/HugoDF/vue-multiple-components-in-sfc/blob/master/02-global-component-string-template/src/App.vue, там объявлено два компонента: HelloWorld/'hello-world' и default/'app' (имя переменной компонента — по имени файла шаблона). Я в любой момент могу переименовать default в любое другое имя. У меня есть возможность инициализации этих переменных из различных источников и в разные моменты жизненного цикла компонента. А у вас псевдо-глобальные переменные почему-то этому решению соответствуют…


        1. AlexxNB Автор
          14.05.2019 08:42
          +2

          Дело в том, что Svelte — он не React и не Vue. Упаковывает и импортит компилятор. Вам об этом думать не надо. В этом и смысл — чтобы не писать кучу шаблонного кода(т.е. boilerplate), который обязательно должен быть в фреймворке с runtime. В учебнике чуть подробнее про импорты и вложенные компоненты(полистайте вперед немного, там последовательное объяснение и выполнение уроков)


          1. vintage
            14.05.2019 09:11
            -2

            кучу шаблонного кода(т.е. boilerplate), который обязательно должен быть в фреймворке с runtime

            С чего бы?


            1. nrgian
              14.05.2019 09:26

              С чего бы?

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


              1. AlexxNB Автор
                14.05.2019 09:40
                +2

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


                Я хотел сказать, что runtime предполагает обязательные ритуальные действия, например как у помянул Rich в этой статье для Vue:


                ...
                import Component from 'component';
                
                export default {
                  ...
                  components: {
                    Component
                  }
                ...
                }

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


                1. vintage
                  14.05.2019 17:13

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

                  Можно даже не импортировать, не устанавливать, а сразу использовать. Имея при этом рантайм. Пример я тут уже приводил.


                1. Druu
                  14.05.2019 18:17

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

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


              1. Druu
                14.05.2019 16:58

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

                А тришейкинг куда делся?


              1. vintage
                14.05.2019 17:10

                обязательно

                ...


                обычно

                Вы уж определитесь там.)


        1. PaulMaly
          14.05.2019 11:08
          +1

          А всё потому, что на языке программирования и фреймворке мы пишем не «Hello world»-ы, а многокомпонентные приложения из тысяч строк кода, и взаимодействие кода с браузером клиента, удобство описания и взаимодействия компонентов, упаковка кода для клиента, отладка (на девелоперской, серверной и клиентской стороне!)… все эти вещи очень сильно влияют на разработку. А здесь даже до уровня «как написать if» не добрались, что уж говорить даже про модульные компоненты. Дело не в компромиссах из реальной жизни… А лишь в компромисах между «hello world» и реальным кодом.

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

          Авторы, как вы собираетесь эти var a=… упаковывать и импортить вообще? Компоненты в React и Vue — именно этот вопрос решают.

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

          Пишем компонент:
          <script>
          let privateVar = 1, 
              publicProp = 2;
          
          function privateFunc() { ... }
          function publicMethod() { ... }
          
          export { // публичный интерфейс
            publicProp,
            publicMethod
          };
          </script>
          


          Используем через инстанс компонента или декларативно:

          <Nested bind:this={comp} publicProp={3} />
          
          <script>
            import Nested from './Nested.svelte';
          
            let comp; // или через инстанс
            ...
            comp.publicProp = 4;
            comp.publicMethod();
          </script>
          


          Их может быть несколько на один файл,

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

          // multipleComponents/index.js
          import HelloWorld from './HelloWorld.svelte';
          import Default from './Default.svelte';
          export default Default;
          export HelloWorld;
          


          Я в любой момент могу переименовать default в любое другое имя.

          Если вы про устаревший механизм «регистрации» компонентов, то например в реакт его никогда не было. Да и нативные импорты позволяют вам переименовывать компоненты и так:

          <Posts />
          <Message />
          
          <script>
            import Posts from './Listview.svelte';
            import { HelloWorld as Message } from './multipleComponents/';
          </script>
          


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

          В Svelte все тоже самое, только лаконичнее. Более того, синтаксис Svelte 2 был очень похож на Vue. Если уж быть совсем точным, потому что синтаксис Vue был изначально скопирован с Ractive, автором которого является автор Svelte. Так что можно сказать, тот синтаксис, который вы так полюбили, придумал автор статьи ;-)


          1. Druu
            14.05.2019 17:03

            Это скорее минус чем плюс и нужно бить по рукам. Один компонент — один файл.

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


            Если нужно, например, представить несколько логически связанных компонентов как единый «пакет», то проще и нагляднее сделать так:

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


            Кстати, а как в svelte с ленивой подгрузкой компонентов дела обстоят?


            1. PaulMaly
              15.05.2019 10:22

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

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

              А тут на лицо полезный бойлерплейт. Во-первых, он делает структуру приложения понятно и прозрачной. Во-вторых, «много-много мелких компонентов» это условное понятие, потому что пока компонент мелкий, а знавтра новая задача и он уже большой. Один разработчик привык искать его в файле с другим компонентов, а другой был вынужден вынести его в отдельный файл. В-третьих, сейчас в этом месте нужен один подкомпонент, а завтра надо свитчить между 5-ю, тоже в этот же файл засунем все? В-четвртых, сегодня этот компонент нужен в одном месте, а завтра в 2-х. Получается постоянный refactoring-driven-development даже там, где он не нужен изначально.

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

              /src/
                /components/
                  /Grid/
                    index.js
                    Grid.svelte
                    /components/
                      UserCard.svelte
                      ProductCard.svelte
              


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

              Это совершенно не обязательно. Просто иногда это удобнее. Например вы примере выже, /src/components/Grid/index.js просто точка для импорта компонента Grid.svelte, чтобы удобнее было импортировать:

              import Grid from '~/components/Grid/Grid.svelte';
              
              vs
              
              import Grid from '~/components/Grid/';
              


              Кстати, а как в svelte с ленивой подгрузкой компонентов дела обстоят?

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


              1. Druu
                15.05.2019 10:45

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

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


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

                Это каким образом структура приложения становится более понятной и прозрачной от того что вас лишили возможности структурировать код?


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

                Ну вот когда будет большой (90% — что никогда), тогда и вынесете в отдельный файл. YAGNI же.


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

                Шел 2019, казалось бы, а люди что-то там в файлах ищут.


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


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

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


                то этот вопрос имхо лучше решить на уровне файловой системы:

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


                А как это вообще относится к фреймворку?

                Ну напрямую. Способ ленивого использования компонент всегда прибит к фреймворку. Как в свелте это делается? А динамические компоненты как создаются? Сам компонент в свелте как сущность — это вообще что?


                1. PaulMaly
                  15.05.2019 11:29
                  +1

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

                  Вот лично я с 2013 года импортирую и регистрирую компоненты. Сперва в рамках Ractive, потому Vue, потом Svelte 1-2. Расскажите пожалуйста о преимуществах импорта + регистрации, перед просто импортом. Интересно.

                  Это каким образом структура приложения становится более понятной и прозрачной от того что вас лишили возможности структурировать код?

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

                  Ну вот когда будет большой (90% — что никогда), тогда и вынесете в отдельный файл. YAGNI же.

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

                  Шел 2019, казалось бы, а люди что-то там в файлах ищут.

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

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

                  Нормальные это какие? На том же Vue, с которого началось обсуждение, и на котором мы писали с момента появления 2-ки и до сих пор, никто тоже так не делает. Идеоматический способ использовать все те же SFC. То что реакт можно превратить в помойку большая часть разработчиков реакт, с которыми я знаком, считают пагубным делом и имеют проблемы с этим на своих проектах. Не нужно придумывать из мухи слона. Для мелкого проекта, засунуть в один файл еще куда ни шло, но когда проект хоть чуть крупнее или средний — это большая ошибка.

                  Какая разница вообще, в каком что файле? Обычно файлвоая структура разработчику неинтересна. Программист не работает с файлами, он работает с программными сущностями — модулями, классами, функциями.

                  А импортируете эти сущности вы не из файлов случаем?

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

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

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

                  Совершенно не согласен. Ваше право так думать, но такие штуки как Next/Nuxt/Sapper даже конвенции роутинга возложили на файловую систему. И многих людям, включая меня, очень нравится.

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

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

                  Как в свелте это делается? А динамические компоненты как создаются?

                  Легче легкого:

                  <button on:click={load}>Load component</button>
                  <svelte:component this={comp} />
                  
                  <script>
                    let comp = null;
                  
                    function load() {
                      import('./Component.svelte')
                        .then(({ default }) => {
                          comp = default;
                        });
                    }
                  </script>
                  


                  Или даже просто так при рендере парента и сразу со индикацией загрузки и выводом ошибок:

                  {#await import('./Component.svelte')}
                  <p>Loading...</p>
                  {:then comp}
                  <svelte:component this={comp.default} />
                  {:catch err}
                  <p>Component loading error: {err.message}</p>
                  {/await}
                  


                  Сам компонент в свелте как сущность — это вообще что?

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

                  import Cart from '~/compoenents/Cart.svelte';
                  
                  const cart = new Cart({
                    target: document.getElementById('cart'),
                    props: { ... }
                  });
                  
                  // total sum of products in cart (computed value)
                  console.log(cart.total);
                  
                  // <button id="addBtn" value="{productId}">Add to cart</button>
                  document.getElementById('addBtn').addEventListener(e => {
                    cart.add(+e.target.value);
                  }); 
                  
                  



                  1. mayorovp
                    15.05.2019 11:34

                    Уточнение: в реакте компонент точно так же можно создать из внешнего кода и дергать его методы, просто потребуется 1 вызов ReactDOM.render


                    1. PaulMaly
                      15.05.2019 12:55

                      А можно пример, чтобы быть точным? Просто я привык, что ReactDOM.render выгледит примерно так:

                      function Cart() {
                        ....
                      }
                      
                      ReactDOM.render(<Cart />, document.getElementById('cart');
                      

                      Только вот что делать, если файл внешнего кода не проходит через сборщик (транспиллер), например? Как зашипить компонент React в качестве подключаемого на страницу через script-тег класса?


                      1. mayorovp
                        15.05.2019 13:32

                        Вот так же:


                        var Cart = require('Cart'); // допустим, у нас requirejs
                        var cart = ReactDOM.render(React.createElement(Cart), document.getElementById('cart'));

                        Разумеется, сам компонент через транспилер придётся перегнать.


            1. mayorovp
              15.05.2019 10:39

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

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


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


    1. argamidon
      12.05.2019 08:23
      +3

      Я так и не узнал, зачем мне стоит писать меньше кода.

      Верно, ведь больше кода = больше бананов!!!


    1. worldmind
      12.05.2019 14:21

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


  1. alexesDev
    12.05.2019 00:42
    +1

    Пример с react средний, вынести NumberInput станет аккуратней, но это так, мелочи. React это про «learn once write anywhere» и это круто, больше ни у кого нет развитой ветки native. Как у Svelte дела?

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


    1. vpotseluyko
      12.05.2019 01:20
      +1

      Ну есть еще vue-native, flutter с dart..


    1. AlexxNB Автор
      12.05.2019 10:38

      Силами сообщества сейчас пилится Svelte-Native, но пока не для серьёзного применения.


  1. vpotseluyko
    12.05.2019 01:19

    Пример vue плохой- data может быть стрелочной функцией


  1. DarthVictor
    12.05.2019 03:09
    +5

        function handleChangeA(event) {
            setA(+event.target.value);
        }
    
        function handleChangeB(event) {
            setB(+event.target.value);
        }
    
        <input type="number" value={a} onChange={handleChangeA}/>
        <input type="number" value={b} onChange={handleChangeB}/>
    

    Не будет такого в реальном проекте.
    Будет
        import Input from '../common';
        ...
        <Input type="number" value={a} onChange={setA}/>
        <Input type="number" value={b} onChange={setB}/>
    



    1. justboris
      12.05.2019 11:15
      +1

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


      function useNumberValue(initialValue) {
        const [value, setValue] = useState(initialValue);
        return [value, event => setValue(+event.target.value)];
      }
      
      export default () => {
        const [a, handleChangeA] = useNumberValue(1);
        const [b, handleChangeB] = useNumberValue(2);
      
        return (
          <div>
            <input type="number" value={a} onChange={handleChangeA} />
            <input type="number" value={b} onChange={handleChangeB} />
            <p>
              {a} + {b} = {a + b}
            </p>
          </div>
        );
      };

      но это уже кому как удобнее


      1. mayorovp
        13.05.2019 11:03

        Ваш useNumberValue — это очень странный хук, поскольку использовать его можно только совместно с тэгом input.


        1. justboris
          13.05.2019 11:15

          а как было бы правильно?


          1. mayorovp
            13.05.2019 11:24

            Правильно было в том комментарии, на который вы отвечали.


      1. PaulMaly
        14.05.2019 11:19

        А мне вот кстати нравится. То что это хук для конкретного элемента (input) и даже типа (number) можно нивелировать его логичным расположением в папках проекта, например, сделать файл hooks/input.js для всех хуков связанных с инпутами.


        1. mayorovp
          14.05.2019 12:21
          -1

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


          1. justboris
            14.05.2019 12:59

            Скорее наоборот, можно будет переключаться между разными UI-библиотеками (Material, Bootstrap и т.д.) не трогая код внутри хука.


            1. mayorovp
              14.05.2019 13:17

              Это вообще как?


          1. PaulMaly
            14.05.2019 13:31
            +1

            Вы бы еще написали, что-то вроде: «А вот есть придется вообще приложение переписать, то...». Мне кажется ничего нет страшного в том, что вы написали. Очевидно, что переход с инпута на что-то еще — это серьезная мера.

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


    1. PaulMaly
      14.05.2019 11:17

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


      1. DarthVictor
        14.05.2019 12:10

        Насчет NumberInput я соглашусь, хотя это вопрос вкуса. А вот то что фреймворк сам делает преобразование типа – это очень х… во. Нельзя менять общепризнаное API. Либо давайте другое имя компоненту, и я могу кликнуть по его имени и перейти к реализации. Либо его поведение компонента совпадает с описанием WHATWG/W3C, да хотя бы MDN. Почему пользователи фреймворка должны учить кастомное поведение, если разработчики фреймоворка не удосужились выучить дефолтное?


        1. PaulMaly
          14.05.2019 13:51

          А вот то что фреймворк сам делает преобразование типа – это очень х… во. Нельзя менять общепризнаное API

          То есть вы знаете конкретный кейс, когда значение поля для ввода с type=number должно использоваться как строка? Хм… честно говоря я не знаю. В итоге получается, что вам приходится создавать целый компонент, чтобы просто исправить неочевидное поведение браузерной реализации импута, а зачем? Если уж не хотите пользоваться благами автоматизации и хочется писать все руками, то Svelte не запрещает вам использовать подход реакта:

          <input type="number" value={a} on:input={handleChangeA}>
          <input type="number" value={b} on:input={handleChangeB}>
          


          Пшык и проблемы нет? Был бы смысл в этом только…

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

          Потому что это удобно, это изначально ожидаемое поведение для type=number и это скорее бага в спецификации. Кроме того, использование 2way биндингов не только опциональное, но и отключаемое на уровне компилятора.

          Ну и как бы 2way биндинги не обязаны вообще следовать стандартам, потому что в стандартах их нет. Они нужны исключительно для удобства использования, а не просто для прокидывания значений как есть. Если вам нужно raw-значение, используйте ивенты как я описал выше и пишите собственное приведение типов для каждого места использования. Право ваше.


          1. Druu
            14.05.2019 17:08

            То есть вы знаете конкретный кейс, когда значение поля для ввода с type=number должно использоваться как строка?

            Когда оно не целое.


            1. PaulMaly
              14.05.2019 17:20

              А что сложение не целых чисел в JS делается с помощью строк? Не знал: svelte.dev/repl/bb67cff2eaf0486498bb1510bc7b5fa4?version=3.3.0


              1. Druu
                14.05.2019 17:54

                При чем тут сложение? Вы спрашивали конкретный кейс, я вам назвал конкретный кейс. Складывать ничего не надо.
                Попробуйте написать "0.5" в своем примере.
                Еще у вас пишутся нули слева и сбрасывается позиция при автоматическом удалении нулей с конца.
                Забаговано, короче, приемку ваш инпут не прошел.
                И проблема в том, что нормальный инпут из него даже не сделать, не меня логики, которая там в потрохах защита.
                Валидация с запятыми тоже, кстати, криво работает.


                1. PaulMaly
                  14.05.2019 18:05
                  -1

                  Попробуйте написать «0.5» в своем примере.

                  А вы попробуйте написать 0,5 то есть так как работает input type=number. Мне вот вообще само поле не дает написать точку. Все остальное работает как и предполагается: svelte.dev/repl/bb67cff2eaf0486498bb1510bc7b5fa4?version=3.3.0

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

                  Здрасти, мы с вами не пишем компонент input number для всех случаев жизни, а просто получаем значение из html input в виде числа для сложения. И я не знаю кейсов, когда число нам нужно ввиде строки.


                  1. Druu
                    14.05.2019 18:24
                    +2

                    А вы попробуйте написать 0,5

                    Мне не надо 0,5, мне надо 0.5, потому что так хочет пользователь. И выводит же 0.5 с точкой. А вводится с запятой? Это что за шизофрения с разным форматом ввода/вывода?


                    работает input type=number

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


                    Мне вот вообще само поле не дает написать точку.

                    Вот именно! А как сделать, чтобы давало?


                    Все остальное работает как и предполагается:

                    Нет, не работает. Стартовые нули должны удаляться (не удаляются) позиция курсора при удалении нулей на конце сбрасываться не должна (она сбрасывается), валидация запятой должна быть консистентна (она неконсистентна).


                    Здрасти, мы с вами не пишем компонент input number для всех случаев жизни, а просто получаем значение из html input в виде числа для сложения.

                    Я же вам сказал, в чем проблема. Проблема в том, что из вашего инпута нельзя сделать нормальный, человеческий инпут. Из инпута, который отдает строку — можно, а из вашего — нельзя. В этом и состоит кейс, когда "значение поля для ввода с type=number должно использоваться как строка".


                    1. PaulMaly
                      14.05.2019 18:42
                      -1



                      Мне не надо 0,5, мне надо 0.5, потому что так хочет пользователь. И выводит же 0.5 с точкой. А вводится с запятой? Это что за шизофрения с разным форматом ввода/вывода?

                      Это веб-стандарты, детка) HTML вводит 0,1, а js выводит 0.1 )))) Причем тут Svelte?

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

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

                      Вот именно! А как сделать, чтобы давало?

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

                      Нет, не работает. Стартовые нули должны удаляться (не удаляются) позиция курсора при удалении нулей на конце сбрасываться не должна (она сбрасывается), валидация запятой должна быть консистентна (она неконсистентна).

                      Типа, вы считаете правильным, что для input number можно написать число 007 и браузерный инпут спокойно примет это значение в качестве числа? Мне кажется это не нормально. Если считаете иначе, можете не юзать биндинги. Мое мнение тут не изменилось — биндинги чинят некоторые огрези реализации нативных контролов, чтобы разработчику было удобнее.

                      Я же вам сказал, в чем проблема. Проблема в том, что из вашего инпута нельзя сделать нормальный, человеческий инпут. Из инпута, который отдает строку — можно, а из вашего — нельзя. В этом и состоит кейс, когда «значение поля для ввода с type=number должно использоваться как строка».

                      У нас с вами видимо разные представления о правильном инпуте. Для меня числовой инпут дающий вводить не число — это не совсем правильный инпут))


                      1. Druu
                        14.05.2019 19:11

                        Причем тут Svelte?

                        Svelte при том, что этот инпут — не нативный, а обертка над ним. Он не ведет себя как нативный, он ведет себя так, как написали разработчики svelte.


                        Это веб-стандарты, детка)

                        Но вы же понимаете, что пользователю до фени веб-стандарты?


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


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


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

                        Оно на целое число меняется, там ни запятых, ни точек. И это не важно, поймите, как вам (или мне, или разработчику свелте) кажется лучше.


                        У нас с вами видимо разные представления о правильном инпуте.

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


                        1. PaulMaly
                          15.05.2019 13:07

                          Svelte при том, что этот инпут — не нативный, а обертка над ним. Он не ведет себя как нативный, он ведет себя так, как написали разработчики svelte.

                          Это реализация биндинга такая. Может она бажит, что не исключено. В любом случае, если что-то не устраивает в нем, всегда можно использовать `on:input`.

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

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

                          То есть ответ на ваш вопрос «зачем надо число возвращать в виде строки» — чтобы можно было свободно его обработать, как захочется.

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

                          <input type="number" value={a} on:input={e => a = +e.target.value}>
                          


                          Оно на целое число меняется, там ни запятых, ни точек. И это не важно, поймите, как вам (или мне, или разработчику свелте) кажется лучше.

                          А вы сами попробуйте:

                          <input type="number" step="0.1" bind:value={a}>
                          


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

                          А что пользователь хочет видеть решаете вы или кто?


          1. vintage
            14.05.2019 17:25

            вы знаете конкретный кейс, когда значение поля для ввода с type=number должно использоваться как строка?

            Чтобы написать "e" - не является валидным значением, а не "undefined" - не является валидным значением.


  1. vintage
    12.05.2019 06:44

    Сначала, версия Svelte:

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


    1. Надо управлять входными данными.
    2. Надо получать результаты.
    3. Надо стилизовать каждый дом-элемент.
    4. Надо иметь возможность кастомизировать стили.
    5. Надо прикручивать e2e тесты.
    6. Надо собирать аналитику по использованию.

    В результате код обрастает тем самым шумом, с которым боролись:


    <script>
    
      import Number from './Number.svelte';
    
      export let name = ''
      export let prefix = ''
      export let a = 1;
      export let b = 2;
      export let style;
    
      let id = prefix + '.' + name
    
      export let res;
      $: res = a + b;
    
    </script>
    
    <Number prefix={id} name="a" bind:value={a} style={style.a} />
    +
    <Number prefix={id} name="b" bind:value={b} style={style.b} />
    =
    <span id={ id + '.' + 'res' } class="res" style={style.res}>{res}</span>

    И это ещё без асинхронного вычисления значения и без обработки ошибок, без которого Svelte показывает просто белый экран.


    Ну и для сравнения, вот как выглядит почти полное отсутствие шума на самом деле:


    $my_form $mol_view
        sub /
            <= First $mol_number
                value?v <=> first?v 1
            \+
            <= Second $mol_number
                value?v <=> second?v 1
            \=
            <= Result $mol_view
                sub /
                    <= result \

    namespace $.$$ {
        export class $my_form extends $.$my_form {
    
            result() {
                return this.first() + this.second()
            }
    
        }
    }


    1. psFitz
      12.05.2019 09:39
      +2

      Тут на китайском? Я никогда не писал на svelte и reacrt, но их код я понял сразу, не говоря уже о vue. Но ваши примеры видел раз 10 на хабре, но так и не понял, что эта куча символов значит. \= и так далее


      1. vintage
        13.05.2019 01:26

        Возможно лаконичность синтаксиса замотивирует вас почитать документацию: https://github.com/eigenmethod/mol/tree/master/view#viewtree


        1. psFitz
          13.05.2019 09:53

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


          1. vintage
            13.05.2019 10:00
            -1

            Проще всего понять суть, сравнивая исходный и сгенерированный код в песочнице.


            1. psFitz
              13.05.2019 12:17

              если честно не сильно проще, я даже не понимаю что делает пример в песочнице и зачем он нужен


    1. justboris
      12.05.2019 12:27

      И куда подевались prefix, id и style, которые вы добавили в код на svelte, но их не видно в tree?


      Для полноты сравнения нужно было наверное показать еще имплементацию First, Second и Result.


      1. vintage
        13.05.2019 01:14

        но их не видно в tree?

        О том и речь, что во view.tree это всё не надо делать вручную. Автоматика-с.


        нужно было наверное показать еще имплементацию First, Second и Result.

        Вообще-то они показаны. Я привёл полностью работоспособный код компонента. Вы можете скопипастить его в my/form/form.view.tree и my/form/form.view.ts и далее использовать.


        1. justboris
          13.05.2019 01:26

          В конечном html у нас два тэга input для ввода и один span для вывода. В исходном коде они никак не фигурируют.


          Или хотите сказать, что "<=>" обозначает input, а "<=" – span?


          1. vintage
            13.05.2019 09:17

            В конечном html

            Конечный — всё-таки DOM. HTML — это просто один из способов его сериализации.


            Или хотите сказать, что "<=>" обозначает input, а "<=" – span?

            Нет, это двусторонний и односторонний биндинги свойств.


            <= First $mol_number
                        value?v <=> first?v 1

            Создать компонент $mol_number и назвать его First, привязать его значение value к нашему значению first, и вывести его.


            1. justboris
              13.05.2019 10:38

              Тогда для честного сравнения нужно учитывать еще и сериализатор.


              Для React я тоже могу написать написать свой рендерер на замену react-dom, на котором пример тоже получится в 3 строчки, но объективным сравнением это никак не будет.


              1. vintage
                13.05.2019 10:46

                Тогда для честного сравнения нужно учитывать еще и сериализатор.

                Он-то тут каким боком?


                я тоже могу написать

                Так напишите и будем сравнивать.


        1. arvitaly
          13.05.2019 05:44

          О том и речь, что во view.tree это всё не надо делать вручную. Автоматика-с.

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


    1. TheShock
      12.05.2019 16:45
      +3

      Ну и для сравнения, вот как выглядит почти полное отсутствие шума на самом деле:

      $my_form $mol_view
          sub /
              <= First $mol_number
                  value?v <=> first?v 1
              \+
              <= Second $mol_number
                  value?v <=> second?v 1
              \=
              <= Result $mol_view
                  sub /
                      <= result

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


    1. Cerberuser
      12.05.2019 20:23
      +4

      $my_form $mol_view
          sub /
              <= First $mol_number
                  value?v <=> first?v 1
              \+
              <= Second $mol_number
                  value?v <=> second?v 1
              \=
              <= Result $mol_view
                  sub /
                      <= result \

      Это что-то на Хаскелле?


      1. mayorovp
        13.05.2019 10:51
        +2

        Не обижайте Хаскель!


      1. 0xd34df00d
        14.05.2019 18:09

        Я почему-то подумал, что это гибрид хаскеля и постскрипта.


    1. babylon
      12.05.2019 21:12
      -1

      Дмитрий, на что вы ориентировались при разработке UI mol компонентов. Grid, flexbox...?


      1. vintage
        13.05.2019 09:10

        Там флексбоксы в основном используются.


    1. PaulMaly
      14.05.2019 11:33

      Понять бы еще зачем вы все это понаписали. Что такое prefix? Зачем он одинаковый для обоих инпутов? Пример на $mol вообще не содержит этих вещей. Возможно они сокрыты внутри реализации $mol_number, но тогда нужно показать и его реализацию, кроме того совершенно не видно использования. Вижу привязки, но не вижу кто генерирует префиксы и стили и как они попадают внутрь $mol_number. Если это делается как-то за ширмой и не явно, то это скорее минус. Неявно можно и в Svelte, только надо ли?

      Опять же, вы тут используете несколько готовых компонентов $mol ($my_form, $mol_view, $mol_number), не представляете детали их реализации, а потом говорите «смотрите!!! а на Svelte реализация этого с нуля будет уже не в 3 строчки, а в 10 строк». Хм, ну ладно. Не уверен, что это звучит очень круто и убедительно… Скорее уж наоборот)


      1. vintage
        14.05.2019 18:03

        Понять бы еще зачем вы все это понаписали.

        Я же написал 6 пунктов для которых всё это нужно.


        Что такое prefix? Зачем он одинаковый для обоих инпутов?

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


        Пример на $mol вообще не содержит этих вещей.

        Потому, что фреймворк делает это всё самостоятельно, а не требует писать бойлерплейт.


        Возможно они сокрыты внутри реализации $mol_number

        Они сокрыты в $mol_view, от которого наследуются вообще все компоненты. Это тот самый рантайм, с которым "борется" Svelte.


        Неявно можно и в Svelte

        Попробуйте реализовать.


        Опять же, вы тут используете несколько готовых компонентов $mol ($my_form, $mol_view, $mol_number), не представляете детали их реализации

        $my_form — компонент, который тут собственно и создаётся.
        $mol_number — стандартный компонент. Реализацию Number для Svelte я тоже не привёл, так что всё честно.
        $mol_view — тот самый рантайм, которого в Svelte нет, и который прячет от программиста львиную долю бойлерплейта.


  1. andreyiq
    12.05.2019 07:51
    +1

    Это все преимущества? Не увидел ни одной весомой причины, почему я должен с Vue перейти на это


    1. PaulMaly
      14.05.2019 11:38

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


  1. artemmalko
    12.05.2019 08:02
    +1

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

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

    Кажется, явное всегда лучше. Тот факт, что в Svelte есть неявное приведение string к number в случае input type number нужно держать в голове. То есть, разбирая код на Svelte нужно потратить гораздо больше усилий мозга, нежели чем в явных решениях других ребят, что вы привели в статье. Это я про фразу
    Поэтому, когда вы читаете такой код, вам придётся приложить гораздо больше усилий, чтобы понять замысел автора.


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


    1. extempl
      12.05.2019 08:19

      Тот факт, что в Svelte есть неявное приведение string к number в случае input type number нужно держать в голове. То есть, разбирая код на Svelte нужно потратить гораздо больше усилий мозга

      Справедливости ради, это то, что называется expected result, а значит, если все (или правильнее сказать, если движок JS в браузере) будут возвращать данные в том же типе, что и указан в инпуте — все быстро привыкнут к "правильному, ожидаемому" поведению и проблем не будет.


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


      1. artemmalko
        12.05.2019 14:42
        +1

        Немного про expected result: каков будет expected result для инуптов с type'ом tel или datetime. Для tel еще ладно, string даже норм. А вот для datetime можно и Date сделать, как expected result, дату же выбираем.

        И немного про сам Svelte, но это уже ответ не вам, а скорее к автору статьи
        Кстати, про input type=«number». Если запустить пример из статьи и стереть значение из input'а, мы получим замечательный результат: undefined + 2 = NaN.


        1. justboris
          12.05.2019 15:06

          Если запустить пример из статьи и стереть значение из input'а, мы получим замечательный результат: undefined + 2 = NaN.

          Вызываем в тред PaulMaly, он расскажет, как правильно.


          1. PaulMaly
            14.05.2019 12:14



            Короткий ответ — das ist javascript)))

            И все же интересно было бы узнать, какого поведения по-умолчанию вы ожидаете? приведение undefined к 0? Если такое и надо делать, то для какой-то конкретной задачи, то есть в userland, а не на уровне фреймворка:

            $: sum = (a || 0) + (b || 0);
            


            1. justboris
              14.05.2019 12:55

              Если такое и надо делать, то для какой-то конкретной задачи, то есть в userland, а не на уровне фреймворка

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


              1. PaulMaly
                14.05.2019 13:39

                Я бы с вами согласился, если бы был какой-то идеоматический способ конвертировать undefined в number. В реакт это работает как вам кажется логично, потому что +'' === 0, верное ли это приведение? Имхо нет. Вангую что при таком подходе где-нибудь в районе банковской сферы, можно нарваться на серьезные экономические последствия.

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

                export function toNumber(value) {
                  return value === '' ? undefined : +value;
                }
                

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

                import toNumber from 'lodash.tonumber';
                ...
                    function handleChangeA(event) {
                        setA(toNumber(event.target.value));
                    }
                
                    function handleChangeB(event) {
                        setB(toNumber(event.target.value));
                    }
                ...
                

                То есть писать еще больше кода, который Svelte пишет за нас. И кстати, почему-то lodash тоже undefined к нулю не приводит, с чего бы это?


                1. vintage
                  14.05.2019 18:14

                  если бы был какой-то идеоматический способ конвертировать undefined в number

                  Правильный вопрос: с какого фига там вообще взялся undefined?


                  1. PaulMaly
                    14.05.2019 18:44

                    То есть по-вашему лучше бы была пустая строка?)))


                    1. Druu
                      14.05.2019 19:52
                      +1

                      Лучше NaN. Либо число, либо не число. Ну или ошибка.


                      1. PaulMaly
                        15.05.2019 09:38

                        То есть вы считаете что в JS «отсутствует значение» — это NaN? А мне вот кажется, что это называется undefined. Но даже если уйти от религиозных споров, что правильнее и все такое, есть же чисто прикладной аспект — проверять на undefined значительно проще и удобнее, а значит:

                        <p>{a || 0}</p>
                        <p>{b || 0}</p>
                        
                        <script>
                          $: sum = (a || 0) + (b || 0);
                        </script>
                        

                        vs

                        <p>{isNaN(a) ? 0 : a}</p>
                        <p>{isNaN(b) ? 0 : b}</p>
                        
                        <script>
                          $: sum = (isNaN(a) ? 0 : a) + (isNaN(b) ? 0 : b);
                        </script>
                        

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


                        1. vintage
                          15.05.2019 09:47

                          Я вам по секрету скажу: NaN — тоже ложно значение в условиях.


                          1. PaulMaly
                            15.05.2019 10:04

                            Подловили, сплоховал с примером)) Но не во всех стравнениях кстати. В любом случае, моя позиция простая по этому поводу:

                            1) Если переменная не содержит значения, то это не NaN, а undefined
                            2) С NaN в любом случае больше проблем чем с undefined

                            В итоге, если выбирать между приведением пустой строки к NaN или 0, я бы лучше выбрал 0, то не NaN. Уверен undefined тоже неспроста используют в Svelte.


                        1. Druu
                          15.05.2019 10:20

                          То есть вы считаете что в JS «отсутствует значение» — это NaN?

                          NaN — это не отсутствие значения, NaN — это Not a Number. '' — определенно Not a Number.


                          А мне вот кажется, что это называется undefined.

                          Ну вы еще заставьте пользователя таблицу приведения типов из js выучить.


                          есть же чисто прикладной аспект — проверять на undefined значительно проще и удобнее

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


                          В итоге, если выбирать между приведением пустой строки к NaN или 0

                          Если ваша ф-я приводит строку к числу, то результат работы такой ф-и не может быть undefined. Это шизофрения. Пустая строка — это не 0 и не undefined, это определенно NaN. Так же как и строка вида 'gfgfdgdf'. Кейс со строкой '' ничем не отличается от кейса со строкой 'gdfgdfgdf'.


                          1. PaulMaly
                            15.05.2019 10:26

                            NaN — это не отсутствие значения, NaN — это Not a Number. '' — определенно Not a Number.

                            Но когда юзер полностью отчищает поле для ввода, это не Not a Number, это отсутствие значение.

                            Ну вы еще заставьте пользователя таблицу приведения типов из js выучить.

                            Причем тут юзер? Это задача разработчика запроцессить данный кейс и с undefined это будет сделать проще, чем с NaN.

                            Это программисту проще и удобнее. А что проще программисту — не важно, это никого не волнует. Пользователь явно не хочет разбираться, что такое undefined и чем оно отличается от null.

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


                            1. Druu
                              15.05.2019 10:54
                              +1

                              Но когда юзер полностью отчищает поле для ввода, это не Not a Number, это отсутствие значение.

                              Нет, значение не отсутствует. Это пустая строка.


                              Причем тут юзер? Это задача разработчика запроцессить данный кейс и с undefined это будет сделать проще, чем с NaN.

                              Чем проще? И выводите свой undefined вы именно юзеру. У вас там undefined + 5 = NaN.


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

                              Наоборот — крайних случаев меньше, либо у вас корректное число, либо NaN. Всего два случая. Вы же зачем-то при парсинге предлагаете добавить третий кейс — undefined. Какой в нем смысл, чем '' отличается в этом случае от 'gfdgfd' и зачем вообще нужны такие усложнения — не ясно.


                              1. PaulMaly
                                15.05.2019 11:43

                                Нет, значение не отсутствует. Это пустая строка.

                                Пустая строка для поля ввода числа?))) Нет уж, для меня, как для разработчика, понятнее undefined, чем пустая строка при вводе чила.

                                Чем проще? И выводите свой undefined вы именно юзеру. У вас там undefined + 5 = NaN.

                                Проще чем, что разоаботчику работать с undefined проще чем с NaN, а значит вероястность того, что вы вообще это увидите ниже. В случае с NaN ничем не лучше вообще, ибо NaN + 5 будет все тот же NaN. И в чем профит?

                                Наоборот — крайних случаев меньше, либо у вас корректное число, либо NaN. Всего два случая.

                                Да, у меня либо корректное число, либо нет значения, то есть undefined. NaN — это значение, но значение которое мне не нужно, то есть не валидное значение и с ним работать никак не могу. undefined — это отсутствие значения, такое бывает. В js мы всегда предполагаем, что переменная либо не имеет значения, то есть undefined, либо имеет валидное значение, в данном случае number. Вы же предлагаете добавить кейс с обработкой еще и невалидного значения.

                                Ок, рассмотрим пример, безотносительно Svelte:

                                let number; // undefined
                                
                                function setNumber(n) {
                                  number = n;
                                }
                                
                                setNumber(1); // 1 - valid
                                setNumber();  // undefined
                                setNumber(NaN);  // NaN - invalid
                                


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


                    1. vintage
                      15.05.2019 01:23
                      -1

                      Лучше бы было то, что ввёл пользователь, без потери информации.


        1. extempl
          12.05.2019 15:37

          Забавно, как у нас с вами разнятся ожидания. Хотя это вопрос стандартизации.
          Вот от date я бы на 97% ожидал именно тип даты. А вот с номером телефона и в каком формате если строка — тут вопрос. Скорее это таки long без форматирования, который можно представлять в любом формате в строке. Или массив цифр, чтоб ни у кого не было соблазна оперировать номером телефона как числом.


          1. justboris
            12.05.2019 15:56

            Вот от date я бы на 97% ожидал именно тип даты.

            Здесь возникает вопрос с часовыми поясами. new Date('2019-05-12') вернет вам полночь в вашей таймзоне, а в других поясах это будет другое число.


            1. extempl
              12.05.2019 15:59

              Хранить всегда в UTC? Или, по крайней мере, записывать. А при чтении из date вы сможете получить как локализованное значение, так и UTC, так и с любым другим сдвигом.


              1. justboris
                12.05.2019 16:26

                Получится какой-то такой код


                const value = '2019-05-12';
                // Date.UTC принимает только числа, поэтому парсим строку руками
                const [year, month, day] = date.split('-'); 
                const date = new Date(Date.UTC(Number(year), Number(month) - 1, Number(day)));
                console.log(date.getUTCDate()); // будет всегда 12 в любой таймзоне, как нам и хотелось

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


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


    1. PaulMaly
      14.05.2019 11:46

      Не до конца понял, что вы имеете ввиду под «рантайм» о котором надо помнить. В Svelte не нужно даже понимать как это работает, чтобы использовать. Наоборот компилятор пытается понимать что вы хотите написать, и дописывает за вас утилитарные вещи. Поэтому рантайма как раз тут нет о котором надо думать. Более того, в отличии от реакт, где огромные рантайм абстракции зашиты внутрь фреймворка, на Svelte вы можете за минуту прочитать весь код вашего компонента на любом этапе его написания и совершенно точно знать как он работает. Потому что это максимально прямолинейный, низкоуровневый, заточенный под задачу (текущий код компонента) императивный код. Попробуйте REPL, попишите код, загляните во вкладку JS Output. Если вы не сможете понять как это работает за 5 минут, я куплю вам пиво.

      И еще пример из реакт:

      this.setState({ foo: 1 }); // {foo} НЕ используется в шаблоне JSX
      


      Вам ведь надо «помнить» что вызов setState() вызовет rerender + reconcile даже если {foo} не используется в шаблоне вообще!!!??? В Svelte вы полностью избавлены от таких проблем)


      1. Druu
        14.05.2019 17:29

        В Svelte вы полностью избавлены от таких проблем)

        Наоборот же — в svelte надо помнить, что если foo в шаблоне нет, то рендер не будет вызван :)


        Логика реакта с безусловным рендером в этом плане явно проще.


        1. PaulMaly
          14.05.2019 17:39

          Наоборот же — в svelte надо помнить, что если foo в шаблоне нет, то рендер не будет вызван :)

          Извините, а зачем нам рендер, если foo нет связан с DOM? Или в этом просто какой-то сокральный смысл есть?

          Логика реакта с безусловным рендером в этом плане явно проще.

          Она не проще, а просто тупее. Нам же памяти не жалко, пусть гоняет туда-сюда vdom, даже если это не имеет смысла.


          1. Druu
            14.05.2019 18:01

            Извините, а зачем нам рендер, если foo нет связан с DOM?

            А откуда я знаю, что он не связан? О том же и речь — в svelte мне надо помнить, что с чем связано.


            Она не проще, а просто тупее.

            KISS :)


            Нам же памяти не жалко, пусть гоняет туда-сюда vdom, даже если это не имеет смысла.

            Ну вообще-то да.


            1. mayorovp
              14.05.2019 20:56

              А откуда я знаю, что он не связан? О том же и речь — в svelte мне надо помнить, что с чем связано.

              Простите, но у вас задача-то какая? Вызвать рендер или показать значение?


            1. PaulMaly
              15.05.2019 10:00

              А откуда я знаю, что он не связан? О том же и речь — в svelte мне надо помнить, что с чем связано.

              Вопрос же в том, зачем вам об этом вообще думаю? Лично мне достаточно знать 2 вещи:

              1) я хочу чтобы мой стейт всегда был синхронизирован в DOM
              2) я знаю что Svelte делает это максимально эффективно.

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

              KISS :)

              В данном случае это Keep It So Stupid

              Ну вообще-то да.

              Именно поэтому реакт не подходит для многих проектов, особено для low-power устройств. И речь даже не о экзотических штуках, типа POS терминалах, на которых Svelte показал себя прекрасно, но я просто на мобильных и ТВ. Мы его лично пробовали на ТВ, это марк же.


              1. Druu
                15.05.2019 10:28
                -2

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

                Так не факт, что они лишние.


                Именно поэтому реакт не подходит для многих проектов, особено для low-power устройств. И речь даже не о экзотических штуках, типа POS терминалах, на которых Svelte показал себя прекрасно, но я просто на мобильных и ТВ.

                Вопрос, зачем вообще использовать spa для low-power устройств, остается открытым.


                1. PaulMaly
                  15.05.2019 10:34
                  +1

                  Так не факт, что они лишние.

                  Если foo не связан в DOM, то rerender + reconcile при его изменении — это безусловно лишние операции.

                  Вопрос, зачем вообще использовать spa для low-power устройств, остается открытым.

                  А React подходит только для SPA? Еще говорят Svelte имеет какие-то ограничения по области использования ;-) К вашему сведению, все приложения для TV это как правило SPA, потому что далеко не все платформы поддерживают запуск приложения с удаленного сервера, обычно файлы крутятся на локальном или даже по протоколу file://.


                  1. Druu
                    15.05.2019 10:59

                    Если foo не связан в DOM, то rerender + reconcile при его изменении — это безусловно лишние операции.

                    А вдруг рендер где-то что-то поменяет и в итоге изменятся данные, которые выводятся?


                    А React подходит только для SPA? Еще говорят Svelte имеет какие-то ограничения по области использования ;-)

                    Что реакт, что свелте, что все остальное — это спа-фрейморвки. Если вам не нужно спа, то у них нет преимуществ никаких по сравнению с vanillajs.


                    обычно файлы крутятся на локальном

                    Ну так и крутите на локальном, spa зачем? Можно спокойно написать логику на беке. Да и вообще было бы интересно увидеть конкретный кейс, где реакт тормозил, а вот свелте решил проблему. Ну и еще желательно пример какого-нибудь приложения на свелте хотя бы среднего (100kloc+) размера приложения, чтобы понимать, как это скалируется все.


                    1. mayorovp
                      15.05.2019 11:05

                      А вдруг рендер где-то что-то поменяет и в итоге изменятся данные, которые выводятся?

                      Такого быть не должно.


                      Что реакт, что свелте, что все остальное — это спа-фрейморвки. Если вам не нужно спа, то у них нет преимуществ никаких по сравнению с vanillajs.

                      Обоснуйте. Не вижу никакой проблемы во вставке компонента реакт или свелте на любую страницу (кроме веса реакта).


                      1. Druu
                        15.05.2019 13:32

                        Такого быть не должно.

                        Не должно.


                        Не вижу никакой проблемы во вставке компонента реакт или свелте на любую страницу (кроме веса реакта).

                        Я тоже не вижу. Не вполне ясно, как это противоречит моим словам.


                    1. PaulMaly
                      15.05.2019 12:00

                      А вдруг рендер где-то что-то поменяет и в итоге изменятся данные, которые выводятся?

                      А вдруг, где-то, что-то, как-то))) Очень конструктивненько))) Я вам уже писал об этом, моя мысль не изменилась — реактголовногомозга. И я вас понимаю, потому что если долго работать с такой парадигмой, по-другому мыслить уже не получается.

                      Говорите рендер что-то где-то поменяет? Хм, попробую себе представить:

                      <p>{bar()}</p>
                      <input bind:value={foo} type="number">
                      
                      <script>
                        let foo = 0;
                      
                        function bar() {
                           return foo + 1;
                        }
                      </script>
                      

                      Так что ли? Только в Svelte такие вещи делаются не так))) Можно через чистую функцию (если нравятся функции), а можно через вычисляемое выражение:

                      <p>{bar(foo)}</p>
                      <p>{baz}</p>
                      <input bind:value={foo} type="number">
                      
                      <script>
                        let foo = 0;
                      
                        function bar(foo) {
                           return foo + 1;
                        }
                      
                        $: baz = foo + 1;
                      </script>
                      

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

                      Что реакт, что свелте, что все остальное — это спа-фрейморвки. Если вам не нужно спа, то у них нет преимуществ никаких по сравнению с vanillajs.

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

                      Ну так и крутите на локальном, spa зачем? Можно спокойно написать логику на беке.

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

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

                      В видео к предыдущей статье был кейс с POS терминалами. Реакт тоже тестировался.
                      Ну и еще желательно пример какого-нибудь приложения на свелте хотя бы среднего (100kloc+) размера приложения, чтобы понимать, как это скалируется все.

                      А есть такие приложения в open-source для реакта? Пришлите ссылку, гляну, может напишу аналог. Правда придется при этом по фунционалу раздуть процентов на 50%. Ну чтобы сравняться по кол-ву строк кода с приложение на реакт.

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


                      1. Druu
                        15.05.2019 13:38

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

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


                        Если серьезно, по всей ветке — в линтере есть правило, которое дает ворнинг по неиспользуемым в шаблонах переменные стейта :)


      1. vintage
        14.05.2019 18:28

        Вам ведь надо «помнить» что вызов setState() вызовет rerender + reconcile даже если {foo} не используется в шаблоне вообще!!!???

        А зачем нужно свойство, от которого не зависит визуализация?


        1. PaulMaly
          14.05.2019 18:45

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


          1. TheShock
            14.05.2019 22:12
            +1

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


  1. Imbecile
    12.05.2019 08:19
    +2

    Если следовать посылу заголовка, а именно, писать меньше кода, то надо ещё и Angular рассмотреть.

    Пример на Angular
    image


    1. psFitz
      12.05.2019 09:44

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


      1. Imbecile
        12.05.2019 09:48
        +1

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


        1. marshinov
          12.05.2019 11:46

          Для бекендщиков ровно наоборот


        1. MisterParser
          12.05.2019 11:55

          А мы тут с детьми программированием занимаемся что ли? Взял и изучил.


          1. etho0
            12.05.2019 13:41

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


            1. nrgian
              12.05.2019 14:31

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

              Какие?


              1. psFitz
                12.05.2019 19:23

                Тоже интересно узнать


              1. etho0
                13.05.2019 00:40
                +1

                react, vue, svelte?


                1. psFitz
                  13.05.2019 09:55

                  Не могу говорить за svelte, но в первых двух все не так, ничего они не дают, особенно реакт, особенно по скорости разработки


            1. Raspy
              12.05.2019 19:54
              +1

              Это пока занимаешься формошлёпством. Что-то более-менее крупное, с командой больше 3-4 человек и растянутое во времени на месяцы/года, и тут ангуляр с его кривой обучения, его фреймвёрком и его подходами не так уж плох.


          1. Druu
            13.05.2019 11:24

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


    1. DarthVictor
      13.05.2019 12:01

      Осталось сравнить количество кода для реализации v-model/ngModel/bind:value/value+onChange на кастомном поле ввода для каждого из фреймворков.


      1. PaulMaly
        14.05.2019 12:18

        Уточните пожалуйста что имеете ввиду?


        1. DarthVictor
          14.05.2019 19:10
          +1

          Имелся в виду кастомный компонент ввода. DateRange какой-нибудь. Или автокомплит с серверным поиском.


    1. PaulMaly
      14.05.2019 12:17

      Думаю что Angular не рассматривается прежде всего потому, что играет немного в другой лиге. Все же React/Vue/Svelte — это больше про UI фреймворки, а Angular — это уже application framework.

      Кроме того ваш довод про «остальное автоматически генерирует CLI» не очень состоятелен, так как его можно применить и к Vue, потому что там без сниппетов в IDE тоже мало кто пишет. Другое дело читать все эти лишние конструкции все равно придется потом вам или другим. И кода это в любом случае больше.


      1. Imbecile
        14.05.2019 12:33

        Всё-таки сниппеты IDE и команды CLI — немного две большие разницы.
        CLI есть всегда (ну почти) и в любой IDE (или без неё), а наличие сниппетов зависит от IDE.
        Де-факто, Angular CLI является частью фреймворка и потому

        ng g c sum
        (генерирует код с картинки) я считаю именно особенностью фреймворка.

        UI framework vs Application framework — это как?
        Я ещё понимаю, когда UI library vs App framework в контексте React vs Angular. А вот UI vs App — непонятно.


        1. PaulMaly
          14.05.2019 17:47

          Всё-таки сниппеты IDE и команды CLI — немного две большие разницы.

          Конечно, ведь сниппеты к IDE пишутся дома на коленке, а CLI — это сложная вещь. Кстати, у Vue тоже вполне себе не плохой CLI. Только CLI не поможет вам читать код, который оно нагенерит.

          UI framework vs Application framework — это как?
          Я ещё понимаю, когда UI library vs App framework в контексте React vs Angular. А вот UI vs App — непонятно.

          А мне кажется это более точные определения, потому что ну вот какая из Vue или React «библиотека»? У них нет никакой прикладной ценности.

          Lodash — это библиотека, а основная ценность Vue/React/Svelte — это структурирование кода в виде компонентов с изолированным стейтом, то есть это фреймворки, структуры. Далее, вопрос, а что мы можем структурировать с помощью React/Vue/Svelte? Полностью веб-приложение можем? Очевидно без роутинга, фетчинга и другие таких вещей нет, но можем построить UI.

          В этом смысле Vue/React/Svelte — это UI frameworks. Angular — application framework, потому что на его основе мы можем построить не только UI, но и все приложение.


          1. vintage
            14.05.2019 18:42

            Очевидно без роутинга, фетчинга и другие таких вещей нет

            Вот делаю я простую браузерную игрушку типа "Жизнь" — зачем мне там роутинги, фетчинги и тп?


            Angular — application framework, потому что на его основе мы можем построить не только UI, но и все приложение.

            Вот делаю я читалку PDF. Как это сделать без привлечения сторонних библиотек?


            1. PaulMaly
              14.05.2019 18:49

              Вот делаю я простую браузерную игрушку типа «Жизнь» — зачем мне там роутинги, фетчинги и тп?

              А это уже целое приложение? ))) Выглядит как демка просто.

              Вот делаю я читалку PDF. Как это сделать без привлечения сторонних библиотек?

              Ну так берите PDF фреймворк и вперед))


              1. vintage
                15.05.2019 01:43

                Да, это целое приложение, имеющее ненулевую ценность для целевой аудитории.


                pdfjs — это библиотека, а не фреймворк.


            1. mayorovp
              14.05.2019 20:58

              Вот делаю я читалку PDF. Как это сделать без привлечения сторонних библиотек?

              А откуда взялось уточнение "без привлечения сторонних библиотек"? От application framework не требуется заменять все возможные библиотеки.


              1. vintage
                15.05.2019 01:38

                А почему вы считаете, что роутинг и фетчинг в "application framework" должны быть, а рендерер PDF — нет?


                1. mayorovp
                  15.05.2019 06:49

                  Необходимыми для application framework они и правда не являются. Но и их наличие не мешает.


                  1. vintage
                    15.05.2019 09:14
                    -1

                    Ну, тогда нет никаких отличий App от UI.


      1. Druu
        14.05.2019 17:41

        У вас ведь тоже компилятор вызывается из консоли и генерит итоговый код :)
        Вообще, никто не мешает для ангуляра написать схему, которая будет подхватывать файлы, написанные по типу svelte и автоматом генерить по ним ангуляровские файлы из примера выше. И регистрировать их в ближайшем локальном модуле автоматом.


  1. qant
    12.05.2019 10:34

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


    1. PaulMaly
      14.05.2019 12:22

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


      1. Druu
        14.05.2019 17:47

        Но в плане реализации, совершенно другой подход.

        На самом деле, нет, ангуляр точно так же компилирует шаблоны. С ivy и тришейкинг хотят добавить, чтобы было "исчезающе" :)
        А в реакте компилировать ничего не надо вовсе, т.к. там шаблон по сути обычный js.


        1. PaulMaly
          14.05.2019 17:53

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

          На самом деле да. Потому что несмотря на AoT агнуляра делается оно только для шаблонов, а в Svelte не только для них. Примерно то, что сейча сделает ангуляр, предшественник Svelte, фреймворк Ractive делал уже в 2013 году.

          С ivy и тришейкинг хотят добавить, чтобы было «исчезающе» :)

          Когда добавят, тогда и посмотрим. Хотя в целом в верном направлении думают. Пока же все равно все компоненты зависят от ангуляр core.

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

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

          Принцип работы React, у которого шаблонизатор просто JS и которому не нужна компиляци:
          State Changed -> Rerender -> Reconcile -> Update DOM

          Принцип работы Svelte, который ниче особенного и вообще все это уже было:
          State Changed -> Update DOM

          Разницу улавливаете? Стало понятнее куда делись 2 тяжеленные операции из рантайма и зачем нам компиляци?


          1. Druu
            14.05.2019 18:08
            -1

            На самом деле да. Потому что несмотря на AoT агнуляра делается оно только для шаблонов, а в Svelte не только для них.

            Ну это на самом деле проблема svelte, что приходится делать компиляцию и самого кода компонента. По факту, это ничего полезного не дает.


            Примерно то, что сейча сделает ангуляр, предшественник Svelte, фреймворк Ractive делал уже в 2013 году.

            Только в ractive нету и 10% функционала ангуляра. А так-то да :)


            Хотя в целом в верном направлении думают. Пока же все равно все компоненты зависят от ангуляр core.

            В точности как и у вас они зависят от svelte/core. Просто вы этот svelte/core при компиляции кладете к каждому компоненту.


            Принцип работы React, у которого шаблонизатор просто JS и которому не нужна компиляци:

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


            Стало понятнее куда делись 2 тяжеленные операции из рантайма и зачем нам компиляци?

            Они убрались не из-за компиляции, а из-за того, что у вас cd вместо vdom'a. В ангуляре этих шагов тоже нет. И ни в каком другом фреймворке с cd нет.


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


            1. PaulMaly
              14.05.2019 19:07
              +1

              Ну это на самом деле проблема svelte, что приходится делать компиляцию и самого кода компонента. По факту, это ничего полезного не дает.

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

              Только в ractive нету и 10% функционала ангуляра. А так-то да :)

              А давайте например? Ну чтобы прям 90% только набрать)

              В точности как и у вас они зависят от svelte/core. Просто вы этот svelte/core при компиляции кладете к каждому компоненту.

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

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

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

              Они убрались не из-за компиляции, а из-за того, что у вас cd вместо vdom'a. В ангуляре этих шагов тоже нет. И ни в каком другом фреймворке с cd нет.

              Опять 25)) Для vdom — это и есть cd. Если в случае со Svelte под cd вы подразумеваете строгие стравнения парочки значений, после которых идет точечный вызов DOM API для заранее закэшированных элементов, то ладно, можете называть как хотите. Только на надо это сравнивать с ангуляр, потому что он делает значительно больше вычислений в рантайме. Нет? Приведите пример cd на ангуляр, а я приведу для Svelte и сравним, идет?

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

              Нихрена себе «единственный плюс», это львиная доля вычислений в рантайме. Жирный такой плюс. Когда вы можете написать так:

              <button on:click={e => count++}>Count {count}</button>
              


              А ВЕСЬ cd и render в рантайме будет заключаться в:

              if (changed.count) {
                if (t1.data !== ctx.count) t1.data = ctx.count;
              }
              

              Где закешированная t1 это текстовая нода внутри button (даже document.querySelector не делается!!!)

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


              1. Druu
                14.05.2019 19:41
                -1

                Это не проблема Svelte, а решение проблем других фреймворков.

                Каких именно проблем?


                А давайте например? Ну чтобы прям 90% только набрать)

                ractive — это, опять же, как и svelte чистый рендерер. Там в общем-то ничего нет.


                Это не так, видимо вы так и не посмотрели на исходные коды. Весь Svelte — это чуточка хелперов

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


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

                Без этих шагов он просто перерендерит весь дом, вот и все.


                Опять 25)) Для vdom — это и есть cd.

                В реакте нет cd и vdom нужен только для оптимизации. Семантически реакт просто перерендеривает дом.


                Если в случае со Svelte под cd вы подразумеваете строгие сравнения парочки значений

                Ну в одной компоненте их конечно парочка, но на практике их тысячи.


                Приведите пример cd на ангуляр, а я приведу для Svelte и сравним, идет?

                Сравним как именно?


                А ВЕСЬ cd и render в рантайме будет заключаться в:

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


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

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


                1. mayorovp
                  14.05.2019 21:06

                  В реакте нет cd и vdom нужен только для оптимизации.

                  В том реакте, который я знаю, vdom — это основа всего. Он лежит в основе архитектуры, синтаксиса и семантики. Нельзя так просто взять и отказаться от "просто оптимизации" в реакте.


                  Семантически реакт просто перерендеривает дом.

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


                  1. Druu
                    15.05.2019 08:54

                    В том реакте, который я знаю, vdom — это основа всего. Он лежит в основе архитектуры, синтаксиса и семантики.

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


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

                    Не бывает оптимальных или неоптимальных решений. Бывают достаточно и недостаточно оптимальные.


                    1. mayorovp
                      15.05.2019 09:01

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

                      И как в таком случае будет выглядеть метод render?


                      Не бывает оптимальных или неоптимальных решений. Бывают достаточно и недостаточно оптимальные.

                      Бывают решения, которые менее оптимальны чем другие.


                      1. Druu
                        15.05.2019 09:10
                        -1

                        И как в таком случае будет выглядеть метод render?

                        В смысле? Точно так же и будет. Возвращает кусок дома, описанный на jsx. Ну или прямыми вызовами.


                        Бывают решения, которые менее оптимальны чем другие.

                        Ну да, недостаточно оптимальные решения (оптимальность = 0) менее оптимальны, чем достаточно оптимальные (оптимальность = 1). Но все недостаточно оптимальные эквивалентны друг другу, как и достаточно оптимальные.


                        1. mayorovp
                          15.05.2019 09:14

                          В смысле? Точно так же и будет. Возвращает кусок дома, описанный на jsx. Ну или прямыми вызовами.

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


                          1. vintage
                            15.05.2019 09:23

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


                            1. mayorovp
                              15.05.2019 09:28

                              И при этом, конечно же, никакого инструментария для автоматического проставления этих идентификаторов?


                              А самое веселое при таком подходе начинается если идентификаторы ошибочно повторяются.


                              1. vintage
                                15.05.2019 09:45
                                -1

                                Элементам так или иначе придётся давать имена вручную. Ибо семантику никакая автоматика не сгенерирует.


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


                          1. Druu
                            15.05.2019 09:24

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

                            В данный момент реакт обновляет дом, перезатирая.


                            то такая архитектура никогда не позволит достигнуть состояния "достаточно оптимально".

                            В реакте же позволяет, с некоторыми оптимизациями.


                            1. mayorovp
                              15.05.2019 09:26

                              В данный момент реакт обновляет дом, перезатирая.

                              В данный момент реакт не трогает DOM если нечего менять.


                              В реакте же позволяет, с некоторыми оптимизациями.

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


                              1. Druu
                                15.05.2019 10:35

                                В данный момент реакт не трогает DOM если нечего менять.

                                А если менять надо — то перезатирает.


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

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


                                1. mayorovp
                                  15.05.2019 10:40

                                  Но это просто оптимизация, она никак не влияет на архитектуру и поведение приложения.

                                  Архитектура Реакта возможна в существующем виде только из-за этой "просто оптимизации".


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

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


                                  1. Druu
                                    15.05.2019 11:05
                                    -2

                                    Архитектура Реакта возможна в существующем виде только из-за этой "просто оптимизации".

                                    И без возможна. Просто убираете оптимизацию и получаете реакт без нее.


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

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


                                    1. mayorovp
                                      15.05.2019 11:07

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

                                      Так потому и не теряет, что не пересоздает его. Будет пересоздавать — будет терять.


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

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


                                      1. Druu
                                        15.05.2019 11:16

                                        Так потому и не теряет, что не пересоздает его. Будет пересоздавать — будет терять.

                                        А кто предлагал пересоздавать компонент? Мы вроде обсуждали ререндер дома в ф-и render. Очевидно, вроде, что ререндер дом-дерева компонента и пересоздание самого компонента — вещи существенно разные, нет?


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

                                        Под "поддеревом" и подразумевался компонент. С точки зрения дома, компоненту соответствует некоторое поддерево в этом доме.


                                        1. mayorovp
                                          15.05.2019 11:20

                                          А кто предлагал пересоздавать компонент? Мы вроде обсуждали ререндер дома в ф-и render. Очевидно, вроде, что ререндер дом-дерева компонента и пересоздание самого компонента — вещи существенно разные, нет?

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


                                          Под "поддеревом" и подразумевался компонент. С точки зрения дома, компоненту соответствует некоторое поддерево в этом доме.

                                          Я понял что вы подразумевали. А теперь прочитайте и вы то что я пишу.


                                          PS Чтобы было понятнее о чем я пишу: посмотрите вот этот код (https://codesandbox.io/s/1o9vm152nj) и скажите, как вы планируете сделать что-то аналогичное без виртуального DOM:


                                          class App extends React.Component {
                                            componentDidMount() {
                                              setInterval(() => this.forceUpdate(), 1000);
                                            }
                                          
                                            render() {
                                              return (
                                                <React.Fragment>
                                                  <div>Current time: {new Date().toLocaleString()}</div>
                                                  <input />
                                                </React.Fragment>
                                              );
                                            }
                                          }

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


                                          1. Druu
                                            15.05.2019 13:43

                                            PS Чтобы было понятнее о чем я пишу: посмотрите вот этот код (https://codesandbox.io/s/1o9vm152nj) и скажите, как вы планируете сделать что-то аналогичное без виртуального DOM:

                                            Есть компонент input, у него есть внутреннее состояние, при ререндеринге компонент не пересоздается, с-но состояние не меняется.


                                            1. mayorovp
                                              15.05.2019 14:02

                                              input — не компонент, input — это элемент DOM. Он должен пересоздаваться при каждом рендере просто чтобы реакт остался реактом, а нее превратился во что-то непохожее.


                        1. vintage
                          15.05.2019 09:20
                          +1

                          Возвращает кусок дома, описанный на jsx. Ну или прямыми вызовами.

                          Это уже будет не Реакт. От слова "Вообще".


  1. JustDont
    12.05.2019 11:11
    +2

    Как мы сделаем то же самое в React? Скорее всего, это будет выглядеть примерно так:

    Автор, а функции отдельно вы написали специально для того, чтоб символов побольше напечатать? Люблю такие бессмысленные и беспощадные специальные олимпиады.

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


    1. mayorovp
      13.05.2019 11:00

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


      const handleChangeA = useCallback(event => setA(+event.target.value));

      Не сильно меньше кода получилось.


      1. JustDont
        13.05.2019 11:29
        -1

        Разумеется. Но во-первых, статья не про best practices, если вы заметили. А про длину кода в буквах.

        Во-вторых,

        лучше никогда не писать, поскольку они ломают все оптимизации

        не обязательно. Зависит от того, что, где, и в каком контексте вы написали. «Ломают все оптимизации» — это очень громкое и очень неправильное обобщение.


        1. PaulMaly
          14.05.2019 12:25

          статья не про best practices, если вы заметили. А про длину кода в буквах.

          Не совсем так, просто в Svelte best practices сразу означают и мало кода в буквах. ;-)


    1. PaulMaly
      14.05.2019 12:24
      +1

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


      1. JustDont
        14.05.2019 13:26

        В рамках svelte это идёт на уровне «надо помнить, что там это делается само, потому что вот так вот». Вам по этому поводу уже выше всё хорошо расписали — это далеко не самый приятный подход. Неочевидное плохо практически всегда, разве что иногда можно с ним мириться, если неочевидное даёт другие существенные плюсы (в RP неочевидного всегда море, но там и плюшки от RP соизмеримы). А когда оно экономит + или +'' — такое себе.


        1. PaulMaly
          14.05.2019 13:57

          Вам по этому поводу уже выше всё хорошо расписали — это далеко не самый приятный подход.

          Хм, если бы мне что-то хорошо расписали, я бы заметил… Можете уточнить что именно?

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

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


          1. JustDont
            14.05.2019 14:03

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

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

            Я в вашем посте читаю «там надо приводить и в шаблон это впихивать неочень, а вот у нас не надо приводить, всё сделано без вас».


            1. PaulMaly
              14.05.2019 14:32

              Да?

              Да.

              Я в вашем посте читаю «там надо приводить и в шаблон это впихивать неочень, а вот у нас не надо приводить, всё сделано без вас».

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

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


              Я вам ответил, что так написано не только потому, что:

              это более читаемо, но и потому что там идет приведение строки к числу.


              Вы написали:

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


              Я вам ответил, что пример это явно ухудшит, так как:

              В разметке JSX это будет смотреться просто ужасающе. Никто в своем уме так не пишет.


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

              import React, { useState } from 'react';
              
              export default () => {
                  const [a, setA] = useState(1);
                  const [b, setB] = useState(2);
              
                  return (
                      <>
                          <input type="number" value={a} onChange={e => setA(+e.target.value)}/>
                          <input type="number" value={b} onChange={e => setB(+e.target.value)}/>
              
                          <p>{a} + {b} = {a + b}</p>
                      </>
                  );
              };
              

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

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

              <script>
                let a = 1, 
                    b = 2;
              </script>
              
              <input type="number" value={a} on:input={e => a = +e.target.value}>
              <input type="number" value={b} on:input={e => b = +e.target.value}>
              
              <p>{a} + {b} = {a + b}</p>
              


              Не говоря уже о самом принципе работы, когда на любое изменение любого поля в Реакт будет заново вызваны все useState, далее будет полный rerender + reconcile всего компонента, просто чтобы поменять пару нод. Чтож поделать, у реакта просто дизайн такой. Нравится так писать? Никто вас не заставляет писать по-другому, но и врать себе не надо. Это действительно совершенно разный DX.


              1. JustDont
                14.05.2019 14:48

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

                Стало ложным следующее утверждение из статьи:
                Иначе говоря, требуется 442 символа в React и 263 символа в Vue, чтобы достичь чего-то, что в Svelte занимает 145 символов. Версия React буквально в три раза больше!

                Опачки, уже не в три раза и даже не в два, а на полтора десятка букв длиннее Vue.
                Мой начальный комментарий — именно о том, что если уж вы пытаетесь натянуть вырожденный пример на достоинство фреймворка, то делать это нужно честно. На мой опыт чтения «хайповых» статей (на хабре и за пределами) — так не делает почти никто. Статья про хайп технологии Х? Будем сравнивать вылизанный код Х с кривоватым кодом Y, и сделаем вид, что всё нормально. Тут — то же самое. Если уж сравниваете количество значащих букв (хотя метрика на редкость, простите мой французский, дебильная) — то делайте это честно.

                Нравится так писать?

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

                Никто вас не заставляет писать по-другому, но и врать себе не надо.

                Врать в статьях тоже не надо. Но вот поди ж ты.


                1. PaulMaly
                  14.05.2019 15:23

                  Стало ложным следующее утверждение из статьи:

                  Почему ложным? Автор статьи привел идеоматические примеры для React/Vue/Svelte и посчитал букавы. Вы же начали разговор со своих предпочтений. Считаете что на React или Vue примеры могут быть короче и написаны специально, чтобы сделать длинее? Я так не считаю. Кроме того на Svelte длинее просто не получается, если только биндинги не использовать, но какие для этого причины? В примере на Vue тоже используется биндинг, а в React его просто нет.

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

                  Пример не мой, но мне кажется что читать надо построчно.

                  1) Где короче всего завести переменную в стейте с возможностью изменения? Варианты ответов:
                  a)
                  let a = 0;
                  


                  b)
                  import { useState } from 'react';
                  ...
                  const [a, setA] = useState(0);
                  


                  c)
                  export default {
                    data() {
                      return {
                        a: 1
                      };
                    }
                  };
                  


                  2) Как короче считать переменную в виде числа из поля для ввода и записать в переменную? Варинты ответов:
                  a)
                  <input type="number" bind:value={a}>
                  


                  b)
                  <input type="number" value={a} onChange={e => setA(+e.target.value)}/>
                  


                  c)
                  <input type="number" v-model.number="a">
                  


                  3) Обязательный корневой элемент шаблона увеличивает кол-во необходимых букаф? Варинты ответов:
                  a) Да
                  b) Нет

                  И так далее. Мне кажется ответы очевидны. Об чем тогда спор?

                  На мой опыт чтения «хайповых» статей (на хабре и за пределами) — так не делает почти никто.

                  Готов принять ваше пари. Пишите код на React/Vue так как вы считаете нужным, а я напишу аналог на Svelte и посчитаем. Ок?

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


                  Гхарк… извините, пил кофе, поперхнулся и залил им весь стол. Чего там у Реакт хорошо? Шаблоны? Это JSX который? Жвачкой прилепили DSL на основе императивного языка программирования поверх декларативного XML-like языка? Это еще ладно, можно привычнуть. Опять же там Typescript сразу из коробки. Ок. Но рендер? Вы это вообще серьезно? Он же тупо вызывает заново функцию на КАЖДЫЙ пчих, вообще на каждый и заново делает rerender + reconcile всего компонента вообще на любое изменение! Я вообще не представляю о чем думали люди, которые это писали. Основная версия все еще то, что они были из мира PHP, где на любой запрос создается новый тред и все такое.

                  Чтобы уважаемые реактоводы на меня не обиделись, опишу что действительно хорошо у Реакта:
                  1) Facebook + community + tooling
                  2) Действительно много готовых компонентов и не только компонентов
                  3) Действительно много работы с хорошими зп
                  4) React Native


                  1. JustDont
                    14.05.2019 15:33

                    Готов принять ваше пари. Пишите код на React/Vue так как вы считаете нужным, а я напишу аналог на Svelte и посчитаем. Ок?

                    Так вы ж уже написали выше. И я даже посчитал. Длиннее вышло? Ну да. Но, в общем, не в разы.

                    Шаблоны? Это JSX который? Жвачкой прилепили DSL на основе императивного языка программирования поверх декларативного XML-like языка?

                    Вы где-то в мире фронтэнда видели шаблоны лучше? Я — нет. Как не пытайся совмещать декларативщину с императивщиной, а какие-то минусы будут всегда. Намазывать неродную декларативщину поверх html чтоб что-то там сделать, как делает тот же ангуляр (да и вообще это очень древний подход, куда древнее нынешнего хипстерского фронтэнда) — тоже мягко говоря такое себе, в декларативщину не всё удобно влезает, и монструозные конструкции всё равно появляются. А уж как приятно что-то динамическое там генерить (нет), ммм!

                    Он же тупо вызывает заново функцию на КАЖДЫЙ пчих, вообще на каждый и заново делает rerender + reconcile всего компонента вообще на любое изменение!

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


                    1. PaulMaly
                      14.05.2019 17:01

                      Так вы ж уже написали выше. И я даже посчитал. Длиннее вышло? Ну да. Но, в общем, не в разы.

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

                      Вы где-то в мире фронтэнда видели шаблоны лучше? Я — нет. Как не пытайся совмещать декларативщину с императивщиной, а какие-то минусы будут всегда.

                      Любой настоящий DSL, а знаете почему? Потому что там ключевая фраза «domain specific», то есть можно спроектировать код конкретную доменную область, в данном случае под HTML. Является ли Javascript «domain specific» для HTML? Очевидно нет, это как бы язык общего назначения. Как он вообще может быть лучше чем DSL? Никак.

                      тоже мягко говоря такое себе, в декларативщину не всё удобно влезает, и монструозные конструкции всё равно появляются

                      Сравним парочку конструкций?

                      <div>
                      {conditionA ? (
                        <Foo />
                      ) : conditionB ? (
                        <Bar />
                      ) : (
                        <Baz />
                      )}
                      </div>
                      }
                      

                      vs

                      <div>
                      {#if conditionA}
                        <Foo />
                      {:else if conditionB}
                        <Bar />
                      {:else}
                        <Baz />
                      {/if}
                      </div>
                      


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

                      <ul>
                      {numbers.map((value) =>
                        <ListItem key={value.toString()} value={value} />
                      )}
                      </ul>
                      

                      vs

                      <ul>
                      {#each numbers as value (value)}
                        <ListItem {value} />
                      {/each}
                      </ul>
                      


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

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

                      Это он то простой? По вашему это просто когда на то, чтобы поменять одну букавку в DOM нужно сперва построить копию DOM в памяти, потом пройтись по всем нодам и их аттрибутам и сравнить? Это просто? Нет, во-первых, это не просто, во-вторых, глупо и не опимально. И ребята из реакта знают об этом, именно поэтому и придумали всякие там shoudComponentUpdate/PureComponent/useMemo/useCallback. Они вам как бы говорят, ребята ну тут написали крайне хреновую и тяжелую абстракцию, а вы давайте там уж сами как-то разгребайте если у вас она будет плохо работать.

                      А вот что делает Svelte, если значение a изменилось:

                      if (changed.a) input0.value = ctx.a;
                      
                      if (changed.a) {
                        set_data(t2, ctx.a);
                      }
                      
                      if ((changed.a || changed.b) && t6_value !== (t6_value = ctx.a + ctx.b)) {
                        set_data(t6, t6_value);
                      }
                      


                      Где set_data это обертка над `el.data = text`, а всякие там input0 и t2 — закэшированные ссылки на нужные DOM ноды. И это весь rerender + reconcile который нужен.

                      Кстати, по поводу сторонних стейт менеджеров. Смотрите фокус:

                      <script>
                        import { interval } from 'rxjs';
                      
                        let count = interval(400);
                      </script>
                      
                      <h1>The count is {$count}</h1>
                      


                      Или вот еще, только на Effector:

                      <script>
                        import { createStore, createEvent } from 'effector';
                      
                        let inc = createEvent('counter ++');
                        let counter = createStore(0).on(inc, n => n + 1);
                      </script>
                      
                      <h1>Count: {$counter}</h1>
                      <button on:click={inc}>Increment</button>
                      



                      1. JustDont
                        14.05.2019 18:02
                        -1

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

                        Ну то есть вы сами накатали укороченный реактовый пример, который хоть и не best practices, но в рамках статейного сравнения вполне себе нормальный, и который разбивает утверждение про «реакт длиннее в разы» — и далее всё тот же вы говорите, что в статье всё норм.
                        Такое себе.

                        Сравним парочку конструкций?

                        Они не имеют принципиальных различий. Ну, разве что писать многуровневый тернарник — это в принципе не стоит. Но —
                        <div>
                        {() => {
                          if (conditionA) 
                            return <Foo />;
                          else if (conditionB)
                            return <Bar />;
                          else
                            return <Baz />;
                        }()}
                        </div>

                        уж точно не страшнее варианта svelte. Шелухи вокруг на некоторое количество букв больше, но читается прекрасно. Ну и это plain JS, а не третий набор конструкций для заучивания (впрочем, в JSX html — это не совсем html, так что JSX тут не вырывается вперед один фиг).

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

                        Кроме того, что DSL проще читается в потоке HTML

                        Подождите-подождите, вы всерьез считаете, что в svelte вы пишете чистый HTML с вкраплениями конструкций её DSL? Но это очевидно не так — HTML в svelte — это тоже «не совсем HTML», и вы точно так же останетесь с формально валидным, но не работающим HTML, если попробуете предварительно заменить все DSL-вставки на их вычисленный результат. Все эти bind: on:, и так далее в любом случае без svelte становятся тыквой, как без реакта становится тыквой className. Принципиальных различий с JSХ тут нет.

                        И ребята из реакта знают об этом, именно поэтому и придумали всякие там shoudComponentUpdate/PureComponent/useMemo/useCallback.

                        Это не рендер, это state management. Всё, что вы тут написали. Как я уже сказал, state management в реакте настолько примитивный, что постоянно надо закатывать солнце руками — отсюда и этот список. Рендеру же и не надо быть сложным.

                        Кстати, по поводу сторонних стейт менеджеров. Смотрите фокус

                        Это не фокус. RP в разных парадигмах очень легко переходит друг в друга (паттерн-то один и тот же), а так же в не-RP код и обратно. Это не достоинство svelte, это просто признак нормального RP.


                        1. PaulMaly
                          14.05.2019 18:27

                          Ну то есть вы сами накатали укороченный реактовый пример, который хоть и не best practices, но в рамках статейного сравнения вполне себе нормальный, и который разбивает утверждение про «реакт длиннее в разы» — и далее всё тот же вы говорите, что в статье всё норм.
                          Такое себе.

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

                          Такая сильная разница скорее исключение — из моего опыта, компонент React обычно примерно на 40% больше, чем его эквивалент на Svelte.


                          Итак, этот компонент на React примерно на 40% больше чем на Svelte? Думаю похоже на правду.

                          Я ж вроде про конкретные примеры спросил.

                          Легко: github.com/htmlx-org/HTMLx

                          «Любой настоящий DSL» конечно будет лучше. В рамках своего D, вот в чем загвоздка. А вне рамок — вообще не в тему.

                          А зачем нам шаблонизатор HTML вне рамок HTML? Вы меня прям смутили)))

                          Они не имеют принципиальных различий. Ну, разве что писать многуровневый тернарник — это в принципе не стоит. Но —

                          Они имеют очень даже принципиальные различия. И вы своим примером лишь доказали сразу 2 вещи: 1) излишняя свобода в написании управляющих конструкция поверх html — это плохо; 2) JSX — это ни разу не JS, лишь его подмножество. Если бы это было не так, вам не пришлось бы изгоняться с дополнительной анонимной функцией, чтобы написать обычный if-else.

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

                          А я может хочу for или while использовать. Тоже в анонимную функцию оборачивать? )))

                          Подождите-подождите, вы всерьез считаете, что в svelte вы пишете чистый HTML с вкраплениями конструкций её DSL? Но это очевидно не так — HTML в svelte — это тоже «не совсем HTML», и вы точно так же останетесь с формально валидным, но не работающим HTML, если попробуете предварительно заменить все DSL-вставки на их вычисленный результат. Принципиальных различий с JSХ тут нет.

                          Во-первых, он валидный, а значит никаких сюрпризов для тех, кто уже знает HTML. Во-вторых, этот HTML без проблем отрисует даже браузер, просто все DSL конструкции он примет на TextNode. JSX же даже синтаксически не является ни валидным HTML, ни валидным JS. Эдакий чудоудюрыбакит. Начинаешь писать JS, опс, оказывается не всякую конструкцию из JS можно использовать. Начинаешь писать HTML, опять нет.

                          Это не рендер, это state management. Всё, что вы тут написали. Как я уже сказал, state management в реакте настолько примитивный, что постоянно надо закатывать солнце руками — отсюда и этот список. Рендеру же и не надо быть сложным.

                          Не понимаю как вы разделяете рендер и стейт менеджмент при state-driven подходе. И все же это рендер тупой и тормозной, потому что он даже понятия не имеет какие данные стейта используются для рендера, а какие нет. И еще раз прочитайте вот эту часть, тут чисто про рендер:

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


                          Это не фокус. RP в разных парадигмах очень легко переходит друг в друга (паттерн-то один и тот же), а так же в не-RP код и обратно. Это не достоинство svelte, это просто признак нормального RP.

                          Раз это не фокус, а давайте вы тоже самое на React напишете и мы с вами сравним код, а?


                          1. JustDont
                            14.05.2019 18:52

                            Итак, этот компонент на React примерно на 40% больше чем на Svelte? Думаю похоже на правду.

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

                            И вы своим примером лишь доказали сразу 2 вещи: 1) излишняя свобода в написании управляющих конструкция поверх html — это плохо; 2) JSX — это ни разу не JS, лишь его подмножество. Если бы это было не так, вам не пришлось бы изгоняться с дополнительной анонимной функцией, чтобы написать обычный if-else.

                            1 — да нет, нормально.
                            2 — а где-то утверждалось обратное? Вы спорите со своими собственными фантазиями о JSX?

                            А я может хочу for или while использовать. Тоже в анонимную функцию оборачивать? )))

                            Конечно. И ничего страшного в этом нет. У вас глаз за лишнюю пару скобок цепляется настолько сильно, что прям жизни нет?

                            Во-первых, он валидный, а значит никаких сюрпризов для тех, кто уже знает HTML.

                            И хоть сколько-нибудь значимым достоинством это не является. «Знающий HTML» напишет onclick=, а потом будет удивляться, что у него там прекрасностей svelte не добавляется.

                            Во-вторых, этот HTML без проблем отрисует даже браузер, просто все DSL конструкции он примет на TextNode.

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

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

                            Всякую, но не напрямую. С HTML — то же самое, что и в svelte. Хочешь реакта? Будь добр писать именно так, как ожидает от тебя реакт, а иначе весь реакт пройдет мимо. Что class нельзя написать — и вовсе забавный факт несовпадения окружения, то же самое, что и то, что вы стили в JS пишете кэмелкейсом, а не через -.

                            Раз это не фокус, а давайте вы тоже самое на React напишете

                            В реакте нет RP из коробки, что я вам напишу? Там весь код будет про то, как подружить RP с setState/useState. Ничего интересного. Какой-нибудь MobX со своим изкоробочным решением для реакта сделает это за вас.

                            Не понимаю как вы разделяете рендер и стейт менеджмент при state-driven подходе.

                            Очень просто: надо ли мне что-то из вашего списка, если я не использую setState/useState (в угоду каким-то сторонним решениям, которые сделают это за меня максимально корректным и минимальным образом)? Нет, не надо. Будут ли у меня отрисованы компоненты? Да, будут.

                            И еще раз прочитайте вот эту часть, тут чисто про рендер:

                            «Эта часть» меня вообще никак не волнует, пока мой код проходит по памяти и скорости (а у меня есть очень-очень большой и сложный код на реакте+mobx, который всё отлично проходит). Как известно из других статей о svelte — быстродействием против хорошо написанного реакта она не поражает. Память мерить куда сложнее, но, опять же, пример не лабораторного, а реального сложного кода мне говорит о том, что весь этот «страшно неэффективный» процесс рендера реакта не так уж память и жрет, чтоб это было заметно на практике даже в сложных по памяти условиях.


                            1. PaulMaly
                              15.05.2019 12:42
                              +1

                              А я с этим и не спорил. Я спорил с «в разы».

                              Автор потом отдельно отметил, что это скорее исключение, а обычно это порядка +40%. Не нужно быть таким чувствительным.
                              «Такая сильная разница» в статье взялась не потому, что иногда реакт в разы длиннее, а потому, что автор статьи пример на реакте написал избыточно длинно, только и всего.

                              Не избыточно, а идеоматически. В этом смысле все примеры написаны одинаково так, как их советуют писать в учебниках/доках/докладах. Svelte отличается лишь тем, что длинее писать смысла нет.)))

                              1 — да нет, нормально.
                              2 — а где-то утверждалось обратное? Вы спорите со своими собственными фантазиями о JSX?

                              1) это плохо, почему я описал. почему это нормально по-вашему, я так и не понял. Мой поинт очень прост — читать DSL в потоке HTML вообще задача не плостая, не надо ее усложнять вариативностью данных конструкций.
                              2) Все пишут что JSX — «это просто JS», но это заблуждение. Это subset на основе JS синтаксиса, тот же DSL только не очень то подходящий доменному языку.

                              И хоть сколько-нибудь значимым достоинством это не является. «Знающий HTML» напишет onclick=, а потом будет удивляться, что у него там прекрасностей svelte не добавляется.

                              Так пусть напишет))) И значете что произойдет? Все будет работать так, как он привык в HTML: svelte.dev/repl/472f3af895ae4accb75dace2b872099e?version=3.3.0

                              Конечно же разработчик не настолько глуп, чтобы ожидать что стейт Svelte будет доступен в стандартном обработчике HTML, но все остальное может работать там как обычно и без ошибок. Так что да, Svelte — это валидный HTML/CSS/JS. Магия))

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

                              О, ценность огромная. Например, у нас программисты и верстальщики — это разные люди. Представяете насколько проще верстальщику заверстать компонент на HTML/CSS как он привык, без необхомости заучивать подводные камни JSX? Вместо шаблонизатора он испльзует статические тексты, поэтому даже сборку ему настраивать ненадо. А когда он его заверстал, он просто передает файлик разработчику, и тот лишь дописывает его. Не портирует из HTML/CSS в JSX/CSS-in-JS, а просто дописывает. Это нереально удобно и реально экономит время и силы.

                              Всякую, но не напрямую. С HTML — то же самое, что и в svelte. Хочешь реакта? Будь добр писать именно так, как ожидает от тебя реакт, а иначе весь реакт пройдет мимо.

                              Пример и все описанное выше надеюсь все же убедит вас, что Svelte — это валидный HTML/CSS/JS без нюансов.

                              Что class нельзя написать — и вовсе забавный факт несовпадения окружения, то же самое, что и то, что вы стили в JS пишете кэмелкейсом, а не через -

                              Да уж чего там class. Там и style нельзя писать. И с svg проблемы и еще кучу всего. Давайте просто пойдем от противного:

                              React:
                              1) Валидный JS всегда валидный JSX, так? НЕТ
                              2) Валидный HTML всегда валидный JSX, так? НЕТ

                              Svelte:
                              1) Валидный JS всегда валидный Svelte, так? ДА
                              2) Валидный HTML всегда валидный Svelte, так? ДА

                              Что и требовалось доказать.

                              В реакте нет RP из коробки, что я вам напишу? Там весь код будет про то, как подружить RP с setState/useState. Ничего интересного. Какой-нибудь MobX со своим изкоробочным решением для реакта сделает это за вас.

                              Вы говорили же про использования внешних решений. Я вам привел 2 очень простых примера интеграции Rxjs и Effector в Svelte. Можете просто переписать их на React, чтобы мы ощутили разницу того, как же круто и офигенно реакт позволяет интегрировать сторонние стейт менеджеры по сравнению с убогим Svelte?

                              Очень просто: надо ли мне что-то из вашего списка, если я не использую setState/useState (в угоду каким-то сторонним решениям, которые сделают это за меня максимально корректным и минимальным образом)? Нет, не надо. Будут ли у меня отрисованы компоненты? Да, будут.

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

                              «Эта часть» меня вообще никак не волнует, пока мой код проходит по памяти и скорости (а у меня есть очень-очень большой и сложный код на реакте+mobx, который всё отлично проходит)

                              Ответ на предыдущий комментарий относится и сюда. Нравится крутить реактивностью отдельно — пожалуйста. Мне не понятно почему не использовать уже готовые решения.

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

                              Ну давайте посмотрим. React + Mobx говорите?



                              Так то вообще огонь конечно. Всего то в 1,5-2,5 раза хуже по всем показателям. Так что все ок, не волнуйтесь, используйте дальше и пусть ваши юзеры будут счастливы ;-)


                              1. JustDont
                                15.05.2019 13:26
                                -1

                                Вы сейчас перешли ту самую границу, которая отделяет нормальных людей от людей типа vintage. Скажите, на что вы рассчитываете, когда постите картинки откуда-то из ангажированных источников без детализации? Вы всерьез думаете, что я не схожу к автору js-framework-benchmark и не посмотрю результаты, которые постит он сам?
                                image
                                Ой, реакт фейлит на перестановку строк в таблице способом «в лоб». Это очень нужная операция в боевом коде и я прям очень страдаю от того, что она медленная (нет).
                                А в остальном разница минимальна. Это именно то, что я имел в виду под «быстродействием против хорошо написанного реакта она не поражает». Потому что реально не поражает.

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

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


                      1. Druu
                        14.05.2019 18:36

                        The count is {$count}

                        А почему ошибку тут не выводит, как и в примере ниже?


                        1. PaulMaly
                          14.05.2019 19:09

                          В каком примере ниже? И почему должно?


                          1. Druu
                            14.05.2019 19:46

                            В каком примере ниже?

                            Во втором примере с effector.


                            И почему должно?

                            Ну там же observable. Или шаблон будет выводить не значение обсервабла, а сам обсервабл?


                            1. PaulMaly
                              15.05.2019 12:10

                              Ну там же observable. Или шаблон будет выводить не значение обсервабла, а сам обсервабл?

                              А это и есть фокус. Вообще там в обоих случаях, не только с effector, обсервабл ;-)


                      1. vintage
                        14.05.2019 19:13
                        -2

                        Сравним парочку конструкций?

                        Давайте сравним:


                        content() {
                          if( conditionA ) return this.Foo()
                          if( conditionB ) return this.Bar()
                          return this.Baz()
                        }

                        number_views() {
                          return this.numbers().map( value => this.Number_view( value ) )
                        }


                        1. mayorovp
                          14.05.2019 21:27
                          +1

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


                          Во втором примере всё ещё хуже. Мало того, что код не имеет ничего общего с DOM, так ещё и выглядит куда менее аккуратно чем JSX — а ведь это ещё постараться надо было...


                          Блин, да даже на jquery у меня понятнее получалось!


                          1. vintage
                            15.05.2019 02:06
                            -1

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

                            Есть у Реакта такой недостаток, да.


                            Мало того, что код не имеет ничего общего с DOM

                            Логика в принципе не может иметь ничего общего с DOM, так как DOM — это структура данных, а логика — нет.


                            выглядит куда менее аккуратно чем JSX

                            Что такое "аккуратно"?


                    1. Druu
                      14.05.2019 18:30

                      (да и вообще это очень древний подход, куда древнее нынешнего хипстерского фронтэнда)

                      Вообще-то, нет. Генерить результат "напрямую", как в реакте — на десятки лет более старый подход, чем темплейты :)
                      С-но, темплейты и были придуманы как решение проблем, вызванных использованием подхода реакта. Не наоборот :)


                      1. JustDont
                        14.05.2019 18:32

                        Вы не с тем спорите. Я не утверждал, что подстановки моложе шаблонов. И то, и другое — очень старые вещи. Я лишь говорил о том, что оно старее нынешнего фронтэнда.


                    1. vintage
                      14.05.2019 19:03
                      +1

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

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


                    1. mayorovp
                      14.05.2019 21:16

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

                      Вот только сама необходимость такого стороннего стейт менеджера и является недостатком.


                      1. JustDont
                        14.05.2019 21:35
                        +1

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


                        1. Druu
                          15.05.2019 09:05
                          +1

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

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


                          1. JustDont
                            15.05.2019 10:52

                            Любой десктопный уи-фреймворк или бекенд-фреймворк?

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

                            С-но, единственная отрасль где вообще обсуждается вопрос «комбайн вс некомбайн» — это фронтенд.

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

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

                            Ну да, ангуляр всегда лучше «по понятным причинам» (с). А пацаны-то и не знали.


                            1. Druu
                              15.05.2019 11:11

                              когда и комбайн отстоен, и альтернатив никаких

                              А почему альтернатив никаких, вы не думали?


                              единственный период времени, где вообще появились вопросы «комбайн вс некомбайн» — это сейчас

                              Это "сейчас фронтенд". Потому что вне фронтенда этот вопрос и сейчас не стоит. И стоять не будет.


                              И уже не надо писать многомегабайтное «цельное» решение

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


                              Ну да, ангуляр всегда лучше «по понятным причинам» (с).

                              Ну именно так. Если вам нужно сложное приложение, а не очередной твиттер, и у вас нету проблем с "многомегабайтностью" (а их обычно в таком случае нет), то альтернатив ангуляру в 2019 в общем-то и не придумали.


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


                              1. JustDont
                                15.05.2019 11:19

                                А почему альтернатив никаких, вы не думали?

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

                                Это «сейчас фронтенд». Потому что вне фронтенда этот вопрос и сейчас не стоит. И стоять не будет.

                                Посмотрим.

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

                                Мне остаётся только повторить «а пацаны-то и не знают». Ну вот реально, мир пишет примерно на чём угодно, Китай — больше на Vue, остальные — больше на реакте, сложность приложения тут вообще никаким боком, потому что пишут что угодно, и тут выходит на сцену Druu, и говорит человечьим голосом: ребята! Вы ничего не понимаете! Альтернатив ангуляру нет! Не беспокоиться может только твиттер!
                                Если реальность не соответствует вашим воззрениям — тем хуже для реальности, так что ли?

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


                                1. Druu
                                  15.05.2019 13:49

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

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


                                  Если реальность не соответствует вашим воззрениям — тем хуже для реальности, так что ли?

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


                                  публично доступных приложений в интернете — у гугла

                                  Это какое?


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

                                  А почему не на реакте/вуе или свелте? :))
                                  Потому что легаси и переписывать дорого. А так у них были продукты на том же первом ангуляре. Сейчас есть и на втором, основная часть для внутреннего использования, скорее всего.


                                  1. JustDont
                                    15.05.2019 14:04

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

                                    С точки зрения джуна/мидла — ага.
                                    С точки зрения человека более опытного — огромное значение имеют ответы на вопросы «где мы будем брать людей, знакомых с технологией, и во сколько денег они нам обойдутся», а так же «где мы будем искать пути решения проблем, с которыми мы столкнёмся». Для первого вопроса «Китай или не Китай» внезапно оказывается очень важным. Для второго — в меньшей степени, но тоже важным.

                                    А она соответствует, вполне. Кровавый интерпрайз пишется на ангуляре

                                    Кровавый энтерпрайз пишется на чем попало. У нас, например, половина нового (3 и менее года от начала запиливания proof of concept) энтерпрайза на ангуляре, половина — на реакте. Те, что на ангуляре — очень радуются, потому что у них, например, есть и то, что на angularJS, и они вместо развития сидят и думают, как они это всё переписывать будут. Те, у кого актуальный ангуляр — тоже сидят и думают, как бы им переделать их имеющиеся оптимизации рендера, потому что нынче ivy делает как раз примерно то самое, что у них понаворочено, только лучше. В общем, благодать.

                                    Потому что легаси и переписывать дорого

                                    Угу. И для кровавого энтерпрайза это как раз обычная причина №1 для того, что что-то написано на технологии Х. Не потому, что «лучше», не потому, что «хуже», а потому, что в своё время начали писать именно на Х, а переписывать дорого.


                        1. mayorovp
                          15.05.2019 09:19

                          Вот только фокус в том, что комбинация внешнего стейт-менеджера с реактом "грамотным сочетанием" не является.


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


                          1. JustDont
                            15.05.2019 10:58

                            К примеру, в текущей архитектуре react невозможно избавиться от повторного рендера сразу после монтирования компонента

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


                            1. mayorovp
                              15.05.2019 11:02

                              Ну да, это именно проблема реакта.


                              1. JustDont
                                15.05.2019 11:47

                                Пошел проверил — и оказывается, я всё это время неправильно понимал суть™.
                                Реакт в принципе с нуля всё два раза рендерит. Скорее всего потому, что первый раз в vdom, а второй уже реально. Там и экземпляры компонентов разные, для vdom и не для vdom. Потом, при дальнейших апдейтах, как я понимаю, измененные куски отправляются в vdom напрямую, потому что дальше никаких лишних дёрганий render() нет.

                                ЗЫ: Или даже нет… проверять это в онлайн-песочнице было плохой идеей. Надо б экспериментировать в чистом браузере. Вообще конечно забавно, что мне пришлось три раза перезагрузить страницу на codesandbox, чтоб у меня ts взлетел должным образом в песочнице.


                                1. mayorovp
                                  15.05.2019 12:08

                                  Фаза "рендерит реально" называется reconcile.


                                  Когда я говорил "рендерит два раза" — я имел в виду именно два вызова render, с фазой reconcile после каждого (но вторая фаза почти всегда холостая).


                                  1. JustDont
                                    15.05.2019 12:13

                                    Когда я говорил «рендерит два раза» — я имел в виду именно два вызова render

                                    Я именно это и полез проверять. На изменения в самом dom я и до этого смотрел, и там ничего интересного. И лишнего.

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


                                    1. mayorovp
                                      15.05.2019 12:16

                                      А вы не забыли в методе componentDidMount вызвать setState или forceUpdate?


                                      1. JustDont
                                        15.05.2019 12:25

                                        А зачем? Я пошел посмотреть в ответ на ваше

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

                                        Зачем я буду руками дёргать стейт, если у меня менеджер?
                                        Ну и к слову, всё-таки привёл минимальный пример в рабочее состояние, несмотря на ненужную возню с песочницей: codesandbox.io/embed/n9k74ly1v0
                                        Вы видите там лишние рендеры? Я — нет.


                                        1. mayorovp
                                          15.05.2019 13:58

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


                                          Любой стейт-менеджер вынужден выбирать между повторным рендером и утечками памяти в Concurrent Mode.


                                          В mobx-react на данный момент заткнули проблему через очистку незакоммиченных реакций по тайм-ауту (магический тайм-аут взят с потолка). Выглядит полным костылем.


                                          Вот ещё интересная ссылка: https://github.com/facebook/react/issues/15317


                                          1. JustDont
                                            15.05.2019 14:16

                                            Спасибо за ссылки. Да, это всё выглядит дикими костылями.


                  1. vintage
                    14.05.2019 18:59
                    -2

                    Где короче всего завести переменную в стейте с возможностью изменения?

                    a?v 0

                    Это на view.tree.


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

                    $mol_number value?v <=> a?v

                    Это тоже на view.tree. При этом эти два код можно и объединить:


                    $mol_number value?v <=> a?v 0

                    Обязательный корневой элемент шаблона увеличивает кол-во необходимых букаф?

                    Как правило общий корневой дом элемент вокруг компонента необходим в целях визуализации. Так что это довольно сомнительное преимущество.


  1. firk
    12.05.2019 12:12
    -1

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


    Также я не утверждаю, что уменьшение строк кода — это самоцель, так как это может способствовать превращению нормального читаемого кода, вроде этого…
    for (let i = 0; i <= 100; i += 1) {
        if (i % 2 === 0) {
            console.log(`${i} — чётное`);
        }
    }


    … во что-то неудобоваримое:

    for (let i = 0; i <= 100; i += 1) if (i % 2 === 0) console.log(${i} — чётное);

    Для таких конструкций (по 1 строчке во вложенном блоке) всегда использую второй вариант. Он просто лучше читается и не выглядит простынёй кода, замусоренной пробелами. И при "приёме чужого кода в разработку" одним из первых дел конвертирую эти неудобные простыни в нормальный компактный код.


    1. NightGhost
      12.05.2019 18:28
      +12

      Сочувствую вашим коллегам


      1. sumanai
        12.05.2019 20:32

        Это исправляется автоформатированием в IDE. А вот как firk переводит код из нормальной формы в однострочную, кроме как вручную, я не знаю. Написал свой плагин для автоформатирования?


        1. NightGhost
          13.05.2019 12:02

          Мне кажется таким людям должно доставлять удовольствие вручную форматировать «простыни». Этакий отдельный вид мазохизма.


          1. sumanai
            13.05.2019 20:45
            +2

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


            1. firk
              14.05.2019 12:06

              Ну что такое, я вовсе не заявлял, что надо весь код писать в одну строчку.
              Но фигурные скобки, переводы строк и отступы вокруг одного statement, прекрасно влезающего в строку, на мой взгляд лишние. И даже иногда вокруг двух (ну тут без фигурных скобок уже не обойтись естественно а вот остальное можно убрать), если второе — передача управления (return, continue, break, goto).

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

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


    1. biziwalker
      12.05.2019 19:48
      -4

      Мне вот оба варианта не нравятся, более читаемый вариант:

      Array.from(Array(100).keys())
          .filter(i => i % 2 === 0)
          .forEach(i => console.log(`${i} — чётное`));
      


      1. TheShock
        12.05.2019 21:45

        На самом деле, самое главное в таком стиле — подходящая либа:

        const isEven = i => i % 2 === 0;
        const range  = num => [ ...Array(num).keys() ];
        const log    = item => console.log(item);


        И тогда мы получаем следующее:
        range(100)
          .filter(isEven)
          .map(it => `${i} — чётное`)
          .forEach(log);


        1. Imbecile
          14.05.2019 12:38
          +1

          Нужно реактивно

          import { range } from 'rxjs';
          import { filter, map } from 'rxjs/operators';
          
          range(1, 100).pipe(
            filter(n => n % 2 === 0),
            map(n => `${n} - чётное`)
          ).subscribe(console.log);


      1. Tangeman
        12.05.2019 23:39

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

        Впрочем, если учесть что едва ли не 9 из 10 разработчиков пишут в таком стиле, неудивительно что всё требует жутко много памяти и работает очень медленно… зато удобно для глаз автора кода (наверное).


        1. psFitz
          13.05.2019 09:59
          +1

          Ага, конечно, из-за того, что массив на 100 итемов выполняется 0,0001 ms вместо 0,0002ms все глючит и жрёт много памяти


          1. Skerrigan
            13.05.2019 11:21
            +1

            Ваша мысль понятна, тем не менее, сам в своем проекте сталкивался с ситуацией вида «оптимизация в ядре на пару миллисекунд выливается в сокращение работы на минуты».

            Т.е. я не говорю за «все ПО на планете», но вполне бывают ситуации, когда 100500 мелких оптимизаций в ядре дают прирост производительности суммарно в сотню-другую процентов.


            1. Druu
              13.05.2019 11:30

              сам в своем проекте сталкивался с ситуацией вида «оптимизация в ядре на пару миллисекунд выливается в сокращение работы на минуты».

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


              1. mayorovp
                13.05.2019 11:36

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


          1. Tangeman
            13.05.2019 13:11

            «на порядок» — это «в 10 раз». Хотя в данном конкретном случае (я чисто из вредности проверил) разница получилась аж в 20(!) раз (последний хром).

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

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

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


            1. Druu
              13.05.2019 13:19

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

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


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

              А с точки зрения хода мыслей разработчика массива тут не создается.
              Разработчик говорит: "из последовательности чисел 1..100 отфильтруй четные и выведи на экран" (и это, согласитесь, проще чем "установи значение переменной в 0, увеличивай на единицу, пока оно не станет больше 100, для каждого значения, если оно четное — выведи его на экран"), а то, что движок не умеет в оптимизацию и создает массив в принципе тут (не говоря уже о промежуточных) — проблема движка.


              1. Tangeman
                13.05.2019 15:09

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

                Если фрагмент настолько прост — может быть. А если он сложнее и их десятки тысяч? Что-то я сомневаюсь что тот кто привык писать всё «в лоб» хоть на секунду задумается о разнице.

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


                1. pacaya
                  13.05.2019 20:23

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

                  А оптимизмции по скорости или размеру нужно делать только тогда, когда профилировщик указывает на это место в коде, как на “бутылочное горлышко"


                1. Druu
                  14.05.2019 08:01
                  -2

                  Если фрагмент настолько прост — может быть. А если он сложнее и их десятки тысяч?

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


                  разработчик должен об этом думать

                  Не должен, это преждевременная оптимизация. Когда ваше приложение перестанет удовлетворять требованиям по скорости/памяти — тогда и надо думать.


              1. psFitz
                13.05.2019 15:13

                если у вас перебора массивов на 1 секунду — это проблема не движка и не циклов в принципе, это проблема архитектуры


  1. amarao
    12.05.2019 13:52

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


    1. PaulMaly
      14.05.2019 14:40

      Отличие лишь в том, что «много кода» в Svelte написаны для buildtime, а не для вашего runtime. Почувствуйте разницу:

      {
      ...
        "dependencies": {
          "react": "latest",
          "react-dom": "latest"
        },
      ...
      }
      

      vs

      {
      ...
        "devDependencies": {
          "svelte": "latest"
        },
      ...
      }
      


  1. Source
    12.05.2019 13:59

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

    После этой фразы я ожидал поворот статьи в сторону Haskell, или хотя бы PureScript :-)


  1. VM390
    12.05.2019 19:29
    -1

    На каком языке написано первое предложение статьи?
    Может быть автор должен уважать своих читателей? Дальше читать не захотелось…


  1. impwx
    12.05.2019 22:08

    Опять маслобойка? Автор упускает важную деталь — для Angular / React / Vue уже есть отличная поддержка со стороны IDE, а без нее экономия на символах ничего не стоит. Для Svelte, насколько я знаю, она очень глубоко в альфе (хотя если это не так, поправьте меня пожалуйста).


    1. JustDont
      13.05.2019 00:08

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

      У svelte, кстати, я идеологических проблем вижу буквально пару (в отличие от еще более странных поделий, за которые тут на хабре порой топят) — и на самом деле если б мне надо было писать проект в определенных рамках — я бы её как минимум внёс в шорт-лист. Но, конечно, не факт, что svelte стала бы окончательным выбором. Одна проблема всеобщая — это очень унылая поддержка со стороны IDE, что для проекта размером больше наколенного будет серьезным недостатком; вторая — системная, критичная для достаточно больших проектов, тот фактик, что код svelte полностью разматывается в стандартный js без фреймворка — даёт постоянный неустранимый оверхед в виде многократного повторения ошметков фреймворка повсеместно в каждом месте скомпилированного кода.

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

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


      1. PaulMaly
        14.05.2019 14:55

        Одна проблема всеобщая — это очень унылая поддержка со стороны IDE, что для проекта размером больше наколенного будет серьезным недостатком;

        Ответил тут.

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

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

        Если же вы ее достигли и еще не сделали code-splitting для динамической подгрузки компонентов по запросу, то у вас какие-то проблемы. А с code-splitting Svelte работает в разы лучше, чем любой монолит, из-за своих «идеологических проблем». Или как я это называю «верных архитектурных решений».

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

        Готов еще раз с вами обсудить минусы Svelte. Рассказывайте!

        p/s надеюсь вы не на полном серьезе апеллируете во всех своих комментариях к автору статьи? Ибо это перевод.


        1. JustDont
          14.05.2019 15:04

          Готов еще раз с вами обсудить минусы Svelte. Рассказывайте!

          Так вроде ж обсудили уже. Если с разматыванием кода проблем нет, то остаётся только вопрос плагинов к IDE (которые конечно «можно написать», но, как говорится, когда напишут, тогда и будем посмотреть). В остальном у меня нет никаких претензий общего плана, а о частностях можно будет говорить, когда до них дойдет. Более того, сам подход мне очень нравится, да и читал я «скомпилированный» код svelte — и там тоже всё довольно здорово.

          Пока у меня, к сожалению, новых проектов нет, где можно было бы взять svelte, но если будут (и будут плагины IDE) — другое дело. Ну или если в реакте, который меня пока устраивает, начнётся какая-нибудь ангуляр-подобная движуха по переделыванию фреймворка вне зависимости от того, нужно ли это кому-то вне фейсбука или нет. Если фейсбук в один прекрасный день объявит, что ООП в реакте больше не будет и пишите на хуках, потому что <список высосанных из пальцах аргументов почему ФП лучше ООП (нет)> — так я мгновенно переобуюсь куда-нибудь еще, например на svelte.

          p/s надеюсь вы не на полном серьезе апеллируете во всех своих комментариях к автору статьи? Ибо это перевод.

          Я человек простой — не вижу плашки «перевод» — считаю это оригиналом. Но да, теперь вот прочитал внимательно.


          1. AlexxNB Автор
            14.05.2019 16:52

            Я человек простой — не вижу плашки «перевод» — считаю это оригиналом. Но да, теперь вот прочитал внимательно

            Я засылал в Песочницу и там то ли не было выбора "Статья/Перевод/Новость", то ли я был крайне невнимателен (публиковал во время 13 часовой поездки сидячим поездом Псков-Петрозаводск). В любом случае, сейчас уже не исправить.


    1. develop7
      13.05.2019 12:52
      +1

      угу, дядя боб слепил из глины и соломы чучело и героически его разгромил


    1. PaulMaly
      14.05.2019 14:43

      Автор упускает важную деталь — для Angular / React / Vue уже есть отличная поддержка со стороны IDE, а без нее экономия на символах ничего не стоит. Для Svelte, насколько я знаю, она очень глубоко в альфе (хотя если это не так, поправьте меня пожалуйста).

      И что? Им и годков по больше. Плагины для IDE это то, что можно написать. А вот дизайн самого фреймворка, особенно который оброс легаси, просто так не переделаешь.


      1. impwx
        14.05.2019 15:18

        Вы недооцениваете сложность реализации нормальной поддержки со стороны IDE, особенно учитывая количество возможных сочетаний технологий (JS / TS / Coffeescript, CSS / LESS / SASS / PostCSS / ...). Небольшая экономия символов не оправдывает необходимости все это переделывать.


        1. PaulMaly
          14.05.2019 15:29

          Учитывая что Svelte компонент это почти валидный HTML файл (за исключением синтаксиса шаблонов), то изначальная его поддержка есть во всех IDE. Опять же, все из перечисленных фреймворков тоже начинали с плохой поддержки IDE. Есть тут минус у Svelte то, что это чисто community-driven проект без поддержки корпораций, но лично меня это больше привлекает, чем быть заложником предпочтений разработчиков из Facebook или Google. Потому что разработчики внутри корпораций решают как правило задачи несколько другого плана, которые далеко не всегда коррелируют для задач большенства других разработчиков.


          1. impwx
            14.05.2019 15:43

            Разница между изначальной и нормальной поддержкой в IDE, на мой взгляд, огромна. И какая разница, что было N лет назад, когда Angular / React / Vue только зарождались? Сейчас-то у них эта поддержка есть, поэтому фреймворк без нее можно позиционировать разве что как игрушку или эксперимент, но не как production-ready решение.


            1. PaulMaly
              14.05.2019 16:13
              +1

              То есть N лет назад Angular / React / Vue позиционировались как игрушки? Что-то не припомню такого. По-моему они всегда говорили о себе как по production-ready решениях. Да и как, если ты community-driven проект привлечь разработчиков к улучшению поддержки IDE, если не писать вот такие статьи? Ладно, фрейсбук и гугл могут за зарплату посадить людей писать плагины к IDE, но Svelte только через участие заинтересованных членов сообщества. И это настоящий open-source.


              1. impwx
                14.05.2019 17:22

                Требования к production-ready решениям в 2015 и 2019 годах значительно различаются.


                1. PaulMaly
                  14.05.2019 17:42

                  Какой-то слабый однако довод. То есть по-вашему, раз community-driven проект на начальных этапах по определению не может иметь tooling сопоставимый с corp-driven проектом, то он не должен существовать вообще? Интересная точка зрения конечно, но право ваще. Спорить с этим нет смысла.


                  1. impwx
                    14.05.2019 18:08
                    -1

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


  1. puyol_dev2
    12.05.2019 22:43

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


  1. trublast
    13.05.2019 10:20
    +1

    Вместо

    for (let i = 0; i <= 100; i += 1) {
        if (i % 2 === 0) {
            console.log(`${i} — чётное`);
        }
    }

    разве не так?
    for (let i = 0; i <= 100; i += 2) 
        console.log(`${i} — чётное`);
    


    пишите меньше кода…


  1. OrangePi
    13.05.2019 12:13

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


    1. mayorovp
      13.05.2019 16:31

      Простите, но где вы тут видите эмодзи?