LoginSignup
9
8

More than 5 years have passed since last update.

Reactを書く際に複数のAltJSを混在させてみる

Last updated at Posted at 2015-03-28

GitHubへのリンク

概要

環境をバージョンアップしたことによりTypeScriptにreact-jadeを埋め込む処理がエラーが出るようになったため、外部ファイルのjadeテンプレートを利用する方法へ変更しています

これReactを使う際に複数のAltJS(TypeScript & CoffeeScript & Babel)を混在させるサンプルアプリケーションについての記事です。
AltJSを中間ファイルであるjsへと個別に吐きだし、Browserifyでbundleする事により対応しています。

各AltJSのReact対応について

※リンク先はgulp用のプラグイン

  • TypeScript
    • jsx構文を使えるトランスパイラがまだ無い為、react-jadeを利用してHTMLタグを記述しています。
      react-jadeのコードはBrowserifyでbundle時にreact-jadeプラグインによりES5のJSへとtransformされています。
  • CoffeeScript
    • jsx構文をサポートしたCoffeeScriptであるcoffee-reactを利用
  • Babel

実行結果

実行結果.png

コード

メインApp

app.cjsx
CoffeeReactClass      = require('./coffeereactclass').CoffeeReactClass
CoffeeReactMixinClass = require('./coffeereactmixinclass').CoffeeReactMixinClass
#TSClass               = require('./tsclass').TSClass
TSTmplClass           = require('./tsclass').TSCTmpllass
BabelClass            = require('./babelclass').BabelClass
BabelTmplClass        = require('./babeltmplclass').BabelTmplClass

App = React.createClass(
  render: () ->
    <div>
      <CoffeeReactClass      title="coffee-react" />
      <hr />
      <CoffeeReactMixinClass title="coffee-react" />
      <hr />
      <TSTmplClass           title="TypeScript" />
      <hr />
      <BabelClass            title="Babel" />
      <hr />
      <BabelTmplClass        title="Babel" />
    </div>
)

React.render(
  <App />,
  document.getElementById("app-container")
)

メインとなるAppではcoffee-reactを使用していますが、一番短く書けるからってだけで他の言語でも構いません。
ここから各言語で書かれたReactコンポーネントを表示しています、各コンポーネントにはそれぞれタイトルを渡し、各自で表示するように統一しています。


coffee-react

coffeereactclass.cjsx
CoffeeReactClass = React.createClass(
  render: () ->
    items = [
      "item1"
      "item2"
      "item3"
    ]

    <div>
      <h1>{this.props.title}</h1>
      <ul>
        {items.map((x, i) -> <li key={i}>{x}</li>)}
      </ul>
    </div>
)

module.exports.CoffeeReactClass = CoffeeReactClass

単に親からタイトルを受け取り、表示しています。


mixinを利用したcoffee-react

coffeereactmixinclass.cjsx
Mixin =
  render: () ->
    <div>
      <h1>{this.state.title}</h1>
      <ul>
        {this.state.items.map((x, i) -> <li key={i}>{x}</li>)}
      </ul>
    </div>


CoffeeReactMixinClass = React.createClass(
  mixins: [Mixin]
  getInitialState: () ->
    title: this.props.title + " (using mixin)"
    items: [
      "hoge"
      "fuga"
      "piyo"
    ]
)

module.exports.CoffeeReactMixinClass = CoffeeReactMixinClass

表示部分をMixinオブジェクトとして切り出した方法です。
ReactでViewとControllerが一緒くたになりがちですが、Mixinを利用してViewをMixinオブジェクトへと切り離す試みをしています。

この記事を書いた後に知った為このままですが、
実際はmixinはES6 class向けにサポートされない為、継承の方が良いです。


jadeテンプレートを埋め込んだTypeScript
外部ファイルのjadeテンプレートを利用したTypeScript

test-template.jade
h1= title
ul
  - for (var i = 0; i < items.length; ++i) {
    li(key=i)= items[i]
  - }
tstmplclass.ts
import React = require('react');
var tmpl = require('./test-template');

export var TSTmplClass = React.createClass({
  render: function() {
    var items = [
      "tom",
      "bob",
      "hiroshi"
    ];

    return tmpl({
      title: this.props.title + " (using jade template file)",
      items: items
    });
  }
});

jsx構文が書けない為、表示部分をreact-jadeで対応、View部分の切り離しも兼ねています。

jadeテンプレートは中間ファイルには残ったままになりますが、Browserifyでbundleする際に

b.transform('react-jade').bunde()

としてbundleファイルにJSコードへ変換されて埋め込まれるようにしています。
react-jadeのライブラリコードが埋め込まれて肥大化する懸念がありましたが、このコードの場合も、外部ファイルにする際もJSコードに変換して埋め込んでしまうので大丈夫でした。
Browserifyのバージョンを9.0.7に上げると、変換前のコードとreact-jadeのコードが埋め込まれて肥大化するようになりました、もしかしたら展開するオプションや方法があるかもしれませんが、jadeファイルに分割しておいた方が無難だと思います。
Node.js v5に上げると、react-jadeでエラーが出るようになったため、外部ファイルのjadeテンプレートを利用する方法へ変更しています。
ちなみに、TypeScriptでReactの型を扱うにはtyped-react等がありますが、自分の環境だと上手く動かなかった為今回は使用していません。


Babel

babelclass.js6(便宜上付けた独自拡張子)
export var BabelClass = React.createClass({

  render: function () {
    var items = [
      "suchi",
      "tempura",
      "fujiyama"
    ]

    return (
      <div>
        <h1>{this.props.title}</h1>
        <ul>
          {items.map(function(x, i) { return <li key={i}>{x}</li>; })}
        </ul>
      </div>
    )
  }
})

こちらも単に親からタイトルを受け取り、表示しています。


外部ファイルのjadeテンプレートを利用したBabel

test-template.jade
h1= title
ul
  - for (var i = 0; i < items.length; ++i) {
    li(key=i)= items[i]
  - }
babeltmplclass.js6
import tmpl from './test-template'

export var BabelTmplClass = React.createClass({
  render: function () {
    var items = [
      "tendon",
      "katudon",
      "puteranodon"
    ]

    return tmpl({
      title: this.props.title + " (using jade template file)",
      items: items
    });
  }
})

テンプレートエンジンであるreact-jadeを利用して、Viewを切り離しています。
新たにjadeを覚える必要がありますが、mixinよりはこちらの方が正攻法だと思います。

まとめ

基本的に、言語ごとに出来る事に違いはありません、TypeScriptだけreact-jadeの使用を強いられますが(無くても書けるけど、辛い)複数のAltJSを混在させられる為、その都度やりやすい言語を選べば良いと思います。

備考

gulp-react-jadeについて

gulpにてjadeテンプレートファイルをjsに変換する際は、本家のgulp-react-jadeを利用し、独自にBrowserify用のヘッダ文字列付与を施しています。
個人的に本家版を使いたかったってだけで、
pugjs/react-jadeを利用した自作のgulpプラグインを利用していますが、通常はmizchiさんのmizchi/gulp-react-jadeの方を使う方が楽です。

参考

9
8
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8