Upload
max-klymyshyn
View
345
Download
3
Embed Size (px)
Citation preview
Изоморфная разработка 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 проект)
‣ Сложнее тестировать
Кто в темеВыводы
‣ Yahoo! Mail
‣ Walmart
‣ Airbnb
‣ Netflix
@maxmaxmaxmax