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で配置してあげる必要があります。
ラベル:
javascript,
jsx,
php,
symfony2