Серверная часть NodeJS работает локально, но не на Heroku - PullRequest
0 голосов
/ 26 июня 2018

Мне было интересно, если у кого-то еще возникла проблема, когда он создал приложение NodeJS для рендеринга на стороне сервера, которое прекрасно работает локально, но не загружает серверную часть после развертывания на heroku.

Я создал приложение, используя потрясающий RazzleJS Джареда Палмера в сочетании с Redux, React Router и React Rouig Config.

Способ работает так, что в моем файле server.js я проверяю компонент, который загружается, для статической функции с именем fetchData, если функция существует, то функция запускается, что является запросом на основе обещаний к API, используя Аксиозы в гром.

В моем файле server.js запускается другая функция, которая проверяет выполнение всех обещаний, прежде чем окончательно отобразить HTML-код для страницы.

Локально это работает отлично, и даже если Javascript отключен, страница загружается вместе с выбранными данными.

Развернув это на heroku (единый план dyno - hobby), однако, если я отключу javascript, страница загружается с отсутствующими данными, что предполагает, что страница отображается перед разрешением обещаний. Затем данные загружаются правильно с использованием эквивалентной отправки ComponentDidMount для данных.

В настоящее время у меня есть следующий код:

Server.js

function handleRender(req, res) {
  const sheet = new ServerStyleSheet();

  const store = createStore(rootReducer, compose(applyMiddleware(thunk)));

  const branch = matchRoutes(Routes, req.url);
  const promises = branch.map(({ route }) => {
    let fetchData = route.component.fetchData;

    return fetchData instanceof Function
      ? fetchData(store, req.url)
      : Promise.resolve(null);
  });

  return Promise.all(promises).then(() => {      
    const context = {};
    const html = renderToString(
      sheet.collectStyles(
        <Provider store={store}>
          <StaticRouter context={context} location={req.url}>
            {renderRoutes(Routes)}
          </StaticRouter>
        </Provider>
      )
    );

    const helmet = Helmet.renderStatic();
    const styleTags = sheet.getStyleTags();
    const preloadedState = store.getState();

    if (context.url) {      
      res.redirect(context.url);
    } else {      
      res
        .status(200)
        .send(renderFullPage(html, preloadedState, styleTags, helmet));
    }
  });
}

Пример компонента React

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchProductData } from '../thunks/product-data';

class Test extends Component {
  static fetchData(store, url) {
    store.dispatch(fetchProductData());
  }

  componentDidMount() {
    if(this.props.productData.length === 0 ) {
      this.props.fetchProductData() // Successfully fetches the data
    }
  }

  render() {
    return (
      <div>
        { this.props.productData && this.props.productData.map( (product, i)  => {
          return <div key={i}>{product.title}</div>
        })}
      </div>
    );
  }
}

const mapStateToProps = state => {
  return {
    productData: state.productData
  }
};

const mapDispatchToProps = dispatch => {
  return {
    fetchProductData(){
      dispatch(fetchProductData());
    }
  }
};

export const TestContainer = connect(mapStateToProps, mapDispatchToProps)(Test);

Это всего лишь пример компоновки компонентов, так как те, которые у меня есть, довольно сложны, но в этом случае productData будет установлен в [] в defaultState.

Кроме того, все редукторы и действия работают правильно локально, и только при развертывании в Heroku по плану хобби рендеринг на стороне сервера больше не работает?

1 Ответ

0 голосов
/ 27 июня 2018

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

React-router-config, однако, не может справиться с тем фактом, что функция fetchData является еще одним уровнем в иерархии, и поэтому все мои обещания были разрешены с нулем.

Теперь, когда я снова удалил компонент HOC, рендеринг на стороне сервера снова работает правильно:)

...