読者です 読者をやめる 読者になる 読者になる

UTALI

書き溜めておいた技術記事や旅行記のバックアップです。

Reactのサーバーサイドレンダリングについて

少々学習コストは高いものの、非常に保守しやすいスッキリしたロジックを書くことができるので、僕はReactを愛用しています。現在、ExpressアプリのレンダリングエンジンとしてECTを利用しているのですが、HTMLに直接コードを埋め込むという古臭いやり方に少し嫌気が差してきました。

そこでReactをサーバーサイドで利用できないかと色々調べてみたら大して難しくないようなので、Reactをサーバーサイドでレンダリングエンジンとして利用したいと思います。

すでに作成済みのexpressのプロジェクトファイルを開いてメインのフォルダに移動します。そして必要なパッケージのreactexpress-react-viewsをインストールします。

sudo npm install react express-react-views --save

無事にインストールが完了したならば次にapp.jsを編集します。 最初にReactをExpressサーバーで利用する ためのパッケージexpress-react-viewsを読み込みます。

var reactViews = require('express-react-views');

続き

app.set('view engine', 'jsx');

app.engine('jsx', reactViews.createEngine());

このように書き換えることによってレンダリングエンジンがjsxに変更されます。

ここでapp.jsの編集は終わりです。

次にviewsをjsxファイルに置き換えます。

ここでカギになるのはpropsの扱いです。Reactではコンポーネントに与えられる変数の初期値としてpropsを利用します。問題はサーバーサイドでレンダリングされるときにどのようにpropsに値を渡すかです。Expressではレンダリングの際に変数を以下のような形式で渡します。

res.render('index', { title: 'Express'})

これについて説明するとindexというひな形ファイルのtitle変数に"Express"という文字列を渡しているわけです。

実はReactではこのように渡された変数がpropsの変数として自動的に格納されます。

つまり、ここで渡された変数はthis.props.titleとしてアクセスすることができるわけです。このことを覚えておけば、コンポーネントを書くときに混乱せずに済むと思います。

それではindex.jsxファイルを書いてみましょう。

var React = require('react');

var Index = React.createClass({

  propTypes: {

    title: React.PropTypes.string

  },



  render: function() {

    return (

<html>

<head>

<title>{this.props.title}

 </title>

</head>

<body>

        <h1>{this.props.title}</h1>

</body>

</html>

    );

  }

});



module.exports = Index;

順を追って説明していきましょう。まず最初にReactのモジュールを読み込みます。これがなければ何もできません。

var React = require('react');

次にクラスを宣言します。クラスはReactでビューを組み立てる基本的なパーツですね。

var Index = React.createClass({

ここは特に書く必要もないのですが、一応念のため、titleを文字列型に限定しています。

  propTypes: {

    title: React.PropTypes.string

  },

実際にレンダリングされるHTMLファイルです。Reactの用語を使えばコンポーネントですね。注意して欲しいのは必ずHTMLとして1つに閉じることです。

  render: function() {
    return (
      <Layout title={this.props.title}>
        <h1>{this.props.title}</h1>
        <p>Welcome to {this.props.title}</p>
        <p>
          I can count to 10:
          {countTo(10)}
        </p>
      </Layout>
    );
  }
});

最後に外部から利用出来るようにexportsに格納します。

module.exports = Index;

問題:やっぱりECTに比べると遅い