Перейти к содержанию
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
exlends
Категории
  1. Главная
  2. Категории
  3. Фронтенд
  4. Lit vs Svelte: Битва за производительность и выбор

Lit vs Svelte: Битва за производительность и выбор

Запланировано Прикреплена Закрыта Перенесена Фронтенд
8 Сообщения 3 Постеры 85 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • AladdinA Не в сети
    AladdinA Не в сети
    Aladdin
    js
    написал отредактировано
    #1

    В мире, уставшем от “тяжести” React и сложности Angular, Lit и Svelte занимают нишу performance-ориентированных решений. Однако их философия диаметрально противоположна:

    • Lit — это библиотека-обертка, которая заставляет браузер работать на вас (Use the Platform).
    • Svelte — это компилятор, который переписывает ваш код в императивный JavaScript, исчезая в рантайме.

    1. Архитектура и Философия

    Lit: Ближе к металлу

    Lit разработан Google и построен поверх стандарта Web Components (Custom Elements, Shadow DOM, HTML Templates).

    • Суть: Lit добавляет минимальный слой (около 5kb) для реактивности и декларативного рендеринга.
    • Рендеринг: Использует tagged template literals (шаблонные строки JS). Браузер парсит HTML один раз, а Lit обновляет только динамические части (holes). Никакого VDOM.
    • Стейт: Основан на реактивных свойствах класса.

    Svelte Компилятор — это фреймворк

    Svelte не работает в браузере так, как React или Vue. Вы пишете компоненты в файлах .svelte, а на этапе сборки они превращаются в высокооптимизированный ванильный JS.

    • Суть: Перенос работы из браузера (рантайм) на этап сборки (компиляция).
    • Рендеринг: Генерирует точечный код для DOM-манипуляций (например, p.textContent = value). Виртуального DOM нет.
    • Стейт: В Svelte 5 (Runes) используется система сигналов ($state, $effect), что делает управление состоянием явным и предсказуемым.

    2. Сравнение кода (DX)

    Для примера возьмем простой счетчик.

    Lit (Class-based)

    Lit использует современный JS/TS. Это “просто JavaScript”, что удобно для типизации и отсутствия магии.

    import { LitElement, html, css } from 'lit';
    import { customElement, state } from 'lit/decorators.js';
    
    @customElement('my-counter')
    export class MyCounter extends LitElement {
      // Стили изолированы в Shadow DOM
      static styles = css`
        button { color: blue; }
      `;
    
      @state()
      protected _count = 0;
    
      private _increment() {
        this._count++;
      }
    
      render() {
        return html`
          <p>Count: ${this._count}</p>
          <button @click="${this._increment}">+1</button>
        `;
      }
    }
    

    Svelte 5 (Runes syntax)

    Svelte выглядит как HTML с примесью логики. Это снижает порог входа (“low boilerplate”).

    <script>
      let count = $state(0);
    
      function increment() {
        count += 1;
      }
    </script>
    
    <style>
      /* Стили автоматически scoped (но не Shadow DOM по умолчанию) */
      button { color: blue; }
    </style>
    
    <p>Count: {count}</p>
    <button onclick={increment}>+1</button>
    

    Вывод по DX:

    • Svelte лаконичнее. Меньше шума, быстрее писать UI.
    • Lit более структурирован и нативен. Если вы знаете стандартные классы ES6, вы знаете Lit.

    3. Веб-компоненты (Web Components / Custom Elements)

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

    Lit: Native Citizen

    Lit создан для веб-компонентов. Любой компонент Lit — это валидный стандартный HTMLElement.

    • Плюсы:
      • Идеальная совместимость (работает в React, Vue, Angular, чистом HTML без танцев с бубном).
      • Shadow DOM включен по умолчанию (полная изоляция стилей).
      • Отличная работа с атрибутами и свойствами (автоматическая конвертация типов, reflection).
      • Поддержка slots (нативная проекция контента).

    Svelte: Custom Element Mode

    Svelte может компилировать свои компоненты в веб-компоненты, добавив <svelte:options customElement="my-tag" />.

    • Нюансы и проблемы:
      • Сложность с пропсами: Веб-компоненты общаются через атрибуты (строки). Lit умеет автоматически парсить JSON из атрибутов в объекты. В Svelte Custom Elements передача сложных данных (массивов/объектов) требует прямой установки свойств DOM-узла через JS, что менее удобно при декларативном использовании в HTML.
      • Стили: В режиме Custom Element Svelte инлайнит стили внутрь JS-бандла компонента (строкой), чтобы внедрить их в Shadow Root. Это убивает кэширование CSS браузером.
      • Ограничения: Некоторые фичи Svelte (например, специфичные переходы или контекст) могут работать некорректно или требовать костылей при переходе через границу Shadow DOM.

    Вердикт: Если ваша цель — библиотека UI-компонентов для использования в разных фреймворках (Design System), Lit безальтернативно лучше. Svelte в режиме веб-компонентов — это “костыль” для интероперабельности, а не основной сценарий.


    4. Производительность (Performance)

    Здесь нет явного победителя, есть нюансы архитектуры.

    Загрузка (Startup & Bundle Size)

    • Svelte: Выигрывает на малых и средних проектах. Поскольку рантайма нет, вы грузите только код вашего компонента. “Hello World” на Svelte будет весить копейки (3-5kb).
    • Lit: Требует загрузки ядра Lit (~5kb gzipped). Для одного компонента это много. Но если компонентов 100, то ядро грузится один раз, а компоненты Lit очень легкие.
    • Inflection Point (Точка пересечения): Компоненты Svelte генерируют больше кода на каждый компонент, чем Lit. В очень больших приложениях общий бандл Svelte может стать больше, чем Lit-приложение, так как Lit переиспользует свое ядро, а Svelte повторяет логику обновлений в каждом файле.

    Рантайм (Runtime Speed)

    • Svelte: Хирургическая точность. При изменении переменной он обновляет конкретный текстовый узел. Самый быстрый механизм обновлений на рынке (сравнимый с SolidJS).
    • Lit: Очень быстр, но использует сравнение значений (dirty checking) на уровне свойств компонента и эффективное обновление HTML-шаблона. Чуть медленнее Svelte в синтетических тестах с тысячами элементов, но в реальности разница незаметна глазу (оба быстрее React в разы).

    5. Итоговая таблица сравнения

    Характеристика Lit Svelte (v5)
    Основа Библиотека (Runtime wrapper) Компилятор
    Язык JavaScript / TypeScript Svelte DSL (надстройка над HTML/JS)
    Web Components Native (Первоклассная поддержка) Compilation Target (Есть ограничения)
    Стилизация Shadow DOM (CSS in JS / CSS Files) Scoped CSS (через классы или Shadow DOM)
    Состояние Reactive Properties (Decorators) Runes ($state, $derived)
    Ecosystem Ориентирована на стандарты, Design Systems Ориентирована на Full-stack (SvelteKit)
    Сложность обучения Средняя (нужно понимать DOM, this, классы) Низкая (очень простой синтаксис)

    6. Что и для чего выбрать?

    Выбирайте Lit, если:

    1. Вы строите Design System. Вам нужно создать набор кнопок, инпутов и дропдаунов, которые будут использоваться командами на React, Angular и Vue одновременно. Это “киллер-фича” Lit.
    2. Микро-фронтенды. Вам нужна полная изоляция стилей и независимость от внешних фреймворков.
    3. Enterprise-стандарты. Вы хотите писать код, который будет работать через 5 лет, даже если Lit исчезнет (потому что в основе лежат стандарты браузера).

    Выбирайте Svelte, если:

    1. Вы делаете SPA / Full-stack приложение. В связке со SvelteKit это мощнейшее оружие для создания продуктов.
    2. Важна скорость разработки. Вам нужно быстро собрать сложный интерактивный дашборд с анимациями.
    3. Команда новичков. Svelte прощает незнание тонкостей JS (контекстов this, замыканий) больше, чем классовый подход Lit.
    4. Виджеты. Нужно встроить легкий интерактивный блок на тяжелый сайт (WordPress, Magento), и вы не хотите тащить туда React.

    Резюме эксперта

    Если задача — “Сделать приложение”, берите Svelte. Вы получите удовольствие от процесса и отличную производительность из коробки.

    Если задача — “Сделать библиотеку компонентов” или “Интегрироваться в чужой стек”, берите Lit. Svelte в роли веб-компонентов пока проигрывает в гибкости и передаче данных.
    ^1^2^4^6^8

    ⁂
    kirilljsxK 1 ответ Последний ответ
    👍
    2
    • hannadevH Не в сети
      hannadevH Не в сети
      hannadev
      написал отредактировано
      #2

      А я говорила что lit классный для веб-компонентов, так и останется. СПС за разбор 👍

      1 ответ Последний ответ
      0
      • AladdinA Aladdin

        В мире, уставшем от “тяжести” React и сложности Angular, Lit и Svelte занимают нишу performance-ориентированных решений. Однако их философия диаметрально противоположна:

        • Lit — это библиотека-обертка, которая заставляет браузер работать на вас (Use the Platform).
        • Svelte — это компилятор, который переписывает ваш код в императивный JavaScript, исчезая в рантайме.

        1. Архитектура и Философия

        Lit: Ближе к металлу

        Lit разработан Google и построен поверх стандарта Web Components (Custom Elements, Shadow DOM, HTML Templates).

        • Суть: Lit добавляет минимальный слой (около 5kb) для реактивности и декларативного рендеринга.
        • Рендеринг: Использует tagged template literals (шаблонные строки JS). Браузер парсит HTML один раз, а Lit обновляет только динамические части (holes). Никакого VDOM.
        • Стейт: Основан на реактивных свойствах класса.

        Svelte Компилятор — это фреймворк

        Svelte не работает в браузере так, как React или Vue. Вы пишете компоненты в файлах .svelte, а на этапе сборки они превращаются в высокооптимизированный ванильный JS.

        • Суть: Перенос работы из браузера (рантайм) на этап сборки (компиляция).
        • Рендеринг: Генерирует точечный код для DOM-манипуляций (например, p.textContent = value). Виртуального DOM нет.
        • Стейт: В Svelte 5 (Runes) используется система сигналов ($state, $effect), что делает управление состоянием явным и предсказуемым.

        2. Сравнение кода (DX)

        Для примера возьмем простой счетчик.

        Lit (Class-based)

        Lit использует современный JS/TS. Это “просто JavaScript”, что удобно для типизации и отсутствия магии.

        import { LitElement, html, css } from 'lit';
        import { customElement, state } from 'lit/decorators.js';
        
        @customElement('my-counter')
        export class MyCounter extends LitElement {
          // Стили изолированы в Shadow DOM
          static styles = css`
            button { color: blue; }
          `;
        
          @state()
          protected _count = 0;
        
          private _increment() {
            this._count++;
          }
        
          render() {
            return html`
              <p>Count: ${this._count}</p>
              <button @click="${this._increment}">+1</button>
            `;
          }
        }
        

        Svelte 5 (Runes syntax)

        Svelte выглядит как HTML с примесью логики. Это снижает порог входа (“low boilerplate”).

        <script>
          let count = $state(0);
        
          function increment() {
            count += 1;
          }
        </script>
        
        <style>
          /* Стили автоматически scoped (но не Shadow DOM по умолчанию) */
          button { color: blue; }
        </style>
        
        <p>Count: {count}</p>
        <button onclick={increment}>+1</button>
        

        Вывод по DX:

        • Svelte лаконичнее. Меньше шума, быстрее писать UI.
        • Lit более структурирован и нативен. Если вы знаете стандартные классы ES6, вы знаете Lit.

        3. Веб-компоненты (Web Components / Custom Elements)

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

        Lit: Native Citizen

        Lit создан для веб-компонентов. Любой компонент Lit — это валидный стандартный HTMLElement.

        • Плюсы:
          • Идеальная совместимость (работает в React, Vue, Angular, чистом HTML без танцев с бубном).
          • Shadow DOM включен по умолчанию (полная изоляция стилей).
          • Отличная работа с атрибутами и свойствами (автоматическая конвертация типов, reflection).
          • Поддержка slots (нативная проекция контента).

        Svelte: Custom Element Mode

        Svelte может компилировать свои компоненты в веб-компоненты, добавив <svelte:options customElement="my-tag" />.

        • Нюансы и проблемы:
          • Сложность с пропсами: Веб-компоненты общаются через атрибуты (строки). Lit умеет автоматически парсить JSON из атрибутов в объекты. В Svelte Custom Elements передача сложных данных (массивов/объектов) требует прямой установки свойств DOM-узла через JS, что менее удобно при декларативном использовании в HTML.
          • Стили: В режиме Custom Element Svelte инлайнит стили внутрь JS-бандла компонента (строкой), чтобы внедрить их в Shadow Root. Это убивает кэширование CSS браузером.
          • Ограничения: Некоторые фичи Svelte (например, специфичные переходы или контекст) могут работать некорректно или требовать костылей при переходе через границу Shadow DOM.

        Вердикт: Если ваша цель — библиотека UI-компонентов для использования в разных фреймворках (Design System), Lit безальтернативно лучше. Svelte в режиме веб-компонентов — это “костыль” для интероперабельности, а не основной сценарий.


        4. Производительность (Performance)

        Здесь нет явного победителя, есть нюансы архитектуры.

        Загрузка (Startup & Bundle Size)

        • Svelte: Выигрывает на малых и средних проектах. Поскольку рантайма нет, вы грузите только код вашего компонента. “Hello World” на Svelte будет весить копейки (3-5kb).
        • Lit: Требует загрузки ядра Lit (~5kb gzipped). Для одного компонента это много. Но если компонентов 100, то ядро грузится один раз, а компоненты Lit очень легкие.
        • Inflection Point (Точка пересечения): Компоненты Svelte генерируют больше кода на каждый компонент, чем Lit. В очень больших приложениях общий бандл Svelte может стать больше, чем Lit-приложение, так как Lit переиспользует свое ядро, а Svelte повторяет логику обновлений в каждом файле.

        Рантайм (Runtime Speed)

        • Svelte: Хирургическая точность. При изменении переменной он обновляет конкретный текстовый узел. Самый быстрый механизм обновлений на рынке (сравнимый с SolidJS).
        • Lit: Очень быстр, но использует сравнение значений (dirty checking) на уровне свойств компонента и эффективное обновление HTML-шаблона. Чуть медленнее Svelte в синтетических тестах с тысячами элементов, но в реальности разница незаметна глазу (оба быстрее React в разы).

        5. Итоговая таблица сравнения

        Характеристика Lit Svelte (v5)
        Основа Библиотека (Runtime wrapper) Компилятор
        Язык JavaScript / TypeScript Svelte DSL (надстройка над HTML/JS)
        Web Components Native (Первоклассная поддержка) Compilation Target (Есть ограничения)
        Стилизация Shadow DOM (CSS in JS / CSS Files) Scoped CSS (через классы или Shadow DOM)
        Состояние Reactive Properties (Decorators) Runes ($state, $derived)
        Ecosystem Ориентирована на стандарты, Design Systems Ориентирована на Full-stack (SvelteKit)
        Сложность обучения Средняя (нужно понимать DOM, this, классы) Низкая (очень простой синтаксис)

        6. Что и для чего выбрать?

        Выбирайте Lit, если:

        1. Вы строите Design System. Вам нужно создать набор кнопок, инпутов и дропдаунов, которые будут использоваться командами на React, Angular и Vue одновременно. Это “киллер-фича” Lit.
        2. Микро-фронтенды. Вам нужна полная изоляция стилей и независимость от внешних фреймворков.
        3. Enterprise-стандарты. Вы хотите писать код, который будет работать через 5 лет, даже если Lit исчезнет (потому что в основе лежат стандарты браузера).

        Выбирайте Svelte, если:

        1. Вы делаете SPA / Full-stack приложение. В связке со SvelteKit это мощнейшее оружие для создания продуктов.
        2. Важна скорость разработки. Вам нужно быстро собрать сложный интерактивный дашборд с анимациями.
        3. Команда новичков. Svelte прощает незнание тонкостей JS (контекстов this, замыканий) больше, чем классовый подход Lit.
        4. Виджеты. Нужно встроить легкий интерактивный блок на тяжелый сайт (WordPress, Magento), и вы не хотите тащить туда React.

        Резюме эксперта

        Если задача — “Сделать приложение”, берите Svelte. Вы получите удовольствие от процесса и отличную производительность из коробки.

        Если задача — “Сделать библиотеку компонентов” или “Интегрироваться в чужой стек”, берите Lit. Svelte в роли веб-компонентов пока проигрывает в гибкости и передаче данных.
        ^1^2^4^6^8

        ⁂
        kirilljsxK Не в сети
        kirilljsxK Не в сети
        kirilljsx
        js
        написал отредактировано
        #3

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

        AladdinA 1 ответ Последний ответ
        🤚
        1
        • kirilljsxK kirilljsx

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

          AladdinA Не в сети
          AladdinA Не в сети
          Aladdin
          js
          написал отредактировано Aladdin
          #4

          @kirilljsx

          Раньше в реакте вечно приходилось this.bind делать, половина кода в конструкторе одни привязки были! Сейчас на хуках вообще об этом не думаешь 👌

          Пример

          /**
          Объяснение для чего это нужно:
          
          JavaScript теряет контекст this когда метод передается как коллбэк (в onClick, onChange и т.д.). 
          В классовых компонентах this должен указывать на экземпляр класса, чтобы получить доступ к:
          
          this.state - состоянию компонента
          this.props - пропсам
          this.setState() - методу обновления состояния
          и другим методам компонента
          
          Без привязки this будет undefined (в strict mode) или указывать на глобальный объект/элемент DOM. 
          Привязка сохраняет контекст компонента для работы с его данными и методами.
          
          **/
          
          class OldSchoolComponent extends React.Component {
            constructor(props) {
              super(props);
              this.state = {
                count: 0
              };
              
              // Привязка метода к this - обязательно!
              this.handleClick = this.handleClick.bind(this);
              this.handleMouseOver = this.handleMouseOver.bind(this);
            }
            
            // Обычный метод - теряет контекст this при передаче как коллбэк
            handleClick() {
              // Без bind здесь this был бы undefined
              this.setState({ count: this.state.count + 1 });
            }
            
            // Еще один метод
            handleMouseOver() {
              console.log('Mouse over! Count is:', this.state.count);
            }
            
            // Альтернатива - стрелочная функция как свойство класса
            // (работает в современных проектах)
            handleReset = () => {
              this.setState({ count: 0 });
            }
            
            render() {
              return (
                <div>
                  <h2>Счетчик: {this.state.count}</h2>
                  <button onClick={this.handleClick}>Увеличить</button>
                  <button onClick={this.handleReset}>Сбросить</button>
                  <div 
                    onMouseOver={this.handleMouseOver}
                    style={{padding: '20px', background: '#eee'}}
                  >
                    Наведи мышь
                  </div>
                  
                  {/* Или bind прямо в JSX (не рекомендуется, создает функцию каждый рендер) */}
                  <button onClick={this.handleClick.bind(this)}>
                    Еще вариант
                  </button>
                </div>
              );
            }
          }
          
          kirilljsxK 1 ответ Последний ответ
          0
          • AladdinA Aladdin

            @kirilljsx

            Раньше в реакте вечно приходилось this.bind делать, половина кода в конструкторе одни привязки были! Сейчас на хуках вообще об этом не думаешь 👌

            Пример

            /**
            Объяснение для чего это нужно:
            
            JavaScript теряет контекст this когда метод передается как коллбэк (в onClick, onChange и т.д.). 
            В классовых компонентах this должен указывать на экземпляр класса, чтобы получить доступ к:
            
            this.state - состоянию компонента
            this.props - пропсам
            this.setState() - методу обновления состояния
            и другим методам компонента
            
            Без привязки this будет undefined (в strict mode) или указывать на глобальный объект/элемент DOM. 
            Привязка сохраняет контекст компонента для работы с его данными и методами.
            
            **/
            
            class OldSchoolComponent extends React.Component {
              constructor(props) {
                super(props);
                this.state = {
                  count: 0
                };
                
                // Привязка метода к this - обязательно!
                this.handleClick = this.handleClick.bind(this);
                this.handleMouseOver = this.handleMouseOver.bind(this);
              }
              
              // Обычный метод - теряет контекст this при передаче как коллбэк
              handleClick() {
                // Без bind здесь this был бы undefined
                this.setState({ count: this.state.count + 1 });
              }
              
              // Еще один метод
              handleMouseOver() {
                console.log('Mouse over! Count is:', this.state.count);
              }
              
              // Альтернатива - стрелочная функция как свойство класса
              // (работает в современных проектах)
              handleReset = () => {
                this.setState({ count: 0 });
              }
              
              render() {
                return (
                  <div>
                    <h2>Счетчик: {this.state.count}</h2>
                    <button onClick={this.handleClick}>Увеличить</button>
                    <button onClick={this.handleReset}>Сбросить</button>
                    <div 
                      onMouseOver={this.handleMouseOver}
                      style={{padding: '20px', background: '#eee'}}
                    >
                      Наведи мышь
                    </div>
                    
                    {/* Или bind прямо в JSX (не рекомендуется, создает функцию каждый рендер) */}
                    <button onClick={this.handleClick.bind(this)}>
                      Еще вариант
                    </button>
                  </div>
                );
              }
            }
            
            kirilljsxK Не в сети
            kirilljsxK Не в сети
            kirilljsx
            js
            написал отредактировано
            #5

            @Aladdin ого ты труп 🧟‍♂️ отрыл
            Единственное что мне нравилось в классовом подходе это то что функции были в одном месте

            AladdinA 1 ответ Последний ответ
            0
            • kirilljsxK kirilljsx

              @Aladdin ого ты труп 🧟‍♂️ отрыл
              Единственное что мне нравилось в классовом подходе это то что функции были в одном месте

              AladdinA Не в сети
              AladdinA Не в сети
              Aladdin
              js
              написал отредактировано
              #6

              @kirilljsx что ты имеешь ввиду под “функции в одном месте”?

              kirilljsxK 1 ответ Последний ответ
              0
              • AladdinA Aladdin

                @kirilljsx что ты имеешь ввиду под “функции в одном месте”?

                kirilljsxK Не в сети
                kirilljsxK Не в сети
                kirilljsx
                js
                написал отредактировано
                #7

                @Aladdin То что все функции внутри class находятся, а в функциональщине у меня иногда там полный ковардак

                AladdinA 1 ответ Последний ответ
                0
                • kirilljsxK kirilljsx

                  @Aladdin То что все функции внутри class находятся, а в функциональщине у меня иногда там полный ковардак

                  AladdinA Не в сети
                  AladdinA Не в сети
                  Aladdin
                  js
                  написал отредактировано
                  #8

                  @kirilljsx ты можешь также и функции сгруппировать в каком-то объекте, или модуле и получить такой же эффект

                  1 ответ Последний ответ
                  0

                  Категории

                  • Главная
                  • Новости
                  • Фронтенд
                  • Бекенд
                  • Языки программирования

                  Контакты

                  • Сотрудничество
                  • info@exlends.com
                  • Наш чат
                  • Наш ТГ канал

                  © 2024 - 2025 ExLends, Inc. Все права защищены.

                  Политика конфиденциальности
                  • Войти

                  • Нет учётной записи? Зарегистрироваться

                  • Войдите или зарегистрируйтесь для поиска.
                  • Первое сообщение
                    Последнее сообщение
                  0
                  • Лента
                  • Категории
                  • Последние
                  • Метки
                  • Популярные
                  • Пользователи
                  • Группы