所謂同構,簡單的說就是客戶端的代碼能夠在服務端運行,好處就是能極大的提高首屏時間,避免白屏,另外同構也給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 文件便可。