読者です 読者をやめる 読者になる 読者になる

Jasyプロジェクトを作成する

Zynga JavaScript Python

前提条件

Python 3.2とpip、それにJasy 0.4.6がインストールされているものとします。

$ pip install https://github.com/wpbasti/jasy/zipball/0.4.6

ディレクトリ構成

最初にプロジェクトのトップディレクトリを作る。ここでは設定ファイルに記載するプロジェクト名にあわせてmyprojとした。git initは任意だが、coreがないとJasyアプリケーションは実行できないので、git submoduleとして参照しておくと便利。もちろんダウンロードして自分のレポジトリ内に含めてしまったり、hg等の別のVCSの方が好みならばgit submoduleに相当する手段で参照しても可。

$ mkdir myproj
$ cd myproj
$ git init

sourceというディレクトリを作り、さらにその下にclassとassetというディレクトリを作る。class以下がJavaScriptファイルの置き場所で、assetが画像ファイルやCSSファイルの置き場所。ディレクトリ名はsource/class, source/assetそのままを推奨。これはこのディレクトリ名がJasyが期待しているディレクトリ名であるということによる。

$ mkdir -p source/{class,asset}

最初に述べたようにCoreに依存しているので、external/coreというディレクトリにセバスチャンのgithubレポジトリへの参照を張った。このexternal/coreというパスに関しては後に述べるjasyscript.pyの中の設定を変えれば変更可。

$ git submodule add git://github.com/wpbasti/core.git external/core
$ cd external/core
$ git checkout 0.3.1 # 重要!!

重要な点としてはcoreのmasterは今のところ動かないので、0.3.1というタグが打ってあるバージョンを使うこと。submoduleではなくて0.3.1のzipを拾ってきたほうがよいかも。

次に、jasyproject.jsonというJSONファイルをプロジェクトのトップディレクトリに作り、nameにプロジェクト名を記述する。ここではmyprojとした。この名称は後々JavaScriptモジュール、クラスを定義していく際に、myproj.module1.Modelのような名前空間に使うので、org.example.my.great.appみたいな長い名称を付けると、コーディングの手間になるばかりかJavaScript実行時のパフォーマンスにも影響が出ると思う。短めでドットを含まないものが良いと思う。

{
    "name": "myproj"
}

ここまでのディレクトリ構成を示す。

.
├── external
│  └── core
├── jasyproject.json
└── sou
    ├── asset
    └── class

HTML

source/index.htmlに以下のようなHTMLを追加。

<!DOCTYPE HTML>
<html>
<head>
  <title>My First Jasy App</title>
</head>
<body>
  <h1>Hello Jasy</h1>
  <div id="content"></div>
  <script type="text/javascript" src="loader.js"></script>
  <script type="text/javascript">core.io.Script.load("myproj-" + core.Env.CHECKSUM + ".js");</script>
</body>
</html>

何の変哲もないHTMLファイルだが、scriptの部分だけに関してポイントを述べると、

  • loader.jsというのがアプリ起動に最小限必要なbootstrapコード
    • loader.jsはJasyで自動生成される。
    • 後に述べるjasyscript.pyの中で変更すればloader.jsでなくても可。
  • core.io.Script.loadでアプリケーションの実体のスクリプトを読み込む。
    • この実体スクリプトはJasyで自動生成される。

JavaScript

source/class/App.jsに以下のようなJavaScriptを追加。

core.Class('myproj.App', {
    construct: function() {
        alert("Hello Jasy");
    }
});

jasyscript.py

プロジェクトのトップディレクトリにjasyscript.pyという名前で以下のようなPython3スクリプトを作る。

#!/usr/bin/env jasy

def getSession():
    session = Session()

    # 依存しているJasyプロジェクトのディレクトリを指定
    session.addProject(Project("external/core/"))
    session.addProject(Project("."))

    return session

@task
def clean():
    logging.info("Clearing cache...")
    session = getSession()
    session.clearCache()
    session.close()

@task
def build():
    session = getSession()

    # プロジェクトのビルド設定
    session.setField("es5", True)
    session.permutateField("debug")

    # Asset(画像, CSS等)の設定
    resolver = Resolver(session.getProjects())
    resolver.addClassName("myproj.App")
    assets = Asset(session, resolver.getIncludedClasses()).exportBuild()

    # 起動スクリプトをbuild/loader.jsに出力
    includedByKernel = storeKernel("build/loader.js", session, assets=assets)

    # Asset以外に必要な静的ファイルをビルドディレクトリにコピーする
    for staticFile in ["index.html"]:
        updateFile("source/%s" % staticFile, "build/%s" % staticFile)

    # 最適化オプションを指定
    optimization = Optimization("variables", "declarations", "blocks", "privates")
    formatting = Formatting()

    # 起動後に最初に実行されるスクリプトを指定
    bootCode = "new myproj.App();"

    # 設定ごとにbuild/myproj-{{ hexdiget }}.jsというファイルを出力する
    for permutation in session.getPermutations():

        # 依存しているクラスを解決
        resolver = Resolver(session.getProjects(), permutation)
        resolver.addClassName("myproj.App")
        resolver.excludeClasses(includedByKernel)

        # 必要なクラスのみ圧縮して書き出し
        classes = Sorter(resolver, permutation).getSortedClasses()
        compressedCode = storeCompressed("build/myproj-%s.js" % permutation.getChecksum(), classes,
            permutation=permutation, optimization=optimization, formatting=formatting, bootCode=bootCode)

    session.close()

作成したら実行権限を付与してビルドを実行。

$ chmod +x jasyscript.py
$ ./jasyscript.py build

もしくは、Jasyをインストールしたときに同時にインストールされるjasyコマンドで、

$ jasy jasyscript.py build

でもOK。以下のようなビルドのログは出力されたあと、buildディレクトリに生成物ができているはず。

% ./jasyscript.py build
>>> Jasy 0.4.6
>>> Initialized project core
>>> Initialized project myproj
>>> Detecting dependencies...
>>> Publishing files...
>>> Updated 0/0 files
>>> Detecting dependencies...
>>> Sorting classes...
>>> Compressing 13 classes...
>>> Detected 2 possible permutations
>>> Detecting dependencies...
>>> Sorting classes...
>>> Compressing 11 classes...
>>> Detecting dependencies...
>>> Sorting classes...
>>> Compressing 6 classes...
>>> Closing session...

build/index.htmlをブラウザで開けば、App.jsに書いたスクリプトが実行される。最終的なディレクトリ構成は以下のとおり。

.
├── build
│├── index.html
│├── loader.js
│├── myproj-b490a0744.js
│└── myproj-b4f8b078f.js
├── external
│└── core
├── jasycache
├── jasyproject.json
├── jasyscript.py
└── source
    ├── asset
    ├── class
    └── inde.h

よくある質問と回答

jasycacheって何ですか

JasyがJavaScriptのソースを解析するときに作るキャッシュファイルです。レポジトリに含める必要はありません。.gitignoreやsvn:ignoreでレポジトリからは外しましょう。

jasyscript.py buildで"Invalid indention in doc string at line 25"のようなエラーが出ます

アルファ版のJasy 0.5を使っているためです。しばらくJasy 0.4.6を使う方が無難です。

どうしても最新版を使いたい人は治るのを気長に待ちましょう。もしくはPush Requestを送りましょう。

shelveの"dbm.error: db type could not be determined"というエラーが出ます

Macのgdbmのバージョンの問題だと考えられます。Python 3.2の次のリリースで修正されると思いますが、それを待てない人は以下のエントリを参照してください。