LINUX.ORG.RU

Cruzo – минималистичный UI фреймворк с роутером, компонентами и разными плюшками (~14 kb gzip)

 , , , ,


2

3

Хотел рассказать вам о своих наработках, делаю этот фреймворк с 2020г, с появлением LLM нагенерил доков и UI-тестов, убрал с себя рутину, наконец-то зарелизил. Сам фреймворк без зависимостей.

При этом есть: шаблонизатор с реактивностью, компоненты, роутер, HTTP-обертка, шаблоны {{ }} через байткод (без eval, CSP-friendly).


Всё, что нужно для SPA:

import {
  Template,
  AbstractComponent,
  RxBucket,
  routerService,
  RouteUrlBucket,
  HttpClient,
  componentsRegistryService,
} from "cruzo";

~44 KB min / ~14 KB gzip в бандле приложения (production, tree-shake).

UI-kit (input, select, modal…) — отдельные импорты, в цифру не входит.

Сопоставимая комплектация

«Маленькое SPA: UI-runtime + роутер + HTTP + реактивный стейт», без тяжёлого UI-kit:

СтекЧто входитgzip (порядок)
cruzotemplate VM, components, rx, bucket, router, http~14 KB
Reactreact + react-dom + react-router-dom~55–60 KB
Angularcore + router + common/http (+ zone в классической сборке)~90–130 KB только framework-chunk

React легче только пока у тебя одна кнопка без роутера. Angular — для простой админки часто overkill и по KB, и по голове.


Счётчик

import { AbstractComponent, componentsRegistryService } from "cruzo";

class Counter extends AbstractComponent {
  static selector = "counter";
  count$ = this.newRx(0);

  getHTML() {
    return `
      <button onclick="{{ root.inc() }}">
        ping: {{ root.count$::rx }}
      </button>
    `;
  }

  inc() {
    this.count$.update(this.count$.actual + 1);
  }
}

componentsRegistryService.define(Counter);
componentsRegistryService.initApp();
<counter></counter>

Форма на RxBucket

import { AbstractComponent, RxBucket } from "cruzo";
import { InputConfig } from "cruzo/ui-components/input";
import { SelectConfig } from "cruzo/ui-components/select";

class SearchPanel extends AbstractComponent {
  static selector = "search-panel";

  innerBucket = new RxBucket({
    search: { config: InputConfig({ placeholder: "найти..." }) },
    sort: {
      config: SelectConfig({
        placeholder: "сортировка",
        getItems: async () => [
          { label: "Новые", value: "new" },
          { label: "Старые", value: "old" },
        ],
      }),
    },
  });

  query$ = this.newRxValueFromBucket(this.innerBucket, "search");
  sort$ = this.newRxValueFromBucket(this.innerBucket, "sort");

  getHTML() {
    return `
      <input-component component-id="search" bucket-id="${this.innerBucket.id}"></input-component>
      <select-component component-id="sort" bucket-id="${this.innerBucket.id}"></select-component>
      <pre>query: {{ root.query$::rx }}</pre>
      <pre>sort: {{ root.sort$::rx }}</pre>
    `;
  }
}

Роутер + ленивая подгрузка

import { RouteUrlBucket, delay, routerService } from "cruzo";

export const routes = new RouteUrlBucket({
  home: {
    url: "/",
    componentSelectorUnbox: () => "home-page",
    routeSelectorUnbox: () => "#app",
  },
  lazy: {
    url: "/lazy-demo",
    componentSelectorUnbox: () => "lazy-page",
    routeSelectorUnbox: () => "#app",
    loadResources: async () => {
      await delay(2000); // демо-задержка
      await import("./lazy-page.js");
    },
  },
});

routerService.update();

HTTP из того же пакета

import { HttpClient } from "cruzo";

const api = new HttpClient("https://api.example.com", {
  params: async (_m, _url, opts) => {
    opts.headers ??= {};
    opts.headers.Authorization = "Bearer " + token();
  },
});

const me = await api.get("/me");

Всё это — cruzo, те самые ~14 KB gzip.


Почему я решил сделать VM, а не eval, ведь бандл был бы намного меньше!

Выражения в {{ }} компилируются в байткод и исполняются маленькой VM. Подмножество JS — в {{ }} не весь язык, а фиксированный набор. Парсер отсекает лишнее до исполнения, защита от выполнения произвольного JS.

Ну еще, если есть тег Content-Security-Policy: default-src ‘self’; script-src ‘self’, то eval(…) просто не выполнится.


Ссылки


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

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

anonymous
()
Ответ на: комментарий от static_lab

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

Обещаю, не буду докапываться до мелочей.

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

anonymous
()
Ответ на: комментарий от anonymous

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

static_lab ★★★★★
()
Ответ на: комментарий от static_lab

Я вбил в гугле запрос и открыл например это https://htmlburger.com/blog/single-page-app-examples/

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

Помнишь историю, как маск выгонял людей из твиттера после покупки? Так ещё же хуже стало!

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

anonymous
()
Ответ на: комментарий от anonymous

хотя их пилят топы с почти безлимитным бюджетом и большим количеством умных людей

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

