Edited at

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

More than 3 years have passed since last update.

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の方を使う方が楽です。


参考