所谓同构,简单的说就是客户端的代码能够在服务端运行,好处就是能极大的提高首屏时间,避免白屏,另外同构也给SEO提供了不少便利。css
React 同构得益于 React 的虚拟 DOM。虚拟 DOM 以对象树的形式保存在内存中,并存在先后端两种展示形式。html
在服务端经过 ReactDOMServer.renderToString 方法将虚拟 DOM 渲染为 HTML 字符串,到客户端时,React 只须要作一些事件绑定等操做就能够了。node
在这一整套流程中,保证 DOM 结构的一致性是相当重要的一点。 React 经过 data-react-checksum
来检测一致性,即在服务端产生 HTML 字符串的时候会额外的计算一个 data-react-checksum
值,客户端会对这个值进行校验,若是与客户端计算的值一致,则 React 只会进行事件绑定,若是不一致,React 会丢弃服务端返回的 dom 结构从新渲染。react
React 新版本中已经在推荐采用 ES6/7 开发组件了,所以服务端对 ES6/7 的支持也不得不跟上咱们开发组件的步伐。可是如今 node 原生对 ES6/7 的支持还比较弱,这个时候咱们就须要借助于 babel 来完成 ES6/7 到 ES5 的转换。这一转换,咱们经过 babel-register 来完成。webpack
babel-register 经过绑定 require 函数的方式(require hook),在 require jsx 以及使用 ES6/7 编写的 js 文件时,使用 babel 转换语法,所以,应该在任何 jsx 代码执行前,执行 require('babel-register')(config),同时经过配置项config,配置babel语法等级、插件等。git
这里咱们给一个配置 demo, 具体配置方法可参看官方文档。es6
{ "presets": ["react", "es2015", "stage-0"], "plugins": [ "transform-runtime", "add-module-exports", "transform-decorators-legacy", "transform-react-display-name" ], "env": { "development": { "plugins": [ "typecheck", ["react-transform", { "transforms": [{ "transform": "react-transform-catch-errors", "imports": ["react", "redbox-react"], "locals": ["module"] } ] }] ] } } }
通常状况来讲,不须要服务端处理非js文件,可是若是直接在服务端 require 一个非 js 文件的话会报错,由于 require 函数不认识非 js 文件,这时候咱们须要作以下处理, 已样式文件为例:github
var Module = require('module'); Module._extensions['.less'] = function(module, fn) { return ''; }; Module._extensions['.css'] = function(module, fn) { return ''; };
具体原理能够参考require 解读web
或者直接在 babel-register
中配置忽略规则:json
require("babel-register")({ ignore: /(\.css|\.less)$/, });
可是,若是项目中使用了 css_modules 的话,那服务端就必需要处理 less 等文件了。为了解决这个问题,须要一个额外的工具 webpack-isomorphic-tools,帮助识别 less 等文件。
简单地说,webpack-isomorphic-tools,完成了两件事:
客户端的代码经过配置 webpack 打包发布到 CDN 便可。
经过配置 webpack 和 webpack-isomorphic-tools 将非 js 文件打包成 assets 文件便可。