Как стать автором
Обновить

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

Я уже достаточно давно пилю систему управления контентом под названием ZOIA на Marko/Mongo/Bulma, сборка через Webpack. «Изоморфный» серверный рендеринг из коробки, модульность, многоязычность, ну и много других интересных плюшек. Вот ссылка на Github. Если интересно посмотреть, как Зоя работает в «живых» проектах, то, например, вот, ну или присылайте сообщение в личку, отправлю ссылку на демо.
Должен сказать, что Marko работает действительно очень быстро. Сообщество тоже достаточно отзывчивое и дружелюбное.
Если Хабру интересно, могу написать о Зое отдельную статью.

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

Живые примеры это же отлично
именно на этой библиотеке построен фронтенд ebay.com…

Так себе рекомендация, если честно. :)

Когда я вынужденно пользуюсь eBay я всё время подмечаю, что это, наверное "отличный" пример тех самых модных "micro-frontends". Кликаешь на пункт меню — грузится 1 frontend, кликаешь на 2-й грузится 2-й, на 3-й — грузится 3-й. Все при этом выглядят по-разному. Как будто на другой сайт попадаешь. И все визуально как-будто родом из 95-го. Про удобство можно даже не заикаться.


Смотря на код из статьи, невозможно не подметить, что каменный век застрял и в коде. Столько ручной работы. Столько нарушений здравого смысла (скажем загрузка users прописанная прямо в router-е). Стили именования переменных (underscore case и всякие ___implicit: true). Ручные вызовы history. Однобуквенные методы. Вшитые строки с тегами. out.w('<p>not found</p>'). Мои глазаааа…


Мне кажется статья про "фронтенд от ebay.com" должна называться примерно так: "Вредные советы или как мы докатились до такой жизни | eBay".

Дизайн (хуждожественный) это не совсем к коду замечание. Кстати, нам, которые не были с ebay.com с самого основания возможно не понять почему они не стремятся менять дизайн. Возможно это что-то из разряда того чтобы оставаться тем самым старым добрым ebay.com


Marko.js это библиотека в которой нет роутера. Поэтому замечание по загрузке users прописанная прямо в route — это не к ним а ко мне. Код out.w('not found') — это же авто генерируемый код — у webpacka он не намного лучше?

почему они не стремятся менять дизайн

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


это же авто генерируемый код — у webpacka он не намного лучше?

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


Честно говоря по статье в целом непонятно, что такое Macro, как он работает и нужен ли он в 2020г. Ниша у него, судя по всему, примерно та же что у какой-нибудь связки вроде backbone + handlebars, но тут нужно вникать чтобы сказать точнее.

Добавил в текст фразу про автогенерацию кода. Ниша этогй библиотеки примерна такая же как у react. Однако библиотека не имеет агрессивного PR результате чего о ней практически ничего не известно. Также нет наработок по ней — то чем сейчас силен React, когда на каждый случай есть рекомендации как это делать правильно.

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


Для тех кому интересна краткая выжимка:


  • macro использует virtualDom
  • под капотом, судя по всему, observable, сделанные как во Vue2, через get\set-ры
  • использует кастомный формат шаблонов, с довольно богатым сахаром (но кажется сильно уступает Vue, хотя есть и свои фишки вроде возможности задать имя тега и какие-то параметры для субкомпонент (не путать с аттрибутами, они тоже есть))
  • очень легковесный (обещают 10 KiB gzip)
  • использует всякие хаки с $ символов как и Svelte (но не уверен что для тех же целей)
  • поддержка IE9
  • имеет 3 синтаксиса шаблонов: один похожий на xml, второй похож на pug\jade, 3-й JSX, но как и в случае с Vue — неудобный JSX
  • умеет в SSR (кажется это основная фишка фреймворка), причём умеет в stream-ы, поддерживает асинхронность
  • так же поддерживает в шаблонах произвольный JS
  • есть ahead of time compilation шаблонов
  • умеет импортировать только используемые части macro
  • местный аналог PropTypes умеет срабатывать в compile-time
  • использует свой компилятор
  • всегда работает синхронно (React от этого много лет пытаются уйти)
  • есть Single-File-Components
  • местный аналог state работает shallowly, предполагается что всё изменяется иммутабельно, в общем pure by default философия
  • похожая на React модель event-ов — события вешаются на <body/>
  • система обмена событиями (.emit('string', value)) как во Vue

Этакая смесь React & Vue. Самая сильная отличительная черта SSR.

apapacy а можно вот написать про все, что описал faiwer ?


А то в текущей статьей больше вопросов, чем ответов, т.к. куча тезисов просто остались нераскрытыми:


  • Marko.js неистово быстр
  • Marko.js можно считать SSR-first библиотекой
  • Всем известно, что node.js не так хорош, если его нагружать сложными расчетами
  • Код компонентов интуитивно понятен

Ко всем тезисам базовый вопрос "почему?".


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


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

