使用ReactJS + Node實現伺服器端響應渲染

banq發表於2015-01-10
客戶端Javascript驅動的MVC如angular, ember, backbone等的問題是比較慢,使用者體驗差,同時對搜尋引擎不友好,因此,J業界開始實現Javacript的伺服器端渲染。

前段時間Ember.js剛推出FastBoot,見這裡,並且這幾天緊鑼密鼓加緊推進中:INSIDE FASTBOOT: FAKING THE DOM IN NODE.JS

而同時ReactJS已經推出在Node.js + React 同構渲染的演示:

Serverside React Rendering: Isomorphic JavaScript

這個案例是一個普通分頁批次查詢的案例,如下圖:

[img index=1]

點按圖中的id或name等表格名,能夠實現大小排序,頁面下有分頁符,透過檢視Html原始碼,表格中資料是以普通html的table格式輸出,但是點按分頁的下一頁,再檢視html原始碼,還是第一頁的內容,這就與普通使用Jsp或PHP/ASP等伺服器端渲染區別所在,後者每切換一個頁面實際是從伺服器端再拉取一個新的頁面內容,而新式的JS伺服器端渲染技術是第一頁如同JS/PHP/ASP,一旦輸出渲染成功,頁面各種效果包括切換到下一頁都是由第一頁的JS全面掌管,這時如同傳統AngularJS等客戶端Javascript驅動渲染頁面一樣,由AngularJS實時修改當前頁面的DOM。

這種伺服器端和客戶端同構Isomorphic JavaScript 技術的好處是:
1.更好的使用者體驗,載入頁面快
2.搜尋引擎友好,利於SEO
3.易於維護
4.自由逐步增強。

這個程式碼演示下載後,執行node server.js後,瀏覽器瀏覽127.0.0.1:4444可以得到如上圖效果。

看看 server.js主要程式碼:

/** @jsx React.DOM */

var React = require('react/addons');

/* create factory with griddle component */
var Griddle = React.createFactory(require('griddle-react'));

var fakeData = require('../data/fakeData.js').fakeData;
var columnMeta = require('../data/columnMeta.js').columnMeta;
var resultsPerPage = 100;

var ReactApp = React.createClass({

      componentDidMount: function () {
        console.log(fakeData);

      },

      render: function () {

        return (
          <div id="table-area">

             <Griddle results={fakeData} columnMetadata={columnMeta} resultsPerPage={resultsPerPage} tableClassName="table"/>

          </div>
        )
      }

  });

/* Module.exports instead of normal dom mounting */
module.exports.ReactApp = ReactApp;
/* Normal mounting happens inside of /main.js and is bundled with browerify */
<p class="indent">


這段程式碼建立了一個ReactApp模組功能,其功能主要是輸出表格內容,內容資料在fakeData.js中,表格表頭標題資料在columnMeta.js中。

當前端瀏覽器訪問127.0.0.1:4444/時,請求發往埠路由/app/routes/coreRoutes.js:

var React = require('react/addons');
var ReactApp = React.createFactory(require('../components/ReactApp').ReactApp);

module.exports = function(app) {

    app.get('/', function(req, res){
        // React.renderToString 將前面的模組元件ReactApp
        //作為輸入,輸出產生markup
        var reactHtml = React.renderToString(ReactApp({}));
        // ReactApp輸出內容輸出到index.ejs的變數reactOutput處
        res.render('index.ejs', {reactOutput: reactHtml});
    });

};
<p class="indent">


這個路由的功能是直接將ReactApp輸出內容輸出到index.ejs的變數reactOutput處,index.ejs相當於我們以前的index.htm或index.jsp/index.php等:

<!doctype html>
<html>
  <head>
    <title>React Isomorphic Server Side Rendering Example</title>
    <link href='/styles.css' rel="stylesheet">
  </head>
  <body>
    <h1 id="main-title">React Isomorphic Server Side Rendering Example</h1>
    <!-- reactOutput變數輸出在這裡,它是伺服器端React Dom節點-->
    <div id="react-main-mount">
      <%- reactOutput %>
    </div>

    <!-- comment out main.js to ONLY see server side rendering -->
    


  </body>
</html>
<p class="indent">

index.ejs中的 <%- reactOutput %>變數類似JSP中的<%=reactOutput %>,這個reactOutput 是模組元件ReactApp({})的輸出。

一旦index.ejs輸出到瀏覽器,就形成了上圖的效果,然後/main.js應該掌管了整個頁面以後的流程,使用者在頁面上點按排序和分頁都是main.js實現即時動態渲染,頁面網址不再變化,類似傳統的AngularJS效果。


相關文章