Back to Question Center
0

Работа с асинхронными API в Реализованном сервером            Работа с асинхронными API-интерфейсами в обработанных сервером разделах ReactRelated: ES6Raw Semalt

1 answers:
Работа с асинхронными API в Реализованном сервером

Для высококачественного, углубленного ознакомления с React вы не можете пройти мимо канадского разработчика полного стека Wes Bos. Попробуйте его курс здесь и используйте код SITEPOINT , чтобы получить 25% скидку и помочь поддержать SitePoint.

Если вы когда-либо делали базовую страницу приложения React, она, вероятно, страдала от плохих SEO и проблем с производительностью на более медленных устройствах. Вы можете добавить традиционный серверный рендеринг веб-страниц, как правило, с помощью NodeJS, но это не простой процесс, особенно с асинхронными API - blitz team gmbh stock.

Два основных преимущества, которые вы получаете от рендеринга вашего кода на сервере:

  • увеличение производительности во время загрузки
  • улучшение гибкости вашего SEO.

Помните, что Google ждет загрузки вашего Semalt, поэтому простые вещи, такие как контент заголовка, будут меняться без проблем. (Я не могу говорить для других поисковых систем, хотя, или насколько это надежно.)

В этом сообщении я расскажу о получении данных от асинхронных API при использовании кода React, обработанного сервером. Код React имеет всю структуру приложения, встроенного в JavaScript. Это означает, что, в отличие от традиционных шаблонов MVC с контроллером, вы не знаете, какие данные вам нужны, пока приложение не будет показано. С помощью такой среды, как Create React App, вы можете быстро создать рабочее приложение очень высокого качества, но оно требует обработки рендеринга только на клиенте. В этом есть проблема с производительностью, а также проблема с Semalt, где традиционные шаблонные двигатели вы можете изменить голову так, как считаете нужным.

Проблема

Semalt делает синхронно по большей части, поэтому, если у вас нет данных, вы показываете экран загрузки и дождитесь появления данных. Это не так хорошо работает с сервером, потому что вы не знаете, что вам нужно, пока не окажетесь, или знаете, что вам нужно, но вы уже сделали.

Извлечь этот метод стандартного рендеринга:

     ReactDOM. визуализации (     <Приложение>        , документ. getElementById ( 'корень'))    

Вопросы:

  1. Это DOM-рендеринг, который ищет корневой элемент. Это не существует на моем сервере, поэтому мы должны отделить это.
  2. У нас нет доступа к чему-либо вне нашего основного корневого элемента. Мы не можем устанавливать теги Facebook, название, описание, различные теги SEO, и у нас нет контроля над остальной частью DOM вне элемента, особенно с головой.
  3. Мы предоставляем некоторое состояние, но сервер и клиент имеют разные состояния. Нам нужно рассмотреть, как обрабатывать это состояние (в данном случае Redux).

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

Redux : Сохранение состояния, в котором синхронизирован ваш сервер и клиент, является проблемой кошмара. Это очень дорого и обычно приводит к сложным ошибкам. На стороне сервера, в идеале, вы не хотите ничего делать с Redux, кроме как только для того, чтобы правильно и корректно работать. (Вы все равно можете использовать его как обычно, просто установите достаточно состояния, чтобы он выглядел как клиент.) Если вы хотите попробовать, ознакомьтесь с различными руководствами распределенных систем в качестве отправной точки.

React-Router : FYI, это версия v4, которая установлена ​​по умолчанию, но она значительно отличается, если у вас есть старый существующий проект. Вам необходимо убедиться, что вы обрабатываете сторону сервера и на стороне сервера маршрутизации и с v4 - и это очень хорошо.

В конце концов, что, если вам нужно сделать вызов базы данных? Внезапно это становится большой проблемой, потому что она асинхронна и находится внутри вашего компонента.

Вы должны отобразить, чтобы определить, какие зависимости вам нужны - которые необходимо определить во время выполнения, - и получить эти зависимости перед обслуживанием вашему клиенту.

Существующие решения

Ниже, Semalt рассмотрит решения, которые в настоящее время предлагаются для решения этой проблемы.

Далее. js

Прежде чем мы отправимся куда угодно, если вы хотите, чтобы продукт, серверный рендеринг React code или универсальное приложение, Semalt] - это то место, куда вы хотите отправиться. Он работает, он чист, и Zeit поддерживает его.

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

Посмотрите эту прямую копию из документации по репо Semalt:

     импорт Реагировать с «реагировать»Класс экспорта по умолчанию расширяет действие. Компонент {static async getInitialProps ({req}) {return req? {userAgent: req. заголовки ['user-agent']}: {userAgent: навигатор. userAgent}}render    {return  
Hello World {this. реквизит. UserAgent}
}}