static_lab ★★★★★
()
Ответ на: комментарий от static_lab

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

Буду ждать, может кто-то тут в комментариях потом скинет пример хорошего spa.

anonymous
()
Ответ на: комментарий от anonymous

Можете глянуть https://cruzo.org

Исходный код здесь – https://github.com/MaratBektemirov/cruzo-starter

В этой репе уже не сам фреймворк, а что ни на есть SPA, который можно построить на cruzo. Плюс есть deploy.yml, для настройки деплоя на github pages

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

Я кстати открыл для интереса вк видео, там 23 мб JS-скриптов, используется React со state менеджером)

117 / 199 requests

6,000 kB / 8,846 kB transferred

23,697 kB / 28,825 kB resources

Finish: 1 min

DOMContentLoaded: 286 ms

Load: 1.53 s

В самом начале React очень сильно продвигал facebook, ну и люди захавали это, хотя там реактивным программированием и не пахло… А Angular Google не планировал для людских сайтов, больше внутренний инструментов для дашбордов и разного рода админок, но вон оно как получилось… Делают аппки на angular в итоге, но вроде с него все уходят на React.

kodoi
() автор топика
Ответ на: комментарий от kodoi

Можете глянуть https://cruzo.org

Открыл, а что там смотреть? Статичный хтмл. Это spa?

Вопрос без подвоха, я не понимаю.

Комментарий про ВК с моей стороны был не про spa, а в целом про веб.

anonymous
()
Ответ на: комментарий от kodoi

React очень сильно продвигал facebook

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

anonymous
()
Ответ на: комментарий от anonymous

Да, первые spa, в текущем виде, появились еще во времена history api. Я помню как angularjs застал, для меня это вау-эффект был. SPA отличается от не SPA, тем что меньше запросов уходит на сервер, из-за того что переходы происходят без полной перезагрузки страницы

kodoi
() автор топика
Ответ на: комментарий от kodoi

Будет пример нормального spa не хелловорлда или видимо нет?:)

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

Печально.

anonymous
()
Ответ на: комментарий от kodoi

У тебя в стартовом посте выхлоп нейросети в чистом виде, остановись.

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

anonymous
()
Ответ на: комментарий от anonymous

пример нормального spa

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

Надоели чувачки типа опа.

anonymous
()
Ответ на: комментарий от kodoi

как сделать блог

cruzo+s3

Зачем там s3 и твой фреймворк? Взял текст, положил в маркдаун, сделал хтмл (чем угодно типа хьюго ), положил к себе на сервер или на гитхаб пейджс.

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

anonymous
()
Ответ на: комментарий от kodoi

React легче только пока у тебя одна кнопка без роутера. Angular — для простой админки часто overkill и по KB, и по голове.

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

Надоели вы, можно же хотя бы самостоятельно оформить.

anonymous
()
Ответ на: комментарий от anonymous

Генерация страниц долгая на вордпресс, а на свой сервер такие вещи закидывать я считаю расточительство

kodoi
() автор топика
Ответ на: комментарий от anonymous

пример нормального spa

Обычная оконная программа взаимодействующая с сетью/интернетом.

Но так не интересно. Надо все окошки-контролы перерисовать на Document(!) Object Model (ага, на тех самых div’ах) с использованием скриптового языка с неуправляемой автоматической памятью.

anonymous
()
Ответ на: комментарий от anonymous

Я ушел с WebStorm еще давно из-за лагов в интерфейсе (память тоже кстати отжирал), а Visual studio code классно все отрисовывает, но тоже жрет конечно не мало. Браузер в текущем виде и текущем железе, вполне можно использовать для создания сложных приложений с точки зрения интерфейса

kodoi
() автор топика
Ответ на: комментарий от anonymous

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

Зачем? Никакого профита это не даст ни серверу, ни клиенту, ни разработчику.

Лор вон рендерится на сервере, и я уверен что при росте хитов он нормально масштабируется.

Обычная оконная программа взаимодействующая с сетью/интернетом.

Так смысл нормального spa в том чтоб зайти через браузер и что-то сделать без установки софта, например открыть/исправить (ещё и коллективно) табличку в гугл докс.

anonymous
()
Ответ на: комментарий от anonymous

Если лор перейдет на спа, нагрузка в теории может снизится. Просто тут как приготовишь SPA, можно все усложнить каким-нибудь 30 мегабайтным js’ом. Ну и сам бэк еще переписывать надо будет, иногда в переходе на spa нет никакого смысла. Другое дело когда десятки миллионов, там каждый килобайт на счету. Хотя как мы видим на примере вк видео, что не на счету…

kodoi
() автор топика
Ответ на: комментарий от anonymous

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

anonymous
()

Насколько совместим с react? Или все свое. Проблема скорее что для react можно взять уже готовые библиотеки с поддержкой react, и больше для ничего кроме react их нет нормально работающих. Так например для vue пришлось как-то делать «react miniapp» в iframe просто чтобы подключить там библиотеку для react.

