React+Webpack 前后端同构(服务端渲染)实践篇
杰拉斯 | 时间:2016-09-10, Sat | 19,512 views前端开发, 后台技术
前言
聊完理论(详见:《React+Webpack 前后端同构(服务端渲染)理论篇》),我们来看看如何把前后端同构运用到实践中。
服务端渲染
react-dom
模块中,包含了两个服务端渲染相关的两个方法:
renderToString
:将 React 元素渲染为 HTML 字符串,同时为每一个节点带上data-react-id
,而在浏览器端渲染的时候,React 不会重新渲染 DOM 树,而只是单纯为元素添加事件,这就是为什么 React 能够做到高性能的首屏渲染。renderToStaticMarkup
:同样将 React 元素渲染为 HTML 字符串,但不带data-react-id
,产生的 HTML 字符串长度更小,适合只在服务端做渲染的页面中使用,这时候 React 的功能相当于一个模板引擎。
为服务端实现 require
魔法
上一篇我们提到过,我们可以通过 Webpack 加载器将样式、图片等前端资源作为模块进行引入,但这些资源如果在 Node 中直接引入,是会报错的,因此,我们需要借助 webpack-isomophic 模块来消除前后端 require
函数的差异。
前端部分
在 webpack.config.js
中,配置 webpack-isomorphic
插件:
var IsomorphicPlugin = require('webpack-isomorphic/plugin');
// 配置需要同构的文件后缀名
var isomorphicPlugin = new IsomorphicPlugin({
extensions: ['jpg', 'png', 'gif', 'css']
});
module.exports = {
// 配置源文件目录
context: __dirname + '/src',
// ...
plugins: [
//...
isomorphicPlugin
]
};
服务端部分
var webpackIsomorphic = require('webpack-isomorphic');
// 配置构建后的文件目录
webpackIsomorphic.install(__dirname + '/dist', {
cache: process.env['NODE_ENV'] !== 'development'
});
不得不说 webpack-isomorphic
的使用确实非常的简单方便。
前后端数据同步
前面提到,React 在浏览器端,如果 virtual DOM 的渲染结果与服务端一致,则不需要重新渲染 DOM 树,因此前端的数据也应该与服务端保持一致,那么前端如何得到服务端的数据呢?方法也很简单,向浏览器输出 HTML 的时候,同时把数据以 JSON 的格式置于 <script>
标签中,输出至浏览器。
服务端
输出页面 HTML 时,同时带上原始数据:
var initialData = {foo: 'bar'};
var viewsDir = path.join(__dirname, './views/dist');
var template = path.join(viewsDir, 'index.tpl');
var reactClass = path.join(viewsDir, 'js/index.js');
var factory = React.createFactory(require(reactClass));
gotpl.renderFile(template, {
initialData: initialData,
initialHTML: ReactDOMServer.renderToString(factory(initialData))
}, function (err, html) {
if (err) {
res.end(err.stack);
} else {
res.end(html)
}
});
HTML模板
将原始数据置于 <script>
标签中,并赋值给 window.initialData
:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React+Webpack 前后端同构</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="root"><%- initialHTML %></div>
<script>window.initialData = <%- JSON.stringify(initialData) %>;</script>
<script src="index.js"></script>
</body>
</html>
JSX 文件
判断是否浏览器环境,若是,将 window.initialData
作为数据进行渲染:
// ...
if (typeof window !== 'undefined') {
ReactDOM.render(
React.createElement(IndexPage, initialData),
document.getElementById('root')
);
}
搞定,Demo 详见:webpack-isomorphic-example。
结语
最后说点不那么相关的题外话,前几天面试一个人的时候,面试者说:『现在前端发展太快了,都不知道要学什么,从哪学起了。』确实,互联网发展速度飞快,前端作为其中重要的一环,发展更是日新月异。语言上有了 HTML5,CSS3,ES6,TypeScript;框架上 React,Vue.js,Angular 方兴未艾;工具上 Grunt,Gulp,FIS3;模块管理上 RequireJS,SeaJS,Browserify,Webpack;服务端 Express,koa,koa2。。。
那到底要怎样去学习,才能更上这个时代的脚步呢?其实,技术是永远学不完的,面对这么多新兴的技术,大部分我们只需要做到初步的了解就够了,了解它们的特性,了解他们的应用场景,学习成本,这是视野的广度。然后在其中选择一小部分适用于当前学习或工作场景的,去实践,去探究,拓展技术的深度。不可一业不专,不可只专一业——一个什么都会一些,但什么都做不好的人,其实是没有核心价值的。
这里顺便安利一个 React 实现前后端同构的网站:哔卟TV,一个专注于 LOL 的直播聚合平台,做的很用心,LOLer 的福音。
如需转载请注明出处:杰拉斯的博客
确实学不过来… 前端框架现在是五代十国
网站很干净
大学时候的设计了。。没有好好兼容移动端= =
这个评论做得很新颖啊
博主代码高亮用的什么插件?
Google Code Prettify
很棒