株式会社エフ・コードのクリエイター陣が送る、Webサービス開発改善ブログ。

  1. 既存プロジェクトのフロントエンドにHaxeを導入して、AltJSの素晴らしさを体感する

既存プロジェクトのフロントエンドにHaxeを導入して、AltJSの素晴らしさを体感する

2015年3月19日

フロントエンド制作担当のSnowです。

いまフロントエンド界隈で非常に熱い話題の一つにAltJSがあります。私もJavaScriptの直書きには色々不満を持っていたので、AltJSにはとても期待しています。

今回は代表的なAltJSである、Haxe(ヘックス)をご紹介してみたいと思います。 Haxeは2005年に登場しており、本ブログ公開時点ですでに10年の歴史があります。

Haxeを扱った記事はすでに多くあるのですが、JS以外にも書き出せる言語であるということもあり、Haxe専用プロジェクトを特定のIDEから立ち上げるような手法の紹介が多いようです。 しかしJava等サーバサイドのプロジェクトの中にフロントエンドのソースがある場合も多く、専用プロジェクトを立ち上げるのはあまり現実的でないと感じることもあります。

よって今回は、Haxeでない既存プロジェクトのフロントエンドにHaxeを導入し、なおかつコード補完など静的型付けの恩恵を受けられるようにしたいと思います。

~インデックス~

  • 前提:AltJSに期待することと、Haxeにした理由
  • 環境のインストール(FlashDevelop, Haxe, Grunt)
  • 既存ファイルにテンプレートを設置
  • FlashDevelopでプロジェクトを開く
  • Haxeのコーディング
  • JavaScriptにコンパイル

前提:AltJSに期待することと、Haxeにした理由

AltJSが話題になっているということは、JavaScriptに不満を持ち、素のJavaScriptを書きたくない人がたくさんいるのだと思いますが、 私自身はAltJSに次のような期待をしています。

  • IDEで自他ファイルの変数/関数宣言を参照してコード補完してほしい
  • 無難な方法でクラスを作ってほしい(人によって微妙に作り方が違うから)
  • ちょっとしたミスでグローバル汚染されるのを防ぎたい
  • 1ファイルあたりの行数を減らしたい(基本1クラス1ファイルにしたい)
  • 複数JSのファイル結合はしたくない(デバッグが難しくなるから)

上司からはTypeScriptをやれと言われたような気もしたのですが、 今回Haxeを選んだ理由は次の通りです。

  • Haxeのほうが1クラス1ファイルにしやすいらしい(=importがしやすい)
  • Haxeのほうが歴史と実績があるらしい
  • 私が元Flasher

最後の理由は、HaxeとFlashのActionScriptが非常に類似していることによります。 私はJavaScript歴よりActionScript歴が長いため、(私の)学習コストが非常に小さいというメリットがありました。

ただし弊社の他メンバーにそういったバックグラウンドは(おそらく)なく、TypeScriptのほうが既存JSの移植性が高いとも言われ、純粋なJSコーダーの方にとってはTypeScriptのほうが良いかもしれません。 というわけで後日TypeScriptも試してみたいと思います。

なお、HaxeはFlashやスマホのネイティブアプリにも書き出せるといった特徴もありますが、今回は基本的にJS書き出し専用として扱います。

環境のインストール(FlashDevelop, Haxe, Grunt)

早速、下記のソフトウェアをインストールしましょう。

FlashDevelop

もとはActionScriptでFlashを作るための日本製IDEです。Haxeのコード補間に対応しています。 Windows専用のフリーソフトなので、Mac等の場合はHaxeのコード補完に対応した他のIDEをご利用ください。

Haxe

Haxeコンパイラです。下記サイトのDownloadよりインストーラ版をダンロードし、実行するとインストールされます。

Grunt(grunt-cli)

フロントエンド作業で人気のあるタスクランナーです。Haxeのコンパイルを自動的にできるようにします。英語の公式サイトに行く意味はあまりないため、日本語で説明のある@ITの記事を紹介します。なおnode.jsのインストールが前提です。

HaxeやTypeScriptは静的型付け言語のため、IDEのコード補完を使えるようになります。 その代わりコード量が増えるので、書くならIDEがほぼ必須です。そのためAltJSの使い勝手はほとんどIDEで決まると言ってもいいのではないでしょうか。

