Comments 55
Спасибо за обзор.
"как изоморфные приложения отразятся на Вашей зарплате" — хотелось бы послушать и про это.
Про большой размер Bundle-JS: на самом деле можно всё распилить на небольшие чанки (отдельные куски js-кода) и грузить их динамически на клиенте через SystemJS. Webpack 2 нам поможет.
Пока что у React-а весьма плачевная ситуация с роутингом — с 2013 никто так и не осилил сделать всё по уму. Вся надежда на React Router v4. Но пока что там всё очень сыро и недоделано.
А в целом про изоморфные приложения, что хочу добавить: их разработка требует весьма больших компетенций, очень легко где-нибудь облажаться, нужно разбираться в десятках современных инструментов и использовать некоторые подходы к разработке, которые плохо ложатся в головы программистов на JavaScript, например, практически нельзя использовать синглтоны и глобальные переменные в изоморфном коде, а те, кто привык писать клиентский код, лепят их где попало, ибо привыкли, что всегда один экземпляр клиента.
Про большой размер Bundle-JS: на самом деле можно всё распилить на небольшие чанки (отдельные куски js-кода) и грузить их динамически...
Ну на самом деле это далеко не волшебная пилюля. Например у меня в единственном проекте на Reat при загрузке отображается либо страница логина, либо главная страница. В любом случае для работы эти страниц надо загрузить: React, React Bootstrap, lodash, React Router, Redux. Это самые большие библиотеки в проекте и именно они составляют около 70 процентов бандла. Так что в динамическую загрузку получиться отправить только 30% бандла (а то и меньше).
Хоть сейчас берите Emscripten и пишите.
И может я че-то не понимаю… Раньше все скидывали на клиент, чтобы сервер меньше считал. А теперь типа все назад на сервер, потмоу что ОДИН клиент не тянет. А сервер значит 1000 клиентов — легко.
И вот что ещё странно. На клиенте утечка памяти есть, а на сервере на 1000 подключений на томже самом стеке технологий не будет… Странно.
А как дебажить эти ваши изоморфные приложения???
Давайте я вам расскажу. Приложение на клиенте выполняется все время: там всякие таймеры, бэкграунд события, работа со стейтом и тд.
Сервер сайд рендеринг конвертит HTTP запрос в HTML и отдает его клиенту. Все! Поэтому он и тянет 1000 клиентов и утечек там не происходит. Задержка для обычных SPA происходит, потому что надо выкачать JS, обработать его и запустить. Здесь и проходят потеря времени. Изоморфные приложения дают контент юзеру раньше, чем обработается JS, что улучшает UX и делает ваш ресурс SEO-friendly.
Дебажать также просто — у вас код общий на клиенте и на сервере на 90+%. Так что разницы между SPA и изоморфной частью нет особенно. Тут более подробно — https://habrahabr.ru/post/309958/
Суть статьи в следующем.
Придумываем 4-хзвенную технологию.
Звено 1 — база данных
Звено 2 — сервер, которые генерит данные из базы наружу. Сейчас это можно слово «RAST»
Звено 3 — сервер, который генерит шаблон страницы в HTML с помощью js. Это костыль данной технологии — генерацию страницы уже не знаю куда приткнуть: typescript(чтобы можно было больше 3-х файлов написать коллективом более 2-х человек) + babel (потому что нужен прогресс ради прогресса без понятного результата) + framework1-2-3 (костыли для компонентной разработки, потомоу что HTML убог и примитивен). Если выйти за рамки JS, то это все всякие разные PHP/Python/CGI спокойно делают это последние 20 лет без особых заморочек.
Звено4 — браузер, который получив шаблов HTML, подгружает скрипты и страница работает.
Всяя суть статьи в том, что звенья 3 и 4 вы можете сделать в браузере. По своему желанию — или так, или так.
Только особенность технологии JS — если сделать все браузере, то он ставит современные компы на колени (напримет тотже atom за 3-4 час а рабоыт выжирает несколько Гб оперативки на паре открытых файлов по 10 кб).
Итогог, ИЗОМОРФНЫЙ = костыль JS.
Если это слово убрать, то PHP/Python/C++/Pascal + JS — тоже можно, только модные слова типа React, Angular, ES6 — проходят мимо и остается просто работа.
Кстати, судя по статьям на хабре, технология фремворков JS деградирует — ответа, на чем писать, нет даже приблизительно, есть лишь разные варианты БДСМ.
ЗЫ. Подсказываю, как и коментатор ниже — проблема в браузере как стеке технологий.
Серверная часть веб приложений на С++ и сейчас есть, это не обязательно С++. Экзотика это С++ в клиенте через наступающий WebAssembly.
— Грамотный подход к структуре приложения. Не надо делать один большой бандл. Разбивайте приложение на пакеты и модули. Подгружайте все остальное по мере необходимости. И не будет никаких проблем с пустой страницей. К примеру у меня 10 пакетов, каждый их которых содержит 5-7 модулей. А для главной нужены только два три модуля из пакета. А когда происходит навигация — догружаете нужное.
— Проблемы СЕО. Создаем АПИ для робота и отдаем нужный контент. Да, это хак, но снимает кучу проблем. Да приходится поддерживать две точки входа, но еще ни разу не испытывали с этим проблем.
— Один код для сервера и клиента не всегда хорошо, а можно сказать плохо. Возьмем на примере микросервисную архитектуру, где микросервис может быть написан на Java/JS/Python/Ruby/PHP. Кроме JS ваш код нигде больше не пригодится. И что делать, если решили переписать, к примеру один микросервис с Node JS на Java? Приплыли с изоморфом. Пусть лучше каждая часть делает то, что хорошо умеет.
— 5% для бизнеса это крах? Ребята, оставьте «дедушек» умирать. Пусть отойдут в мир иной. И задумайтесь над поддержкой кода для «старья». Иногда овчинка выделки не стоит. Для себя давно вынес решение — никакой поддержки старых браузеров, что приносит значительную экономию по времени, а так же позволяет использовать более новые технологии без лишних полифилов.
Обычно когда речь про изоморфные веб-приложения, это не про API. Это исключительно про UI-ную часть.
API можно на чем угодно писать и дробить его на сколько угодно микросервисов.
Было бы интересно ознакомиться с какими-нибудь материалами по SEO-адаптации одностраничных приложений, поделитесь опытом или ссылкой, пожалуйста.
Для паука можно подготовить один шаблон для всех страниц — картинка, заголовок, контент (или массив контентов).
Почему бы не отдавать сразу в html скрытый html-контент для индексации?
В целом если поразмыслить, я написал 4-5 SPA. Это именно Applications, и хоть в одном бы ешкин кошкин понадобилась бы SEO-оптимизация… так нет же… всё самое вкусное, в назовем так, «личном кабинете».
По поводу вкусняшек — самое вкусное содержит приватные данные пользователя, который бы не хотел публиковать их наружу. Если развивать тему, то SEO оптимизацию имеет смысл делать, в рамках SPA, только на блогах или магазинах к примеру. Да и там собственно логики кот наплакал.
Возьмем за основу магазин. Страница списка товаров. Страница товара. Корзина. Навигация. Поиск. Да собственно и все. Логики почти ноль, как и работы над проектом. И вообще не интересно работать с таким проектом.
Другое дело если это ERP или CRM системы. Со своей админкой, кабинетами, профилями, правами доступа итд. Вот тут SEO и нафиг не нужна. Зато здесь уже надо уделять внимание структуре проекта, оптимизации кода, бизнес логике итд.
Что касается отдачи скрытого контента — надо знать URL'ы, а в метеоре обычно роутинг клиентский. Так что тоже не особо вариант. В любом случае SEO-оптимизировать, скажем, канбан-доску и прочий функционал, связанный с пользовательским контентом, да, нет смысла.
Хороший текст, я даже для себя немного нового узнал. Правда я плюсанул :)
У темы "изоморфных веб-приложений" много ненавистников. Увы. Хотя легко понять почему, всё очень сложно программируется, сотни статей на эту тему, а на выходе всё равно у всех получается страшный клиент весом 3 мегабайта.
Но когда-нибудь скоро все проблемы и подходы к их решению будут стандартизированы, и мы будем иметь легковесные изоморфные single page application.
Изоморфность в контексте Реакта — тупиковый путь в принципе. И проблема даже не в истинной сложности (о которой стыдливо умалчивают в восторженных статьях) и весе, а в том, что на самом деле эта вся возня не дает никакого ощутимого профита по сравнению с иными подходами. А если говорить о будущем — вспомните лучше о веб-компонентах: близкое знакомство с ними ставит мозги на место и хорошо лечит Реакт-головного-мозга.
В теории все замечательно. На практике, уже с интернетом 1 Мбит пользоваться Web очень некомфортно. Когда используешь телефон в области слабого приема (Edge, а такие места встречаются очень часто даже в Московской области), можно даже не пытаться загрузить многие сайты — все равно загрузка этих гигантских бандлов либо прервется по таймауту через несколько минут, либо, что более вероятно, устанешь ждать.
За границей, где слабый Wifi или медленный и дорогой мобильный интернет, современный Web превращает жизнь в кошмар. В прошлом году мне надо было отправить перевод через Интернет-банк за границей. Я потратил на это полдня, но так и не смог дождаться загрузки интерфейса банка. Загрузка постоянно отваливалась по таймауту, все эти огромные бандлы грузятся одним куском и не кэшируются.
"Кэширование? Это какая-то технология 1999 года? У нас нет времени на это старье, мы тут переписываем свое изоморфное Redux-React супер приложение с React 14 на React 15. На наших гигабитных каналах это уменьшает время отклика на 0.001 с — гигантское преимущество, пускай и придется переписать 80% кода. Отстаньте со своим кэшированием". Как-то так получается… :(
Хипстота же, технологии ради технологи. Создаем мельницы, а потом героически с ними боремся, чтобы было о чем рассказать на следующем афтерпати за бокальчиком смузи. Загрузку кода современного жсера можно ускорить вдвое, если выкинуть весь код, который был подключен просто чтобы не выпадать из трендов на следующей конференции.
Право, сейчас за границей и ситуация строго наоборот — вайфай везде и бесплатно, 4G на телефоне и стоит копейки.
Ну, конкретно проблема с банком была в Индии. Я знаю, что в Индии едва ли не самый медленный интернет в мире. Но на мой взгляд это не оправдывает хипста-сайты, которые сейчас везде. Если в Индии их просто загрузить невозможно, то в России, например, это просто некомфортно. Во-первых, очень долго. За городом у меня интернет 1 Мбит, и очень многие сайты ощутимо тормозят. Более быстрый интернет обойдется мне значительно дороже.
Многие тарифные планы для мобильных имеют ограничения по трафику. Не знаю почему, но по опыту все эти React-Redux-куча-прочих-buzzwords приложения каждый раз загружают эти бандлы заново. Может быть React требует внесения изменений в приложение каждые полчаса. Не знаю. Но трафик это подъедает заметно, и скорость загрузки тоже сильно страдает.
В принципе понимаю, что нет в жизни счастья, и надо раскошеливаться на новый интернет-канал на даче, лучше ситуация не станет. А за границей надо планировать все так, чтобы не понадобилось заходить в интернет-банк. Просто удивляет, что все это преподносится как супер-дупер технологии, которые улучшают время загрузки и отклика, а по моему опыту как пользователя — все совсем наоборот. Страницы стали тяжелыми, медленными и хрупкими (то есть, если скорость канала чуть ниже какой-то критической, субъективно менее 1 Мбит, то все эти SPA начинают подвисать, глючить, ломаться).
Ну, в случае с интернет-банком (а также во многих других), это бесполезно. Все равно, пока не догрузятся гигантские бандлы, ничего в банке сделать будет нельзя. А они не загрузятся, потому что загрузка прервется по таймауту.
А даже если и загрузятся, то ни одно из новомодных приложений не проверятся на то, как оно будет вести себя на плохом канале связи. В итоге нередко бывает, что кнопки не нажимаются, формы не работают, и т.д. и т.п., потому что приложение предполагает, что любая коммуникация с сервером завершается успешно (потому что у разработчиков сервер на той же машине, или рядом, на 10 Гбит канале), шлют по сети гигантские JSON-блобы, которые опять же либо теряются, либо приводят к таймауту, а эти ситуации никак не предусмотрены в приложении. Некогда их предусматривать, новая версия Redux вышла. Или FooBarQuux, который в тыщщу раз круче, чем Redux.
Я это взял с того, что часто нахожусь в местах, где медленный интернет. Там все эти модные SPA работают из рук вон плохо. Progressive Enhancement — все понимают, что это хорошо, но никто не делает. Например, один из российских банков отображает страницу ввода пароля до загрузки бандла, но если до полной загрузки ввести пароль, то получаем ошибку. Впрочем, раньше эта страница весила 18 Мб или больше, и дождаться ее загрузки по Edge соединению где-нибудь в Индии было просто невозможно.
У остальных все приблизительно так же. Если не находишься на быстром соединении (как минимум 3G/4G), то любым из современных сайтов пользоваться почти невозможно, включая даже не особо динамические GT и Habrahabr — почему-то часто начало страницы начинает отображаться, а затем браузер заменяет ее на страницу о невозможности загрузки. Как им это удается, не понимаю....
Даже если SPA загрузилось, то оно не работает на медленном соединении. Кнопки не нажимаются, формы не отправляются, возникают ошибки одна загадочнее другой.
Ну что поделать, мир несовершенен. Любая технология, которую можно использовать неправильно, будет использована неправильно.
Из этой же серии приложения на Electron. Простой чатик будет выжирать 2- Гб памяти, и процентов 20-40 CPU. Если же необходимо несколько таких приложений, то к ноутбуку надо будет прилагать батарею Tesla и промышленный вентилятор для охлаждения. Но поток SPA и Electron-приложений это не останавливает, к сожалению.
У разработчиков SPA нет никаких мотивов, чтобы делать небольшие приложения с поддержкой progressive enhancement. Люди, как я, которые много времени проводят в местах с плохим интернетом, не приносят их бизнесу достаточно прибыли, чтобы оправдать правильное написание/оптимизацию.
В своем комментарии, вы безапелляционно написали, что мол пока не загрузится бандл ничего сделать будет нельзя. Я в свою очередь написал, что это сильно зависит от разработчиков приложения и сама по себе такая возможность есть. И кстати говоря, нужно приложить не так уж и много усилий для того, чтобы обеспечить должный уровень progressive enhancement. Проверено на собственном опыте.
Основная проблема как раз и кроется в статьях/комментариях/итп где люди пишут как это сложно и не нужно, при этом мало кто действительно пробовать сделать.
У разработчиков SPA нет никаких мотивов, чтобы делать небольшие приложения с поддержкой progressive enhancement.
У SPA да, но изоформные приложения это не SPA в классическом смысле. У разработчиком таких приложений намного больше мотивов, ибо если ты уже научил свой сервер отвечать на все GET запросы изоморфно, то почему бы не научить его обрабатывать и POST запросты также? Нипочему.
Спасибо за очередной интересный доклад. Вот только я что-то так и не понял зачем нужен отдельный frontend-сервер, это же было до SPA, что сервер сам генерил HTML и отдавал в браузер, теперь получается тоже самое, только с посредником? Или я что-то не так понимаю?
Вся соль в том, что frontend-сервер и frontend-клиент теперь могут иметь 90+% общего кода.
А зачем нужен отдельный frontend-сервер, в чем его необходимость в данной архитектуре?
Классические SPA не дружат с поисковиками и индексированием (есть костыли, но они плохие). А изоморфные, благодаря серверному рендерингу, дружат.
А еще серверный рендеринг ускоряет визуализацию контента в браузере. Т.е. сначала, скажем, отдается 50кб html+css. Пользователь их сразу видит и может уже читать страничку, тыкать по ссылкам и т.д… А только потом уже незаметно для пользователя подгружается тяжелый js-bundle.
Это быстрее чем классические SPA, которые сначала показывают пустую страницу, потом тянут js-bundle целиком, и только потом пользователь что-то видит в браузере.
Классический рендеринг на сервере (не SPA) тоже дружит с поисковиками и с индексированием, загружается страница тоже может быть небольшого размера, но это считается прошлый век.
Ну идея про 90+% общего кода точно классная. В теории это легче и дешевле поддерживать будет. Особенно для крупных проектов.
На практике неясно, пока всё только устаканивается. Проблем хватает.
2. Обеспечивает отдачу отрендеренного HTML по URL (первый заход, поисковые и прочие боты, ориентирующиеся на HTML)
3. (опционально) Служит для SPA шлюзом и агрегатором бэкенда
За эволюцией веб-сообщества можно наблюдать бесконечно. Вот примерная история:
- сервер отдает статический хтмл и ресурсы, просто и идиоматично
- появился PHP, а давайте возвращать хтмл динамически
- Js/JQuery, зачем возвращать хтмл динамически, если можно не заставлять юзера ждать перезагрузку страницы
- только js/SPA, см. п.1 (сервер отдает статический хтмл и ресурсы)
- А давайте снова возвращать хтмл динамически
- (будущее) непонятный баланс между мнгновенным открытием сайта и устанавливаемыми веб-приложениями
<?php require 'http://js-server/needed-url' ?>
Для Symfony есть бандл, который делает это более секурно и гибко, может использовать как рендер-сервер, так и запускать node как обычный процесс.
1. пользователь вводит адрес
2. браузер делает запрос на nginx
3. nginx проверяет есть ли статика, удовлетворяющая запросу
3.1. если есть — отдаёт
3.2. если нет — проксирует на js-сервер
4. js сервер проверяет может ли отрендерить результат сам (возможно обращаясь к php-серверу по API)
4.1. если есть — рендерит
4.2. если нет — проксирует на php-сервер
5. php-сервер обрабатывает запрос обычным путём
Если критично, то можно роутинг сделать на nginx, чтобы он по урлу и прочим параметрам запроса определял куда направлять запросы на js или php. Но это поддерживать сложнее — нужно внедренные на JS-сервере фичи не забывать описывать в конфиге js.
Изоморфные React-приложения: производительность и масштабирование