服务端渲染

React 提供了两个方法 renderToString 和 renderToStaticMarkup 用来将组件输出成 HTML 字符串
这是 React 服务器端渲染的基础,它使 react.js 对于浏览器环境的依赖不在那么强烈,让服务端渲染不在是梦想。

为什么需要服务端渲?

前后端可以共享代码
前后端路由可以统一处理
对 SEO 友好

区别

renderToString        // 渲染的时候带有 data-reactid 属性
renderToStaticMarkup  //没有 data-reactid 属性,  html 字符

Basis

server.jsx

import express from 'express';
const app = express();
//导入输出组件
import { toReactHtml } from "./tostring";
app.use((req,res)=>{
	let html = toReactHtml({
		"title" : "world"
	});
	res.send(html);
});
app.listen(8000,"0.0.0.0",function(){
	console.log("open http://127.0.0.1");
});

tostring.jsx

import { renderToString } from 'react-dom/server';
//导入 app 组件
import { App } from "./app";
function layout(data){
	let content = renderToString(<App { ...data }/>);
	return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
    </head>
    <body>
      <div id="app">
          ${content}
      </div>
    </body>
    </html>
  `;
}

function toReactHtml(props){
	return layout(props || {});
}
export { toReactHtml };

app.jsx

import React, { Component } from "react";
class App extends Component{
	render(){
		return <h1>hello { this.props.title || "react.js" }</h1>;
	}
}
export { App };

webpack 编译配置

对 webpack 不熟悉请看 webpack 相关知识

var path = require("path");
var fs = require("fs");
var webpack = require("webpack");
var staticRoot = path.resolve(__dirname, "./src");
var outputPath = path.resolve(__dirname, "./output/");
var babelrc = JSON.parse(
    fs.readFileSync(path.resolve(__dirname, "./.babelrc"), 'utf8')
);

//排除编译
//过滤 node_modules 中的文件
var ext_NODE_MODULES = fs.readdirSync('node_modules').filter(function (dir) {
  return dir !== '.bin';
}).reduce(function (res, dir) {
  res[dir] = 'commonjs ' + dir;
  return res;
}, {});

module.exports = {
    entry: {
        server: `${staticRoot}/server`        //需要打包的文件
    },
    target: 'node',
    output: {
        path: outputPath,
        filename: '[name].build.js', 
        sourceMapFilename: '[file].map'
    },
    module: {
        loaders: [
            {
                test: /\.js[x]?$/,
                exclude: /node_modules/,
                loader: ['babel'],
                query: babelrc
            }
        ]
    },
    resolve: {
        root: [ staticRoot ],
        alias: [],
        extensions: ['', '.js', '.jsx'],
    },
    //排除编译
    externals: ext_NODE_MODULES,
    plugins: [
        new webpack.ProvidePlugin({
            'React': 'react',
            'ReactDOM': 'react-dom',
        })
    ]
};