Изоморфные веб-приложения: скорее нет, чем да

топ 100 блогов tonsky01.03.2015

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

Как бы нам этого ни хотелось, данные лежат не в браузере (иногда они, конечно, лежат, но это скорее исключение, да и там уже все не так просто стало). На горизонте появляются тучи, простая и стройная архитектура обрастает некрасивыми хаками. Разные компоненты хотят разные куски данных, иногда куски повторяются, надо решать проблему N+1 select, обратная синхронизация, разделение на начальный префетчинг и доставку дельт. REST это новый ORM (пока, правда, не дотягивающий даже до JDBC), а ORM это путь в никуда. Короче, обычный конфликт: наивную версию сделать просто, но работать она будет неприемлимо, а оптимизации вступают в конфликт с базовыми принципами хорошей архитектуры. Facebook предложил Relay + GraphQL, но ощущения пока такие, что хорошо работать это будет в основном на фейсбуке или чем-то очень похожем: рамки сильнее бенефитов.

Что нужно: язык описания зависимостей по данным и протокол синхронизации на его основе, оптимизируемый, в меру универсальный, компонуемый. В идеале один и тот же язык описывает поток браузер-сервер и потоки внутри браузера: от компонентов к родителям, от родителей в центральный sync hub. Потоки двухсторонние: компоненты отправляют запросы по данным в sync hub, там запрос группируется (компонуемость), отсылается на сервер, и наоборот: сервер пушит данные в браузер, sync hub раскидывает по компонентам, кто на что подписался. Возможно, аналогичную схему «одуванчик» можно повторить и внутри сервера.

Вторая область, где не все гладко и сладко — рендеринг страниц на сервере. Если посмотреть с очень высокой башни, можно увидеть основание из слоновой кости и то, что рендеринг на сервере это бред. У нас есть какое-то хранилище, база, это нормально. Есть приложение, оно в браузере и на js. А вот зачем между базой и клиентом нужна какая-то тонкая прослойка в виде рендеринга каких-то странных кусочков html-шаблонов, которые потом надо как-то частично подставлять в уже работающую страницу? Типичное размазывание отвественности: если мы хотим веб-интерфейс, пусть он будет в одном месте (браузер), и пусть у него там будет под рукой все что нужно. Если согласиться, что естественно не держать никакой view логики на сервере (включая тупые параметры REST-концов типа sort=name&order=asc, которые относятся только к вьюхам, вьюхам, вьюхам), роль сервера становится сильно непонятной.

В идеальной архитектуре сервер — точно такой же равноправный луч звезды, присосавшийся к центральной базе/логу событий, как и клиент в бразуере. Просто у него задачи другие — batch-работу какую-то считать, за метриками следить, почту рассылать по расписанию. Это ни в коем случае не паразитирующий посредник на соединении клиент-база. У клиента уже есть всё, чтобы себя обеспечить, сервер как помощник скорее мешает, чем помогает. К тому же все, вплоть до умеренно-больших проектов, всегда делают один и тот же бэкенд: код генерируется и обслуживается фреймворком и на 90% состоит из тавтологии: возьми table user и переложи ее в user.json. Смысл придумывать, писать и поддежривать прослойку, занимающуюся перекладыванием из формы в базу, если и формы, и базы в принципе уже сами это могут? Дайте им поговорить напрямую. В качестве иллюстрации посмотрите Hoodie и noBackend. Хипстерятина, конечно, но хипстеры же неспроста не хотят писать бэкенд — в нем действительно нет большого смысла.

Но я отвлекся. Если строить свое приложение без сервера, всё как раз получается стройно и логично. Но некоторые противные Гуглы хотят, чтобы по GET /index.html HTTP/1.1 отдавался контент, а не какое-то там веб-приложение. И если мы захотим сделать веб-магазин, то какими бы передовыми мы ни были, и как бы сильно нам ни хотелось сократить траты на разработку и душевное здоровье, под Гугл придется прогнуться.