anonymous_sama ★★★★★
()
Последнее исправление: anonymous_sama (всего исправлений: 1)
Ответ на: комментарий от kodoi

Если лор перейдет на спа, нагрузка в теории может снизится. Просто тут как приготовишь SPA

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

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

anonymous
()
Ответ на: комментарий от anonymous

Так там все 15 из 15 пунктов - тормозное и неюзабельное говно

Все 15 у меня проверить не удалось, но гугл-карты, ютуб и пинтерест я открыл — всё на iPhone SE первого поколения с чипом A9. У меня это самый медленный девайс из используемых.

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

kaldeon ★★
()
Последнее исправление: kaldeon (всего исправлений: 1)
Ответ на: комментарий от kaldeon

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

Веб ютуб с годами стал тормознее в разы (хорошо что есть smarttube на ТВ), gmail тоже, google cloud console вообще изначально была говном.

Они пока конечно решают свои задачи, но вымрут в итоге.

anonymous
()
Ответ на: комментарий от kodoi

Да, первые spa, в текущем виде, появились еще во времена history api.

«В текущем виде» - это с нормальной адресацией? А так-то они были задолго до появления History API. И что сейчас с History API не так? (Мне показалось, что вы считаете этот API какой-то древностью.)

estic
()
Ответ на: комментарий от anonymous

Но так не интересно.

С интерфейсом в браузере как раз возможно то, что вы хотите видеть, как я понимаю. А у «обычных оконных программ» обычно монструозные API. Я, например, на данном этапе отказался от подобных приложений. SAAS - наше все :)

estic
()
Ответ на: комментарий от estic

Да, вы правы. Приложение можно было полноценное сделать с появлением AJAX, просто состояние синхронизировать с ссылкой было проблемно

kodoi
() автор топика
Ответ на: комментарий от anonymous

А оно так и есть. https://cruzo.org/ без JavaScript не работает. С JavaScript сразу после открытия можно наблюдать только колонку слева и надпись вверху и надо подождать секунду или две чтобы непосредственно само содержимое как–то там немного погодя асинхронно, для быстроты, прогрузилось и отрисовалось. Если загрузить страничку на не столь давнем умнофоне, задержка неприятно большая. Загружается (в сжатом виде) 366.18 килобайт скриптов и до кучи шрифты с Google. Всё для быстроты и экономии.

PS Ещё бы интересно узнать сколько куашется оперативки.

wenxuan
()
Последнее исправление: wenxuan (всего исправлений: 1)
Ответ на: комментарий от anonymous

Текст со страницы сохранённый в UTF-8 занимает 12,4 КБ. Если сохранить в RTF (можно оформить текст), то 20 КБ. Чудо вэбных технологий в виде 366.18 КБ только лишь скриптов для того чтобы показать 20 КБ текста и одну картинку которая является ссылкой и почему–то ведёт на https://cruzo.org/#/ (при нажатии ничего не происходит). Там ещё есть интерактивные примеры, но они совсем ни о чём так что не считается.

wenxuan
()
Ответ на: комментарий от wenxuan

Чудо вэбных технологий в виде 366.18 КБ только лишь скриптов для того чтобы показать 20 КБ текста и одну картинку

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

С другой стороны современные браузеры и так вполне успешно кэшируют JS/CSS-код. Так что AJAX-приложения в основном ведут борьбу за отказ от повторных загрузки и разбора раздела head, различных меню, сайдбаров и т.п.

estic
()
Последнее исправление: estic (всего исправлений: 2)
Ответ на: комментарий от estic

Это связано с тем что роутер cruzo работает в hash mode. Дело в том что по дефолту github pages криво работает (если прям по ссылке открывать), приходится hash mode включать. Но это также работа через history api. Если ваш сервер будет норм обрабатывать обычный режим, можно не включать hash mode

kodoi
() автор топика
Ответ на: комментарий от estic

Какая может быть нормальня дискуссия с тем кто пишет загрузи почти полмегабайта всего чтобы просмотреть 20 кБ текста ведь так быстрее. Отдать просто HTML без wasm.js на 234 кБ без никому ненужных загружаемых шрифтов не разрешают тараканы в голове?

wenxuan
()
Ответ на: комментарий от wenxuan

Этот wasm нужен для хайлайта кода, а шрифты это часть дизайна. Люди вообще склонны быть радикальными и блуждать из крайность в крайность…

Первая крайность – это сильно снижать размер, при этом в ущерб пользователю, я понимаю что подсветка в примерах должна быть реализована, это упрощает восприятие и 300кб оправдывают цель. И шрифты тоже, это часть дизайна. Вторая крайность – это 24 мбайта JS в вк видео и им подобных, там люди вообще перестали думать про размер, а увлеклись реактом ради реакта.

kodoi
() автор топика
Ответ на: комментарий от wenxuan

без никому ненужных загружаемых шрифтов

ОМГ, вам еще и загрузка шрифтов не нравится!

Или заметили загрузку шрифтов, которые не используются?

не разрешают тараканы в голове?

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

estic
()
Последнее исправление: estic (всего исправлений: 1)
Ответ на: комментарий от wenxuan

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

estic
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария