服务端渲染react+mobx+webpack+express实战(同时也支持客户端渲染)

目前绝大多数网站仍是一个多页的结构,但其实一个网站已经彻底能够作成一个spa,好比youtube就是一个spa,最近公司项目都是采用react+mobx服务端渲染的单页面应用的形式,踩了一些坑,有一些本身的体验,因此把项目抽了出来去掉了业务代码,留了一个架子分享一下。前端

项目github地址react

目前react主流的状态管理使用的比较多的是redux,我司以前有个项目也是react+redux,从我我的使用下来的感觉来讲,对于绝大多数的前端应用场景,mobx远比redux更合适,更简单使用,更容易上手。git

效果

登录,注册

登录

添加item到列表中

列表

若是路由中没有的页面,处理404

图片描述

如何使用

git clone git@github.com:L-x-C/isomorphic-react-with-mobx.git
cd isomorphic-react-with-mobx
npm install

Dev (客户端渲染)

npm start
open http://localhost:3000

Production (服务端渲染)

npm run server
open http://localhost:20000

一些常常会遇到的状况

如何在服务端获取数据?

在每一个component中增长一个onEnter,用一个promise来处理,在这个promise中发起一个action,改变mobx中的states值github

@action
static onEnter({states, pathname, query, params}) {
    return Promise.all([
      menuActions.setTDK(states, '列表'),
      jobActions.fetchJobList(states, query)
    ]);
}

之因此能这么作,是由于在serverRender中有一个onEnter的预处理,会根据component的嵌套从最外层一直遍历到最里层的onEnter,并执行其中的的方法npm

import async from 'async';

export default (renderProps, states) => {
  const params = renderProps.params;
  const query = renderProps.location.query;
  const pathname = renderProps.location.pathname;

  let onEnterArr = renderProps.components.filter(c => c.onEnter);
  return new Promise((resolve, reject) => {
    async.eachOfSeries(onEnterArr, function(c, key, callback) {
      let enterFn = c.onEnter({states, query, params, pathname});
      if (enterFn) {
        enterFn.then(res => {
          if (res) {
            //处理Promise回调执行,好比登录
            res.forEach((fn) => {
              if (Object.prototype.toString.call(fn) === '[object Function]') {
                fn();
              }
            });
          }

          if (key === (onEnterArr.length - 1)) {
            resolve();
          }

          callback();
        }).catch(err => {
          reject(err);
        });
      } else {
        callback();
      }
    });
  });
};

如何在服务端设置tdk(title, description, keywords)?

这其实在上一个问题中就已经出现了,onEnter中有一个setTDK(states, t, d, k)的方法,使用他就能够设置tdk的值redux

如何在服务端进行跳转?

在浏览器环境中,咱们能够设置window.location.href = url来进行跳转。
可是在服务器环境中,并无window和document这2个对象,因此咱们在服务器环境中抛出一个异常,而后捕获到以后进行302跳转。
具体能够看src/helpers/location.js, 中的redirect function
他会自动判断当前环境,来选择使用哪种跳转promise

import {redirect} from './helpers/location';

@action
static onEnter({states, query, params}) {
    redirect('http://www.xxx.com');
}

mobx的原理及使用就不在这里作详细的介绍了,网上搜一搜有不少。
我相信咱们所采用的一些方法也许并非最完美的解法,若是有更好的欢迎来github中提issue探讨交流,互相学习~项目地址在此浏览器

相关文章
相关标签/搜索