UP | HOME

React & React Router 服务端渲染学习

吐槽下

发现 NodeJs 用 Es6 来写东西,是个大坑啊 !! 我死活不知道是哪里出问题了,NodeJs 愣是解析不到 JSX 了。

已经纠结了两个晚上了。

来babel 的世界一看, 我好像掉入了一片大海,左右看不到岸,任由风浪推着我到处飘摇。。。 记得上次出现这感觉,还是刚进入大学,学习 C 的时候,直到我遇到了Java。对啊,我是Java程序员啊,怎么混入JavaScript的世界了,赶紧写几行JavaScript压压惊 。。。

好了,现在从最简单的程序开始写起,一步一步来,看看到底哪一步出什么问题了,看看各种babel工具是干嘛的。

。。。(省略各种纠结的解决方案 ,ORZ。。。)

经过好久的纠结排查中,终于发现问题在 route的引用上。

React Router 配置的 route 是 jsx 的语法,在 node 环境中,引入该语法的文件,如果直接引用过来,会报语法异常,所以需要加上 babel-core 里面的 register 这个 hook 进行转换。

阮一峰的博客里面,有提及到这个 register , 但是他用的babel-register,而我使用 babel-core里面的register ,也可以成功跑起来。暂未知两个具体区别是什么。待之后探究。

目前最简单的一个 React Router 的服务端框架已经可以展现出来了。

基础的环境

packge.json:

{{
  "name": "react-router-startup",
  "description": "A Startup Devlopment Kit for React Router",
  "version": "1.0.0",
  "devDependencies": {
    "babel-cli": "^6.9.0",
    "babel-core": "^6.9.1",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.5.0",
    "babel-watch": "^2.0.2"
  },
  "dependencies": {
    "express": "^4.13.4",
    "react": "^15.1.0",
    "react-dom": "^15.1.0",
    "react-router": "^2.4.1",
    "swig": "^1.4.2"
  },
  "scripts": {
    "start": "babel-node app.js",
    "dev": "babel-watch app.js"
  }
}
  • babel-cli 里面有个 babel-node ,比较重要的工具。
  • babel-watch 动态监视文件变化
  • babel-preset-es2015 es2015转换
  • babel-preset-react react转换

app.js:

// Babel 6 Compile
require('babel-core/register')({
   presets: ['es2015', 'react']
});

import express from 'express';
import React from 'react';
import ReactDOM from 'react-dom/server';
import {match ,RouterContext} from 'react-router';
import swig from 'swig';
var route = require('./view/route'); //注意这一段怪怪的引用

const app = express();

//服务端渲染
app.use((req,res) => {
   match({routes:route.default , location:req.url},(error, redirectLocation, renderProps) => {
      if (error) {
         res.status(500).send(error.message)
      } else if (redirectLocation) {
         res.redirect(302, redirectLocation.pathname + redirectLocation.search)
      } else if (renderProps) {
         var html = ReactDOM.renderToString(React.createElement(RouterContext, renderProps));
         var page = swig.renderFile('template/index.html',{html:html});
         res.status(200).send(page);
      } else {
         res.status(404).send('Not found')
      }
   });
});

app.listen(3000,()=>{
   console.log('server running');
});

route.js:

import React from 'react';
import {Route} from 'react-router';
import App from './component/App';
import Home from './component/Home';
import Content from './component/Content';

export default (
    <Route component={App}>
        <Route path="/" component={Home}/>
        <Route path="/content" component={Content}/>
    </Route>
)

基础环境这样,用新语法去写,一切ok了。

当初试验写新语法,在撸PhotoHub时候,按照阿里前端的那篇文章,搬来了很多babel插件。现在测试了下,用这个方式,babel的插件一个没有用到,已经可以支持node使用新语法,以及服务端的渲染了。

全部代码已放入github,[传送门](https://github.com/ThinkCats/ReactRouterServerRender),希望能给同样在大海中漂泊的小白们带来点亮光。。。

一天晚上,整理了两篇文章,业已很困,酸奶和煤球都已经睡得呼呼了。