なお、本ブログ執筆時点での私の環境は下記の通りです。

  • FlashDevelop 4.7.2.8 for .NET 2.0
  • Haxe 3.1.3
  • grunt-cli 0.1.13 (grunt本体は0.4.5)

Haxeインストール後にFlashDevelopを使うとどこかでコンパイラのパスを求められることがあります。 その際はhaxe.exeのあるフォルダを指定してください。

既存ファイルにテンプレートを設置

FlashDevelopから新規にJS向けHaxeプロジェクトを立ち上げることも可能ですが、 今回は普段運用しているプロジェクトにそのままHaxeを導入するため、次のテンプレートを用意しました。

※Google Chromeでダウンロードを行った場合、「一般的にダウンロードされておらず、危険を及ぼす可能性があります。」といった警告が表示されることがあります。

このテンプレートをダウンロードいただき、解凍したhaxeフォルダを普段のプロジェクトのフォルダ(特にJSを扱っているフォルダ)に入れます。

テンプレート(haxeフォルダ)をプロジェクトに入れた例

テンプレート(haxeフォルダ)をプロジェクトに入れた例

今回は仮のプロジェクトとして「HaxeTest」をAptana Studioで作成し、その直下のjsフォルダの中にテンプレートを入れました。 このHaxeTestは他に何も入っていないプロジェクトですが、すでに運用中のJavaやRailsのプロジェクトに設置して構いません。

FlashDevelopでプロジェクトを開く

こうして設置したhaxeフォルダをエクスプローラーで表示して(もくはIDE上で)、直下のhaxe.hxprojをクリックします。 するとFlashDevelopが起動し、haxeのプロジェクトが表示されます。

haxeのプロジェクトが表示されたFlashDevelop

haxeのプロジェクトが表示されたFlashDevelop

このスクリーンショットではProject Manager(フォルダツリーが表示されているところ)が左にありますが、初期状態では右かもしれません。 ドラッグ&ドロップで移動できるので、お好みで調整してくだい。

このhaxeフォルダ直下にあるsrcフォルダの中身がコンパイルされ、binフォルダにJSが書き出されます。 早速srcフォルダを開くとMain.hxがあり、開くと次のように表示されます。

FlashDevelopで開いたMain.hx

FlashDevelopで開いたMain.hx

authorにsnowと書かれていますが、これは私の名前なので、あなたの名前に書き換えてしまってください。

このMain.hxのmain関数が最初に実行されるようにJSに書き出されます。その設定はcompile.hxmlに書いてあります。

Main.hxは一旦このまま置いておいて、srcにクラスのファイルを追加します。srcフォルダ上で右クリックし、 「Add」 → 「New Class…」を選択します。

右クリックメニューからNew Class...をクリック

右クリックメニューから「New Class…」をクリック

New Haxe Classのウィンドウが表示されます。ここでPackageに「lib」、Nameに「MainController」と入力し、OKをクリックします。

New Haxe ClassのPackageとNameを入力

New Haxe ClassのPackageとNameを入力

するとlibフォルダと、その中にMainController.hxが生成されます。

libフォルダとMainController.hxが生成された

libフォルダとMainController.hxが生成された

Haxeのコーディング

生成したMainController.hxにHaxeのコードを書いてみましょう。

MainController.hxには、最終的に次のようなコードを書きます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package lib;
import js.Browser;
import js.JQuery;

/**
 * Mainの処理。
 * @author snow
 */
class MainController
{
    public var window:JQuery;
    public var body:JQuery;
    public var testDiv:JQuery;

    /**
     * コンストラクタ。
     */
    public function new() 
    {
        init();
    }
    /**
     * 初期化処理。
     */
    private function init():Void {
        window = new JQuery(Browser.window);
        window.on("load", function(e) {
            body = new JQuery("body");
            testDiv = new JQuery(".test");
            body.append("<p>" + (testDiv.length > 0 ? "あるよ" : "ないよ") + "</p>");
            testDiv.css({ "background" : "#ff0" });
        });
    }
}

1行目のpackage文はすでに書かれていますが、その下からすぐにimport~と入力し始めてはいけません。積極的に自動コード補完を利用します。

まずはnew()のすぐ下にprivate function init()と書きます。pri…と入力し始めたとき、早速候補にprivateが表示されます。

コード補完候補にprivateが表示された

コード補完候補にprivateが表示された

このような調子で入力できるため、非常に速くコーディングできるのはもちろん、瑣末なタイプミスも少なくなります。

また、body:JQueryinit():Voidのように、宣言の際にコロンを入れてを指定します。これにより、以降その変数や関数のプロパティやメソッドを余さず補完候補として表示できるようになります。 JQueryなどimportが必要なクラスについては、変数等を宣言した時点で自動的に上のimport文も追加されとても便利です。

HaxeはjQueryをサポートしていますが、$()関数が使えないため、色々と書き換えることになります。 セレクタでDOM要素を取得する場合はJQueryクラスのインスタンスを作り、そのコンストラクタにセレクタを書きます。 また、Windowのロード完了後に関数を呼び出す$(function(){});といった記述をよくすると思いますが、js.Browser.windowを参照し、そのloadイベントにハンドラを追加して対応します。 このような仕様により、最初はjQueryの扱いがやや難しいかもしれません。

今度はMain.hxです。こちらはシンプルに、先ほど作ったMainControllerを取り込むだけにしましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package;

import js.Lib;
import lib.MainController;

/**
 * ...
 * @author snow
 */
class Main 
{
    static var controller:MainController;
    static function main() 
    {
        controller = new MainController();
    }
}

インスタンスとするcontrollerを宣言する際、コロンの後にmain…と入力すると、先ほど作成したMainControllerがしっかりと補完候補に表示されます。

コード補完候補にMainControllerが表示された

コード補完候補に、自作クラスのMainControllerが表示された

このようにファイルを分割することで、長大で可読性の低いコードを保守する必要がなくなります。

JavaScriptにコンパイル

さて、そろそろJSにコンパイルして動作確認しましょう。

コンパイルの前に、binフォルダのindex.html周りを準備します。このindex.htmlはJSをテストするためだけのHTMLです。本番のWebサイトのHTMLである必要はありません。

今回のbin/index.htmlには次のように記述し、jquery.jsをbinフォルダに入れておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>main</title>
    <meta name="description" content="" />
</head>
<body>
    <script type="text/javascript" src="jquery.js"></script>
    <script src="main.js"></script>
    <div class="test"></div>
</body>
</html>

ここまでできたら、FlashDevelopの「Test Project」アイコンをクリックします。

FlashDevelopのTest Projectボタン

FlashDevelopのTest Projectアイコン

ブラウザが開き、うまく動作するとbinにmain.jsが生成されます。そしてどこかのTVドラマのように「test」クラスを持ったDIVタグの存在を知らせてくれます。

あるよ

あるよ

ここからHaxeのコードを編集した際は、先ほどクリックしたTest Projectの左隣にある歯車のアイコン「Build Project」をクリックすればJSが更新されます。 その後ブラウザを更新して再確認すれば良いのですが、コンパイラが高速とはいえ毎回毎回歯車をクリックするのは大変です。

そこでGruntを利用したいと思います。Gruntの設定ファイルは私のテンプレートに入っているので、コマンドプロンプトでhaxeフォルダに移動し、 下のコマンドを実行します。

1
grunt watch

すると、srcの~.hxファイルを編集し保存するたびに都度JSが書き出されます。これでかなり効率的になると思います。watchを終了するときはCtrl+Cを押してください。

FlashDevelopでテストせず本番のHTML上で動作するか確認する場合は、Test Projectをクリックせず直接grunt watchで問題ありません。本番のHTMLは、scriptタグでhaxe/binフォルダ内のJSを参照するようにしてください。

gruntのバージョンが合わない場合は、設定を適宜調整してください。

まとめ

いかがでしたでしょうか。

AltJSは魅力的で、おのおのの言語仕様も固まりつつありますが、現状はIDE選びなど環境整備が難しいと感じます。しかし確立した環境が出つつあるので、そろそろ積極的に利用したいところです。

もう一つの有力候補であるTypeScriptも含め、研究と実践を重ねたいと思います。引き続きよろしくお願いします。

Webフロントエンドを担当。6弦ベースでFコードは押さえられない。

ページトップへ