首页 > 解决方案 > NodeJS 服务器端在本地工作,但不在 Heroku 上

问题描述

我想知道是否有其他人遇到过这样的问题:他们创建了一个服务器端渲染 NodeJS 应用程序,该应用程序在本地完美运行,但一旦部署到 heroku 就不会加载服务器端。

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

它的工作方式是,在我的server.js文件中,我检查正在加载的静态函数调用的组件fetchData,如果该函数存在,则运行该函数,这是一个使用 axios 在 thunk 中对 API 的基于承诺的请求。

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

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

已将其部署到 heroku(单测功机 - 爱好计划),但是如果我禁用 javascript 页面正在加载数据丢失,这表明该页面在承诺解决之前正在呈现。然后使用数据的等效 ComponentDidMount 调度正确加载数据。

我目前有以下代码:

服务器.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));
    }
  });
}

示例反应组件

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 时,服务器端渲染似乎不再工作?

标签: javascriptnode.jsreactjsherokuserver-side-rendering

解决方案


因此,经过一上午的研究,它无法在我的实时环境中运行的原因是因为我有一个 HOC 包装组件用于跟踪分析。

然而,React-router-config 无法处理 fetchData 函数在层次结构中更深层次的事实,因此我的所有承诺都以 null 解决。

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


推荐阅读