И тут мы обнаруживаем себя у разбитого корыта. Сколько бы нам уши не жужжали про объединение браузера и клиента, примеры там обычно на уровне «реализовать факториал один раз». А тут настоящий, честный тест: языка, инфраструктуры вокруг него, абстракций, всего. Даже если ClojureScript и кроссплатформенный (через cljx несложно, даже почти удобно писать код, запускающийся и на сервере, и в браузере), то передовой React уже не так охотно готов запускаться на JVM. Надо сразу придумывать какой-то JS-рантайм (очень сподручно, я вам скажу) — но это ладно, его можно и придумать, и даже условно-эффективно (правда, не на JVM, а скорее на node.js). Гораздо интереснее принципиальные вопросы: как выковырять весь свой динамизм из веб-приложения, всякие onClick и onChange (можете себе представить), как эмулировать подгрузку данных, куда девать пуш-механизм (можно ли без него? а если по нему приходит важная часть контента?) и завязки на DOM (React, кстати, пример очень хорошей абстракции-затычки конкретно в этом месте). Ну и немножко поиграть в искусственный интеллект: представьте, что у вас живое приложение, которое рисуется в несколько проходов: сначала костяк, потом идет запрос на сервер (асинхронный, конечно), потом приходят данные (или обрабатывается ошибка), на основании этих данных делается еще N запросов, и так далее. Плюс стоят всякие фишечки, чтобы улучшить User Experience — прогресс-бар там, фоллбеки какие-то, анимации — исключительно для человека, не для Гуглового бота же. В какой-то момент вам нужно решить, что только что приложение было не готово, а вот сейчас уже в таком состоянии, что его можно отдавать Гуглу, надо делать снэпшот и высылать html. Решаемо, конечно, но опять — чувствуете? — очень сложно и местечково вместо красоты и фиалок.

И это хорошо еще если мы сможем хорошо подгрузку данных замокать (скажем, если у нас есть тот самый воображаемый язык из начала статьи). Но если для полной универсальности сервер-сайд приложение будет само на себя ходить по REST-концам, ну, там, с декодированием JSON-а, аутентификацией, эмуляцией cookie storage — я, пожалуй, в этом месте сразу на пенсию и мемуары переключусь. Программисты всю жизнь делали нестыкуемые между собой платформы (сколько сил вгрохано в проекты из серии «А это тот же X, только для Питона»). Сейчас жизнь прижала, деваться некуда, и мне, если честно, страшно смотреть, что из этого выйдет. Пока выходят ужасы из серии «перепишем git на js» и «запустим js внутри JVM/Монги/nginx».

Короче, различий между живым браузером и статичной версией для Гугла столько, что впору призадуматься: а нужна она вообще, эта изоморфность (не смейтесь, это термин из JS)? То есть нужна, конечно, но похоже что наскоком ее не сделать. Даже, скорее, если ее и делать, то с самого начала, честно, основательно, и придется многим поступиться. Причем границы этого пока туманно очерчены, но может оказаться, что с такими требованиями мы обратно придем к статичным веб-страницам и тонкому клиенту. Потому что сама постановка вопроса, она такая, несовместимая со здравым смыслом.

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

Оставить комментарий

Архив записей в блогах:
Председатель Верховного кассационного суда Бранислава Павлова 12 декабря 2022 года подтвердила, что бывший царь болгар и его сестра действительно являются владельцами дворца Врана. Приговор следует тому же решению, принятому тем же судом в октябре 2020 года в отношении дворца Царская ...
Странная там война какая-то. Как мне представляется, эти бедолаги из коалиционных войск, отбомбившись летят к себе на базу и репу чешут: «А чего это мы вдруг?». А потом думают «А не ебёт, уплочено» и дальше летят бомбить. Нефть – это как-то ...
Мы собрались в гостях у бабушки. Мама смеётся, гремит посудой. Папа сидит в кресле у окна и читает газету. Дядя веселит всех анекдотами. Бабушка несёт из кухни огромное блюдо с пирогами. Ах, какие это восхитительные пироги! Двоюродный брат зовёт меня на балкон. Там в укромном уголке ...
Оригинал взят у holmogor в Полная серия криптосталинистского безумия… При этом самое забавное и тоже по своему "сталинистское" - это относительная корректность в цифрах. 680 тыс приговоренных к расстрелу - это не "миллионы ...
Наш уважаемый премьер несколько лет назад (точнее, в 2003 г) выдвинул незабываемый лозунг –   увеличить ВВП страны за 10 лет в два раза. На фоне растущих цен на нефть, старта крупноузлового производства иностранных автомобилей и оживления на ...