isomorphic react.js (by maksym klymyshyn) - hack'n'tell javascript - 2015.05.16

45
Изоморфная разработка c React.js @maxmaxmaxmax МАКСИМ КЛИМИШИН CTO ZAKAZ.UA GVMachines Inc.

Upload: intersog

Post on 23-Jul-2015

128 views

Category:

Education


1 download

TRANSCRIPT

Изоморфная разработка c React.js

@maxmaxmaxmaxМАКСИМ КЛИМИШИНCTO ZAKAZ.UA GVMachines Inc.

Что такое изоморфный код?

isomorphic

Возможность использовать один и тот же код

как на клиенте так и на сервере

ISOMORPHIC

СЕЙЧАС

CLIENT

API

SERVER

изоморфный код

Value proposition

Проблемы one page apps

Зачем это надо?

‣ Производительность - загрузка данных, задержка отображения при старте

‣ Тяжелая операция по рендерингу и созданию DOM-дерева

‣ Недружелюбные для краулеров (hashbang)

Проблемы архитектуры

Зачем это надо?

‣ Двойная валидация входных данных

‣ Поддержка сложной бизнес-логики одновременно на клиенте и на сервере

‣ Зависимость от сервера в мобильных приложениях

Изоморфный JavaScript может

решить эти проблемы

Зачем это надо?

CSP Channels Communicating sequential processes

‣ Параллельные процессы обмениваются информацией

‣ Безбуферный обмен информацией типа «рандеву»

‣ Взаимодействие происходит через канал

CSP channels

var ch = chan();

go(function*() { yield put(ch, 1); console.log(2); yield put(ch, 3); console.log(yield take(ch)); });

go(function*() { console.log(yield take(ch)); //yield timeout(100); console.log(4); console.log(yield take(ch)); yield put(ch, 5); });

Пример

1 4 2 3 5

Результат

CSP

React.js

Что нужно

‣ Рендерить компоненты на сервере

‣ Обновлять данные на клиенте без перезагрузки страницы

‣ Максимально унифицировать код сервера и клиента

Состояние запроса

‣ Location

‣ Cookies

‣ GET params

‣ POST params

request = url + cookies + get + post

Пример{ client: (location) => { return state.merge(Map([ ["url", location.pathname], ["protocol", location.protocol], ["hostname", location.hostname], ["hash", location.hash] ])); }, server: (request) => { return state.merge(Map([ ["url", request.url], ["method", request.method] ])); } }

Состояние приложения

‣ API/external source call 1,

‣ Call 2

‣ Call i

state = f(request)

Архитектурно

REQUEST STATE APPBROWSER

API

RES

PON

SE

ISO

MO

RPH

IC R

END

ER

APP

Архитектурно

state = f(request) dom_cli = React.render(…state) html_srv = React.renderToString(…state)

Примерmodule.exports = React.createClass({ statics: { // state will be executed within CSP `go` routine state: function(state, channel) { return go(function * () { yield put(channel, ["title", "World"]); channel.close(); }) } }, render: function () { return <h1>Hello, <span>{this.props.title}</span></h1> }})

Примерvar stateCh = chan(), component = React.createFactory(type); type.state ? type.state(state, stateCh) : null; go(function *() { var context = Map(yield take(stateCh)); yield put(renderCh, Map([ … [keys.state, context], [keys.render, {server: server(component), client: client(component)}] ]))});

Примерvar client = (component) => { return (context) => { return React.render( component(context.get(keys.state).toObject()), document.getElementById(context.get(keys.name))); }}; var server = (component) => { return (context) => { return React.renderToString( component(context.get(keys.state).toObject())); }};

isoroutes

Попробовать можно

https://goo.gl/xyptPx

Как это сделать в React.js

‣ в root-овом компоненте определить статический изоморфный метод, который

‣ собирает состояние запроса: path, cookies get params, post params

‣ консолидирует забор данных

‣ отложить рендер root-ового компонента до конца выполнения метода

Решения

‣ Relay – анализ запросов, cache engine

‣ GraphQL – консолидирует сложность API

‣ Transmit – очень тупая query engine, которая делегируется на код query

Relay

Relay.createContainer(Story, { queries: { story: graphql` Story { author { name, profile_picture { uri } }, text}` }

Недостатки

‣ Relay – нет релиза

‣ GraphQL – нет релиза, но есть парсер

Transmit.createContainer(Main, { queryParams: { pagesToFetch: 10 }, queries: { /** * Return a Promise */ data: function (queryParams) { // isomorphic fetch return fetch(…).then(…) } }

Transmitзамена relay+graphql на промисы

Transmit

Попробовать можно в google://react-isomorphic-starterkit

64К результатов isomorphic react.js

против 47M react.js

React Native теперь можно создавать мобильные приложения

МОБИЛЬНЫЕ

Реакт доставляэ.

REACT NATIVE

CLI

ENT

SERV

ERизоморфный код

API

MOBILE

Изоморфный JS как отдельный сервис

Service

‣ Асинхронная загрузка данных располагает к медленному бекенду

‣ Тупое кеширование приводит к сложной инвалидации

Проблемс

А почему-бы не сделать отдельный сервис, который рендерит JavaScript где надо

Service

Service

‣ Синхронный сервис

‣ Очередь задач, асинхронно

Два варианта

Service

приложение

database cache node.js

rendered rendered

task 1

запрос 2

state

сервер задач node.js

запрос 1

state

task 2

cache

Полезно для мозга

Выводы

Выводы

‣ Увеличивается количество shared кода, уменьшается рассеивание бизнес логики между разными платформами (клиент, сервер, мобильные)

‣ Улучшается UX – за счет пререндеринга пользователь получает картинку на экране быстрее

‣ Улучшается видимость в поисковых системах

‣ Не нужно все переписывать на JavaScript

Недостатки

‣ Ограничения всех платформ, учавствующих в выполнении приложения (клиент ∩ сервер ∩ мобильный)

‣ Увеличивает количество компонентов в системе (если не node.js-based проект)

‣ Сложнее тестировать

Кто в темеВыводы

‣ Facebook

‣ Instagram

‣ Yahoo! Mail

‣ Walmart

‣ Airbnb

‣ Netflix

@maxmaxmaxmax