简体   繁体   English

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

[英]NodeJS Server Side working Locally but not on Heroku

I was wondering if anyone else has had the problem where they have created a Server side rendering NodeJS app which works perfectly locally but then doesn't load server side once deployed to heroku. 我想知道是否有人在创建服务器端渲染NodeJS应用程序时遇到问题,该应用程序在本地可以完美运行,但是一旦部署到heroku后就不会加载服务器端。

I have created an app using Jared Palmer's awesome RazzleJS in combination with Redux, React Router and React Router Config. 我使用Jared Palmer的超棒RazzleJS结合Redux,React Router和React Router Config创建了一个应用程序。

The way it works is that in my server.js file I check the component that is loading for a static function called fetchData , if the function exists then the function is run which is a promise based request to an API using axios in a thunk. 它的工作方式是,在我的server.js文件中,我检查了正在加载的组件中是否有一个名为fetchData的静态函数,如果该函数存在,则该函数将运行,这是基于thunk的axios对API的基于承诺的请求。

In my server.js file another function then runs that checks all promises have completed before finally rendering the HTML for the page. 在我的server.js文件中,然后运行另一个函数,该函数在最终呈现页面的HTML之前检查所有Promise是否已完成。

Locally this works perfectly and even with Javascript disabled the page is loading complete with the data fetched. 在本地这是完美的,即使禁用了Javascript,页面也会加载完整的数据。

Having deployed this to heroku (single dyno - hobby plan) however if I disable javascript the page is loading with the data missing, suggesting that page is being rendered before the promises resolve. 已经将其部署到heroku(单个dyno-业余爱好计划),但是,如果我禁用了javascript,页面正在加载而数据丢失,这表明该页面在promise解决之前就已呈现。 The data is then being loaded correctly using the equivalent ComponentDidMount dispatch for the data. 然后,使用等效的ComponentDidMount分派为数据正确加载数据。

I currently have the following code: 我目前有以下代码:

Server.js 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));
    }
  });
}

Example React Component 示例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);

This is just an example of the component layout as the ones I actually have are quite complex but in this instance productData would be set to [] in defaultState. 这只是组件布局的一个示例,因为我实际拥有的组件非常复杂,但是在这种情况下, productData将在defaultState中设置为[]

Also all reducers and actions are working correctly locally it is only when deployed to Heroku on a hobby plan that the server side rendering seems to no longer work? 同样,所有的reducer和action在本地都无法正常工作,只是只有按照业余计划将其部署到Heroku时,服务器端渲染才似乎不再起作用?

So after a morning of research the reason that it wasn't working in my live environment was because I have a HOC wrapping component for the purposes of tracking analytics. 因此,经过一整天的研究,之所以无法在我的实时环境中工作,是因为我有一个用于跟踪分析的HOC包装组件。

React-router-config however can't handle the fact that the fetchData function is another level deeper in the hierarchy and so all my promises were resolved with null. 但是React-router-config无法处理fetchData函数是层次结构中更深一层的事实,因此我的所有诺言都用null进行了解析。

Now that I have removed the HOC component again, server side rendering is once again working properly :) 现在,我再次删除了HOC组件,服务器端渲染再次正常工作:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM