JSXをSymfony2のAsseticで自動的にコンパイルする

2012年6月4日月曜日 投稿者 森怜峰

JSXをSymfony2のAsseticで自動コンパイルしてみますよ。

AsseticはAssetにフィルタを適応する仕組みです。今回はJSXのコンパイル処理をAsseticで自動的にコンパイルしてみます。

まずは、JSX本体の準備

git clone http://github.com/jsx/JSX.git

node.jsが入っていなければインストール

brew install node.js

npm(node package manager)が入っていなければインストール

curl http://npmjs.org/install.sh | sudo sh

それか

brew install npm

JSXのソースをコンパイルして実行してみる

cd JSX
./bin/jsx --executable --output hello.js example/hello.jsx
node hello.js
Hello, world!

 

Symfony2側の用意

Symfony2側のAsseticフィルタクラスの追加

JSX用のフィルタクラス追加します。ここに、vendor/assetic/src/Assetic/Filter/JsxFilter.php を下記内容で追加。

namespace Assetic\Filter;

use Assetic\Asset\AssetInterface;
use Assetic\Util\ProcessBuilder;

/**
 * Compiles JSX into Javascript.
 *
 */
class JsxFilter implements FilterInterface
{
  private $jsxPath;

  public function __construct($jsxPath = '/usr/bin/jsx')
  {
    $this->jsxPath = $jsxPath;
  }

  public function filterLoad(AssetInterface $asset)
  {
    $input = tempnam(sys_get_temp_dir(), 'assetic_jsx');
    file_put_contents($input, $asset->getContent());

    $pb = new ProcessBuilder();
    $pb
      ->inheritEnvironmentVariables()
      ->add($this->jsxPath)
      ->add($asset->getSourceRoot() . DIRECTORY_SEPARATOR . $asset->getSourcePath())
    ;

    $proc = $pb->getProcess();

    $code = $proc->run();
    unlink($input);

    if (0 < $code) {
      throw new \RuntimeException($proc->getErrorOutput());
    }


    $asset->setContent(str_replace($asset->getSourceRoot(), "", $proc->getOutput()));
  }

  public function filterDump(AssetInterface $asset)
  {
  }
}

 

次に、DIコンテナの設定をします

/Users/morireo/Sites/fotofoo_mobile/vendor/bundles/Symfony/Bundle/AsseticBundle/Resources/config/filters/jsx.xml ファイルを編集。

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <parameters>
        <parameter key="assetic.filter.jsx.class">Assetic\Filter\JsxFilter</parameter>
        <parameter key="assetic.filter.jsx.bin">/usr/bin/jsx</parameter>
    </parameters>

    <services>
        <service id="assetic.filter.jsx" class="%assetic.filter.jsx.class%">
            <tag name="assetic.filter" alias="jsx" />
            <argument>%assetic.filter.jsx.bin%</argument>
        </service>
    </services>
</container>

app/config/config.ymlにフィルタ設定の記述

assetic:
    filters:
        jsx:
            jsx_path: /usr/bin/jsx

JSXクラスの記述

Resources/public/jsx/hello.jsx などに書きます

import "js/web.jsx";

class _Main {
  static function main(args : string[]) :void {
    log "Hello, world!";
  }

  static function say() : void {
    var text = dom.window.document.createTextNode("Hello, world!");
    dom.getElementById("hello").appendChild(text);
  }
}

Twigに記述

<html>
<head>
  <title></title>
  {% javascripts debug=true output="/js/hello.js" '@JsxTestBundle/Resources/public/jsx/hello.jsx' filter='jsx' %}
  <script src="{{ asset_url }}"></script>
  {% endjavascripts %}
</head>
<body>

<p id="hello"></p>

<script>
  window.addEventListener("load", function(e) {
    JSX.require("/Resources/public/jsx/hello.jsx")._Main.say$();
  });
</script>

</body>
</html>

これで自動的に.jsxファイルが.jsファイルになってブラウザ上で動作するようになりました。

静的ファイルとして配置するには、./app/console assetic:dump コマンドで web/ 以下に配置されます。プロダクション環境では自動的に再生成されないので、ソースファイルを変更した場合には削除するかassetic:dumpで配置してあげる必要があります。

ラベル: , , ,

コメントを投稿