迅雷下载宝官网使用 React + react-router + redux 构建,出于 SEO 考虑,决定使用 Node.js 搭建一套服务端渲染的环境(Universal app),在此记录遇到的问题和解决方案。
在 react 中,react 组件和渲染的概念已经分离出来了。比如从 v0.14 开始,最常用的浏览器端渲染 render()
方法分离到 react-dom
中,而在服务器端,我们想要得到的不是 DOM 对象,而是字符串形式而已,因此我们可以使用 renderToString()
方法,该方法位于 react-dom/server
中。正是因为这样的分离思路,react 才标榜自己 “learn once, use everywhere.”(虽然代码还不能完全复用)。
Node 环境没有 window
对象, window
下面的子对象包括 location
, navigator
等,直接在 node 环境使用会报错。
React-router 使用 browserHistory
代替 hashHistory
。
URL 中的 hash 部分不会发送到服务器,因此服务器端不能根据 hash 区分请求 URL,还好 react-router 支持 browserHistory + HTML5 history API 方式的路由。注意的是,组件的 <a>
标签需要使用 react-router 的 <Link>
标签代替,这样改变路由很方便。
Node.js v4 对 ES6 和 ES7 的支持还不全面(参见 https://nodejs.org/en/docs/es6
),因此需要使用 babel v6 对源码作转换,方法也很简单,在入口加一句 require('babel-core/register')
即可。
使用 Express 框架处理请求,注意区分开发模式和生产模式,开发模式需要引入 Webpack 中间件(见下文),生产模式对于静态资源直接读取磁盘文件。
其实服务器端加载可以不使用 Webpack,直接加载打包后的静态文件亦可,在这里为了开发环境的方便,也在服务器端引入了 Webpack。
Webpack 要在服务器端使用,需要用到下面三个库。
地址: https://github.com/halt-hammerzeit/webpack-isomorphic-tools
模仿了 Webpack 的 require()
方法,由于 Node.js 环境中本身不支持 require(‘../image.png’) 这样的用法,所以需要这个库提供支持。
地址: https://github.com/webpack/webpack-dev-middleware
Webpack 的一个包裹层中间件,注意仅在开发环境使用。用法参考项目 readme。
地址: https://github.com/glenjamin/webpack-hot-middleware
配合 webpack-dev-middleware 使用,目的是实现热加载。用法参考项目 readme。