FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

Closure Library事始め2@開発合宿 in 三浦海岸

konoです。

前回から間が空きましたが、Closure Libraryの続きになります。

今回は開発合宿があったので、ひたすら本を読みながらサンプルアプリのコードを書きまくって理解を深めていきました。

今回書いたコードは本の丸パクリを適宜機能追加したり、削減したりだったので、著作権上ブログに載せられません^^;


そのうち、いつになるか分かりませんが、一から自分で書いたコードをサンプルとして載せたいと思います。

さて、では今回Closure Libraryのサンプルコードを書いてみて、大体の開発の流れが分かったので、そちらの説明をさせて頂こうと思います。

合宿ではRuby On Railsの環境でClosure Libraryのサンプルアプリを構築してみたのですが、それだと説明しにくいのでディレクトリ構成は以下とします。

sample

  • scripts
  • closure-library  // 取得したclosure library
  • closure
  • third_party
  • myscripts  //自作のjs用
  • stylesheets // css格納用 *今回は使いませんね


Step1: HTMLファイルの作成

そしてsampleディレクトリ配下にindex.htmlを用意します。
今回のアプリ名はsample01としておきます。

sample01</pre>
<h1 id="title">sample01</h1>
<div id="main"></div>
<pre>
<script type="text/javascript">// <![CDATA[
     goog.require('sample01.App');

// ]]></script>


closure libraryを使うにあたって必要になるのがClosure libraryのコアの機能を提供するbase.jsで、必ずこのファイルを読み込んでおく必要があります。
base.jsはclosure-library/closure/goog配下に存在しているので、index.html内に以下の記述をしておきます。

<script type="text/javascript" src="scripts/closure-library/closure/goog/base.js"></script>


さらに依存関係の定義ファイルであるdep.jsを読み込む必要があります。

<script type="text/javascript" src="scripts/dep.js"></script>


依存関係定義ファイルは後ほど作成することになるjsファイルで、アプリが必要とするjsファイルをまとめて定義することで依存関係を管理します。
dep.jsはClosure toolsで提供されるpythonスクリプトを実行することで生成されます。
これは後ほど説明します。

もう一つ、index.html内で注目するべきは以下の記述です。

<script type="text/javascript">// <![CDATA[
  goog.require('sample01.App');
// ]]></script>


これがアプリのメインクラスを読み込むための記述となります。

Step2: jsファイルの作成

アプリケーションのメインスクリプトをsample/scripts/myscriptsにsmple01.jsとして作成します。
とりあえずお約束のHello Closureを出力するだけの簡単なアプリにします。
内容は以下になります。

goog.provide('sample01');
goog.require('goog.dom');

/** @constructor */
sample01.App = function() {
  this.initialize_();
};
goog.addSingletonGetter(sample01.App);

sample01.App.prototype.initialize_ = function() {
	this.outputMessage("Hello Closure")
}

sample01.App.prototype.outputMessage = function(message) {
  goog.dom.getElement('main').innerHTML = message;
};

sample01.App.getInstance();


まず、1行目のgoog.provide('sample01');がsample01.Appクラスを定義するクラス宣言となります。
必ず記述する必要があります。
goog.require('goog.dom');は必要なライブラリの読込となります。
JAVAのimport宣言と同じ様なものです。
今回はDom要素をinnnerHTMLで書き換える処理となるので、goog.domライブラリを読み込んでいます。

/** @constructor */宣言ですが、コンストラクタを記述する際には必ずこのコメントを記載します。
コンストラクタは以下の様に記述します。

/** @constructor */
sample01.App = function() {
  this.initialize_();
};


さらにクラスのインスタンスへアクセスするための以下の記述をします。
これでクラスにgetInstance()メソッドが追加されます。

goog.addSingletonGetter(sample01.App);


sample01.App.prototype.メソッド名とすることでクラスに対して独自のメソッドを追加していきます。

最後に記述したsample01.App.getInstance();でクラスにアクセスしてコンストラクタを実行します。

Step3: 依存関係定義ファイルdep.jsの生成

依存関係定義ファイルであるdep.jsファイルは以下のコマンドで生成できます。

$ python sample/scripts/closure-library/closure/bin/build/depswriter.py --root_with_prefix="myscripts ../../../myscripts" --output_file=scripts/deps.js
    • root_with_prefixは、作成したJavaScriptファイルの存在するディレクトリを指定します。

指定方法は以下の様になります。
ルートディレクトリ△base.jsからルートディレクトリへの相対パス

  • △は半角スペース

これでindex.html、アプリ用のJavaScriptファイル(sample01.js)、依存関係定義ファイル(dep.js)の用意が完了したので
ブラウザでindex.htmlを開いて確認します。
以下の様に表示されます。

f:id:s_hayase:20150722182701p:plain

今回は簡単なサンプルでしたので、読み込むライブラリも1つと大したことないのですが、もっと複雑なアプリで読み込むライブラリが増えるにつれ、ライブラリのロード時間がかなりかかるようになっていきます。

その場合、closurebuilderを使うことでjsファイルを統合し読み込みにかかる時間を圧縮することができます。
更にClosure Compilerを使うことで、JavaScriptの最適化をし、最適化するコードによりますが実行速度をアップすることも可能です。

また、JavaScriptだけでなくClosure Stylesheetsを使うことで、CSSの統合や最適化も可能です。

Closure CompilerとClosure Stylesheetsについては次回のテーマとさせていただく予定です。

最後に

実際に合宿で作ったサンプルアプリはもうちょっと複雑なもので一日中ひたすらコーディングしていたのですが、作っていて気づいた点を最後に報告して終わりとさせていただこうと思います。
    • Closure Libraryは難しい!
割と気軽に手を出してしまいましたが、さすがにgoogle様の作ったものだけあって本気度が違います。
JavaScriptと言うか、ほとんど他の言語になっていて、今までのJavaScriptの知識だけではなんともなりません。 

Closureを複数人が覚えるのがそもそも大変というネックがありますが、人によって書き方がバラバラになりがちなJavaScriptをまとめることが出来ると思います。
また、クラスベースのオブジェクト指向なので複数人での開発に向いています。

  • 他のJavaScriptライブラリとは一緒に使いにくい
 

Closure Libraryはほとんど十分すぎる機能があるのですが、他のJavaScriptライブラリの機能を使いたいといった場合、なかなか一緒に使うのは難しそうですね。

  • ちょっと古い?
 

さすがに2009年あたりに登場したためか、デバッガツールであるClosure Inspectorは最新のFirefoxには対応していないとか、Closure Tools Blogは2012/09以降更新していないとか、今はもうあんまり世間の注目浴びてなくて、使っている人もあまり見かけないとかって感じです。
Libary自体は今も頻繁に更新されていますけど、やっぱり軽く触ってすぐ使えるわけではないので敷居も高いですしね。

そんな感じで軽く夢を砕かれましたが、それでも魅力の多いFrameworkなので、もうちょっと続けて触ってみようと思いますよ。