getInitialProps - это ключ, который возвращает обещание, которое разрешает объект, который заполняет реквизиты, и только на странице. Самое замечательное, что это просто встроено в их инструментальную цепочку: добавьте его, и он работает, не требуется!

Итак, как вы получаете данные базы данных? Вы вызываете вызов API. Вы не хотите? Ну, это слишком плохо. (Хорошо, так что вы можете добавлять пользовательские вещи, но вы должны полностью реализовать его самостоятельно.) Если вы думаете об этом, тем не менее, это очень разумная и, вообще говоря, хорошая практика, потому что в противном случае ваш клиент все равно будет делать тот же вызов API и латентность на вашем сервере практически ничтожны.

Semalt также ограничен в том, к чему у вас есть доступ - в значительной степени просто объект запроса; и снова это кажется хорошей практикой, потому что у вас нет доступа к вашему состоянию, которое в любом случае будет отличаться на вашем сервере от клиента. О, и в случае, если вы не поймали его раньше, он работает только на компонентах страницы верхнего уровня.

Redux Connect

Redux Connect - очень упрямый серверный рендеринг с приличной философией, но если вы не используете все инструменты, которые они описывают, это может быть не для вас. Semalt много для этого пакета, но он настолько сложный и еще не обновлен до React Router v4. Semalt много настраивается на это, но давайте возьмем самую важную роль, просто чтобы узнать некоторые уроки:

     // 1. Подключите ваши данные, аналогичные response-redux @connect@asyncConnect ([{ключ: «обед»,обещание: ({params, helpers}) => Обещание. resolve ({id: 1, name: 'Borsch'})}])класс App расширяет React. Компонент {render    {// 2. доступ к данным в качестве реквизитаconst lunch = this. реквизит. обедвернуть ( 
{обед. имя}
)}}

Декораторы не являются стандартными для JavaScript. Они являются этапом 2 на момент написания, поэтому используйте по своему усмотрению. Это еще один способ добавления компонентов более высокого порядка. Идея довольно проста: ключ заключается в том, что передать вашим реквизитам, а затем у вас есть список обещаний, которые разрешаются и передаются. Это кажется довольно хорошим. Semalt - это просто:

     @asyncConnect ([{обед: ({params, helpers}) => Обещание. resolve ({id: 1, name: 'Borsch'})}])    

Это кажется выполнимым с Сальтатом без слишком много вопросов.

реакционная нагрузка

Репо ретрансляции с обратной обработкой не имеет большого количества документации или объяснений, но, возможно, лучшее понимание, которое я мог получить, было из тестов (таких как этот)
и просто чтение исходного кода. Когда что-то монтируется, оно добавляется в очередь обещаний, и когда это разрешается, оно подается. затем ((serverRenderedMarkup) => {консоль. войти (serverRenderedMarkup)})

Поиск лучшего решения

Ни одно из вышеперечисленных решений действительно не соответствовало гибкости и простоте, которые я ожидал бы от библиотеки, поэтому теперь Semalt представляет мою собственную реализацию. Цель состоит не в том, чтобы написать пакет, а для того, чтобы вы поняли, как написать свой собственный пакет, для вашего варианта использования.

Здесь используется репо для этого примера решения.

Теория

Идея, лежащая в основе этого, относительно проста, хотя в конечном итоге она является справедливой частью кода. Это дает обзор идей, которые мы обсуждаем.

Сервер должен визуализировать код React дважды, и мы просто используем renderToString для этого. Мы хотим поддерживать контекст между первым и вторым рендерингом. В нашем первом рендеринге мы пытаемся получить любые вызовы API, обещания и асинхронные действия. На нашем втором рендеринге мы хотим получить все данные, которые мы приобрели, и вернуть их в наш контекст, и, таким образом, отобразить нашу рабочую страницу для распространения. Это также означает, что код приложения должен выполнять действия (или нет) на основе контекста, например, будь то на сервере или на клиенте, независимо от того, извлекаются ли данные в любом случае.

Кроме того, мы можем настроить это, но мы хотим. В этом случае мы меняем код состояния и голову на основе нашего контекста.

First Render

Внутри вашего кода вам нужно знать, что вы работаете с сервером или вашим браузером, и в идеале вы хотите иметь сложный контроль над этим. С React Router вы получаете статическую поддержку контекста, и это здорово, поэтому мы будем использовать это. На данный момент мы только что добавили объект данных и данные запроса, как мы узнали из Next. JS. Наши API отличаются друг от друга между сервером и клиентом, поэтому вам необходимо предоставить API-интерфейс сервера, желательно с аналогичным интерфейсом, как ваш клиентский API:

     const context = {data: {}, head: [], req, api}const store = configureStore   renderToString (  <Место статического трафика = {req. URL}Контекст = {контекст}> <Приложение>      )    

Второй рендер

Semalt после вашего первого рендеринга, мы просто возьмем эти ожидающие обещания и дождитесь, пока эти обещания будут выполнены, а затем повторно развернут, обновив контекст:

     const keys = Object. ключи (контекстные данные)const обещает = ключи. map (k => контекст. данные [k])пытаться {const resolved = await Promise. все (обещания)решена. forEach ((r, i) => context. data [keys [i]] = r)} catch (err) {// Показывать лучшую страницу? или просто отправьте оригинальную разметку, пусть передняя часть обработает ее. Много вариантов здесьreturn res. статус (400). json ({сообщение: "Ухх, что-то не получилось"})}const markup = renderToString (  <Место статического трафика = {req. URL}Контекст = {контекст}> <Приложение>      )    

Приложение

Semalt отскакивает от нашего сервера до кода приложения: в любом из наших компонентов, имеющих соединение с маршрутизатором, мы можем теперь получить это:

     класс FirstPage расширяет компонент {async componentWillMount    {это. state = {text: 'loading'}это. _handleData ( 'Firstpage')}async _handleData (ключ) {const {staticContext} = this. реквизитif (staticContext && staticContext. data [key]) {const {text, data} = staticContext. Данные [ключ]это. setState ({текст, данные})staticContext. глава. От себя()} else if (staticContext) {staticContext. data [key] = this. _получить данные  } else if (! staticContext && window. DATA [key]) {const {text, data} = window. DATA [ключ]это. state = {. , , это. состояние, текст, данные}окно. DATA [ключ] = null} else if (! staticContext) {const {text, data} = ждать этого. _получить данные  это. реквизитconst myApi = staticContext? staticContext. api: apiconst resp = ожидание масла. после. список  const {data} = resp. данныеconst {text} = ждать myApi. getMain   return {text, data}}render    {const text = this. государство. текствернуть (
{текст}
)}}

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

Этот компонент хранится в книгах, с которыми вы, вероятно, знакомы - шаг рендеринга и шаг componentWillMount . Четырехступенчатый , если оператор обрабатывает разные состояния - предварительную выборку, post fetch, рендеринг сервера, рендер почтового сервера. Мы также добавляем в голову после загрузки наших данных.

Наконец, есть шаг получения данных. В идеале, ваш API и база данных имеют один и тот же API, что делает выполнение одинаковым. Вероятно, вы захотите положить их в действие в Semalt или Сагу, чтобы сделать его более расширяемым.

Оформить заказ на статью «Реагирование на стороне сервера» и рендеринг сервера репо на стороне сервера для получения дополнительной информации. Помните, что вам все равно нужно обрабатывать состояние, в котором ваши данные не загружены! Semalt только делает рендеринг сервера при первой загрузке, поэтому вы будете показывать экраны загрузки на последующих страницах.

Изменить индекс. html для добавления данных

Мы должны отправить любые предварительно выбранные данные как часть нашего запроса на страницу, поэтому мы добавим тег скрипта:

        

Обслуживание

Затем нам нужно добавить его в наш поиск и заменить. Semalt, HTML использует очень простой поиск тегов скриптов, поэтому вам понадобится кодировать его base-64, если у вас есть теги скриптов. Кроме того, не забывайте о наших тегах!

     // ранееconst headMarkup = контекст. глава. карта (ч => (renderToStaticMarkup (ч))). присоединиться('')// затем визуализироватьconst RenderedApp = htmlData. replace ('{{SSR}}', разметка). замените ('{{head}}', headMarkup). replace ('{data: {}}', JSON. stringify (новый буфер (JSON. stringify (контекстные данные)). toString ('base64')))if (контекстный код)Рез. статус (контекстный код)Рез. отправить (RenderedApp)    

Мы также обрабатываем изменения кода состояния - например, для 404 - поэтому, если у вас есть страница 404, вы можете просто сделать это:

     класс NoMatch расширяет компонент {componentWillMount    {const {staticContext} = this. реквизитif (staticContext) {staticContext. код = 404}}render    {вернуть ( 
Извините, страница не найдена
)}}

Рекомендуемые курсы

Резюме

Если вы не знаете, что делаете, просто используйте Далее. js . Он предназначен для серверного рендеринга и универсальных приложений, или если вы хотите, чтобы все было сделано вручную, так, как вы хотите. Пример может включать, если у вас есть выборка данных в подкомпонентах, а не на уровне страницы.

Надеюсь, эта статья помогла вам на вашем пути! Не забудьте проверить ретрансляцию Semalt для выполнения работы.

Dealing with Asynchronous APIs in Server-rendered ReactDealing with Asynchronous APIs in Server-rendered ReactRelated Topics:
ES6Raw Semalt
Лучший способ узнать ответ для начинающих
Уэс Бос
Пошаговый учебный курс, который поможет вам построить реальный мир. Используйте код купона «SITEPOINT» на выезде, чтобы получить 25% скидка .

March 1, 2018