NodeJS服务器端在本地工作,但不在Heroku上工作

时间:2018-06-26 17:27:06

标签: javascript node.js reactjs heroku serverside-rendering

我想知道是否有人在创建服务器端渲染NodeJS应用程序时遇到问题,该应用程序在本地可完美运行,但是一旦部署到heroku,就不会加载服务器端。

我使用Jared Palmer出色的RazzleJS结合Redux,React Router和React Router Config创建了一个应用程序。

它的工作方式是在我的server.js文件中检查正在加载的名为fetchData的静态函数的组件,如果该函数存在,则该函数将运行,这是一个基于promise的请求到使用axios的API进行转换。

然后在我的server.js文件中运行另一个函数,该函数在最终呈现页面的HTML之前检查所有Promise是否已完成。

在本地这可以完美地工作,即使禁用了Javascript,页面也会加载完整的数据。

已将其部署到heroku(单个dyno-业余爱好计划),但是,如果我禁用了javascript,则该页面正在加载而缺少数据,这表明该页面是在promise解决之前呈现的。然后,使用等效的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 :(得分:0)

因此,经过一整天的研究,之所以无法在我的实时环境中工作,是因为我具有用于跟踪分析目的的HOC包装组件。

但是,react-router-config无法处理fetchData函数是层次结构中更深一层的事实,因此我的所有诺言都用null进行了解决。

现在,我再次删除了HOC组件,服务器端渲染再次正常工作:)