54sword / xiaoduyu.com

🐟小度鱼 - 年轻人的交流社区 https://www.xiaoduyu.com
598 stars 148 forks source link

服务端渲染问题 #15

Closed hechuanhua closed 6 years ago

hechuanhua commented 7 years ago

e12c6eca-d8f4-45e6-af16-32937f2482e3 这个估计是版本问题,反正页面一直是显示加载中,页面一直没有请求

还有我看你服务端渲染代码,貌似只支持一个组件一个请求?如果一个组件有多个2个请求,要在2个请求全部加载完成在返回渲染这个时候怎么弄?

function getReduxPromise(props, store, userinfo, callback) {
  console.log(props)
  let comp = props.components[props.components.length - 1].WrappedComponent;
  comp = comp.defaultProps.component

  if (comp.loadData) {

    if (process.env.NODE_ENV == 'development') console.log('获取数据')

    comp.loadData({ store, props, userinfo }, (notFound)=>{
      if (process.env.NODE_ENV == 'development') console.log('获取成功')
      callback(notFound)
    })

  } else {
    callback()
  }

}
54sword commented 7 years ago

我是按页面处理,一个页面有一个comp.loadData方法,是处理首屏需要在服务端加载的数据,而在loadData方法里面处理具体的请求,一个请求或多个请求都可以,请求结束后,回调结果

简单代码例子:https://github.com/54sword/xiaoduyu.com/blob/master/src/containers/topics/index.js

loadTopics 为redux的请求数据的方法,如下代码这里有两次请求,第一次是获取父话题,第二次请求是获取子话题

static loadData(option, callback) {
  // 登录的用户,不服务端加载
  if (option.userinfo) {
    callback(null)
  } else {
    const tag = option.props.location.query.tag || ''

    option.store.dispatch(loadTopics({
      name: 'parent-node-list',
      filters: {child:-1},
      callback: (res)=>{

        option.store.dispatch(loadTopics({
          name: 'node-' + tag,
          filters: { child:1, parent_id: tag },
          callback: (res)=>{
            callback(res.success ? null : true)
          }
        }))

      }
    }))
  }
}

上面的错误是 React 15.5.0 的版本问题,在最新的代码已换成最新书写方式 1、props-types 替换掉 react 自带的PropsTypes 2、去掉了 React.createClass,基本也很少使用它

但警告依然还...打包后就不显示了

hechuanhua commented 7 years ago

@54sword 你这个请求貌似不是异步的吧,你的第二个请求必须等第一个请求完成才能发出,如果是2个请求一起发起的呢

54sword commented 7 years ago

嗯,不是异步。 如果要同时发出请求的话,也是有方法处理 大概思路:两次请求完成后都回调同一个方法,然后在那个方法里面,否判断数据是否完整加载,最后再回调callback

(你这个问题提的不错,如果多个请求的话,异步请求处理一下,应该可以提高一些首屏的加载速度)

hechuanhua commented 7 years ago

@54sword WrappedComponent .defaultProps.component 这里的都是一些什么函数?你新增的API还是你自定义的属性?

54sword commented 7 years ago

是 react-router 的 match 方法返回的对象里面的属性,renderProps 是需要渲染的内容,其中 components 属性是需要被渲染的组件,从这里可以获取到页面的组件

match({ routes, location: req.originalUrl }, (error, redirectLocation, renderProps) => {}

hechuanhua commented 7 years ago

@54sword renderProps 是需要渲染的内容,其中 components 属性是需要被渲染的组件 但是如果是components组件里面包含了一些小组件,这个时候小组件也要发送请求,你这个components貌似只能获取到第一级的组件?获取不到小组件

54sword commented 7 years ago

如果要获取子组件的话,需要router页面组件的defaultProps添加上子组件对象, 这样就可以获取到子组件了,例如

Home.defaultProps = {
  componentPostsList: componentPostsList
}
hechuanhua commented 7 years ago

貌似首页列表没有服务端渲染

54sword commented 7 years ago

你应该是登录用户吧 我这里设置了逻辑,如果是未登录的用户,走服务端渲染。 如果是已登录的用户,那么走客户端渲染。

hechuanhua commented 7 years ago

我看你API接口写的是get('/topics'),但是接口是请求的是/api/v1/topic,你是吧接口代码放在API目录下面了还是通过nginx代理映射的?

54sword commented 7 years ago

@hechuanhua express 就可以设置,例如 app.use('/api/v1', API_V1());

hechuanhua commented 7 years ago

@54sword 二级域名和一级域名可以都绑定80端口吗?我为什么只能一个生效

54sword commented 7 years ago

@hechuanhua 使用nginx,增加server配置,监听80端口,然后根据 server_name 代理到不同端口 简单例子如下

#一级域名
server {
  listen       80;
  server_name www.domain.com domain.com;
  location / {
    proxy_pass http://127.0.0.1:81;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
  }
}

#二级域名
server {
  listen       80;
  server_name a.domain.com;
  location / {
    proxy_pass http://127.0.0.1:82;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
  }
}