По текущей статье я узнал о существовании universal-router и о том, что, возможно marko.js быстро рендерит на сервере. Хотя не он один использует потоковый рендер.

Кто еще использует рендер потоком и без создания dom с последующей сериалищацией в строку или в поток?

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


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




Я не утверждал, что кто-то еще использует потоковый рендер без создания DOM (что бы это ни значило). Я утверждал, что потоковый рендер — не изобретение marko.


И то, что заявления вида "Marko.js неистово быстр" ничем не подкреплены.

В отличие от marko.js все популярные фреймворк создают на стороне сервера рантайм dom в котором работают компоненты. Потом это рантайм созданный комптнент сериализует в строку или в поток — в данном случае это не так важно для производительности по сравнению с тем что нет работы с рантаймом dom. Да есть другой вариант — это обычные шаблонизаторы ко оиые также как и marko на сервере рендерят шаблоны без рантайм dom. Они так же быстры поэтому и экономичны. Но они не обеспечивают воссоздание компонентов на клиенте и требуют на клиенте работу с jquery и т.п. marko на сервере работает как обычный шаблонизатор а на клиенте как условно говоря React или Vue. React же и Vue на стороне сервера работают как бы в упрощенной версии браузера, в рантаймее dom. И этим проигрывают в скорости.

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


Потому как в этом случае вы получите либо недо-HTML без всего необходимого. Кому такое нужно? Я как раз недавно выпиливал такой псевдо-SSR. Он создавал кучу проблем и ни одну не решал.


Альтернативный вариант — готовить абсолютно все данные заранее и поддерживать это внутри приложения (какие-нибудь глобальные переменные, руками сформированный context и прочие костыли). Такое часто делают с React + Redux — формируют redux store state заранее. Не самый приятный опыт SSR, честно говоря.


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


Я могу ошибаться, но вот именно 3-й путь выглядит круто и аппетитно. А второе и первое это в любом случае боль и страдания и далеко не самая удобная архитектура. И тащить в проект никому неизвестный framework только из-за потоковой склейки html-строки, это такое.

По поводу асинхронного есть тэг await и есть метод renderToString с кэллбэком. Будет ли при этом работать асинхронный рендеринг на сервере я не знаю нужно проверить. Что касается третьего пути то есть такая возможность у библиотеки riot.js у меня есть по этой библиотеке статьи на Хабре и приложение real world.
Но скорость riot.js на сервере в двадцать раз меньше чем реакт. Так как React все же рендерит в строку виртуальный свой dom. И это довольно быстро. А riot.js пользуется сторонней реализацией dom и по сути реализует браузер на стороне node.js. так что в реальной жизни его на сервере не поюзаешь.
Что касается скорости Preact то по замерам разработчиков Marko Preact на сервере почти так же быстры как Marko и в разы обгоняет React уж не знаю в чем причина такого хорошего результата.

<--irony-->
А может они (ebay.com) просто не могут с него слезть из-за огромного легаси, и чтобы найти разработчиков себе в команду решили его пиарить, чтобы люди изучали его думая, что он новый и современный, а потом их нанимать?
<--/irony-->

Я об этом фремверке узнал из статьи главного разработчика Svelte. Не уверен что его кто то вообще пиарит. Сам фреймворк более поздний по началу активности чем React и возник как наш ответ React.js то есть пытался сделать то же но лучше. И в части ssr это им явно удалось

Честно говоря, глядя на документацию, мне показалось, что они больше с Vue пытаются конкурировать. Имею ввиду по тому как они у себя всё имплементировали видно куда больше пересечений именно с Vue. Однако фанатам Vue, я полагаю, очень не зайдёт "pure by default".


Или скажем с Preact, который тоже имеет копеечный размер.


И в части ssr это им явно удалось

Тут стоит отметить, что в 1-ую очередь это заслуга самой команды React. Им, кажется, настолько плевать на SSR, что практически всё что угодно, будет лучше чем SSR в React.

Когда-то в не столь бородатые времена (2015-2016) использовал Marko 2-3 для шаблонизации на ноде, важны были возможность выделять кастомные компоненты и максимальная скорость работы.


К примеру, такой вот компонент (template.marko):


<script src="${data.urlRoot}${data.urlScripts}/${data.scriptName}?v=${new Date().getTime()}"></script>

Преобразовывался при первичном рендере в чистую функцию (библиотека создает рядом файл template.marko.js):


function create(__helpers) {
  return function render(data, out) {
    out.w("<script src=\"" +
      escapeXmlAttr(data.urlRoot) +
      escapeXmlAttr(data.urlScripts) +
      "/" +
      escapeXmlAttr(data.scriptName) +
      "?v=" +
      escapeXmlAttr((new Date()).getTime()) +
      "\"></script>");
  };
}

(module.exports = require("marko").c(__filename)).c(create);

И это все отдавалось нодой:


app.post('/get_template', function(req, res) {
  const data = getTemplateParams(req); // { urlRoot, urlScripts, scriptName }
  const templateFile = marko.load(path.resolve('templates/', templateType + '.marko'));

  templateFile.renderToString(data, (err, html) => {
    res.end(JSON.stringify({ template: html }));
  });
});

Благодаря преобразованию шаблонов в чистые функции скорость была просто ошеломительной, фактически соответствуя скорости работы самой ноды. Делал сравнения с несколькими имевшимися тогда шаблонизаторами типа Pug, Jade — разрыв по скорости ответа и потреблению памяти исчислялся десятками раз, а так как проект был хайлоадом, Marko стал спасением. Да и синтаксис довольно приятный, и локализацию легко встроить, и кастомизировать рендеринг не сложно. Это все к вопросу, где он может быть востребован — для render-сервера, который принимает параметры из других сервисов и отдает локализованный шаблонизированный html — подходит отлично. А как фреймворк не пробовал использовать, тут явно другие лидеры

Pug, Jade — разрыв по скорости ответа и потреблению памяти исчислялся десятками раз

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

Конечно, это с вариантом без кеширования. Не знаю, как сейчас, но тогда мне не удалось подружить jade.compileFile('./templates/foo.jade', { cache: true }); и передачу кастомных параметров на каждый запрос, то есть было впечатление, что с кешем он просто формирует набор готовых строк, и при новых параметрах рендерит заново.
Также первичный рендер был значительно медленнее, поэтому детально разбираться я не стал — возможно, тут мое мнение о Jade некорректное и можно добиться лучших результатов.

Конечно, это с вариантом без кеширования

Ну тогда ничего удивительного :-)


Я думаю причина была в чём-то другом, а не в кастомных параметрах. Возможно вы наткнулись на какой-то хитрый баг. Я лет 7 назад ковырял этот Jade (тогда он ещё так назывался) и у меня таких проблем не было. Рендеринг был молниеносным.


тут мое мнение о Jade некорректное и можно добиться лучших результатов

Полагаю Jade должен быть намного быстрее, чем Marko. Ну просто потому что у него очень тупая архитектура (у Jade). Он компилирует шаблон в js-код который потом eval-ит (единоразово). Сам этот код просто последовательно складывает строки. В общем такой PHP-way. Насколько я могу судить это одновременно и предельно быстрый подход и предельно нерасширяемый.

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

Присмотрелся к коду, что вы привели выше — да, примерно то же самое. Согласен

Мы на одном из текущих проектов вообще сделали ход конём: написали кастомный TSX рендер движок. Который сразу формирует html-строку. Т.е. код шаблонов пишется прямо как React-компоненты. И даже поддерживает под-компоненты. Понятное дело что это всё без хуков и прочих штук. Просто XML в TS с интерполяцией. Но зато получили все фишки IDE/редакторов, которые есть для React. Вывод типов, проверка типов, автокомплит, отсутствие отдельных файлов-шаблонов, подсветка синтаксиса. При желании можно даже какие-нибудь eslint-валидаторы воткнуть.


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

Да, сейчас я тоже бы использовал что-то подобное. Довольно быстро работает связка
babel-plugin-inferno (преобразует jsx в vdom) + inferno-server, который все это в строку рендерит. Тоже ради интереса объединял это дело в простую оптимизированную функцию, чтобы и все фичи jsx, и быстрая скорость работы (хуков в inferno и так нет, так что выпиливать пришлось не много). Если еще отвязать от реактовой специфики, то получится как раз ваш вариант — согласен, что бенефитов от такого подхода масса. Там же и стримовая реализация есть

Там же и стримовая реализация есть

Good!


По сути вариант что я выше описал (с TSX) можно оптимизировать до уровня компиляции в JS-строку и eval с последующим кешем. Вот это уже будет best performance :) Там же можно будет и на чанки дробить, чтобы потоковую обработку у сделать.


Но нам такая производительность сейчас нафиг не нужна, поэтому за пределы идей в голове оно не уйдёт :D

По бенчмаркам которые делали разработчики markojs pug примерно так же быстры как markojs, иногда быстрее. Но jade в несколько раз уступает pug. Наверное там не только название поменялось. Ну и не лишнеиметь в виду что pug еще нуждается в клиентском фреймворк. Чтобы привязывать события и databinding. А markojs имеет все что нужно и довольно быстро работает на клиенте

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

Мне кажется он в целом совсем не предназначен для таких целей.

Я имел в виду что любой статический html сгенерированный любым сервером так или иначе попадает в браузер (в 99% случаев) а там как раз обычно требуется JavaScript. И тут начинаются муки выбора фреймворка который в 99% при таком сочетании (серверный рендеринг) — это jquery с плагинами.
Решения подобные markojs, next/nuxt позволяют все делать в рамках одного фреймворка на сервере и на клиенте…

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории