ほぼ日本初 Titanium Mobile Webについて語る

こんにちは、[coe](https://github.com/coe)こと@coffeegyunyuです。
この記事は、 Titanium Advent Calendar 2014 の23日目の記事になります。

僕がTitaniumを始めようと思ったきっかけはクロスプラットフォームが魅力と思ったからなのですが、
コードがiOS寄りだったり、モジュールを探してもiOSのモジュールしかなかったすること、ありませんか？Android派のみなさん。
今回はそんなAndroid派よりも、さらにないがしろにされているMobile webについて書こうと思います。
ちなみにクライアント側ウェブ開発は結構など素人です。

#そもそも、Mobile webってなんなん

Mobile web向けにビルドを行うと、jsはもちろん、htmlやcssその他もろもろが吐き出され、
それをサーバーにアップロードすることによってWebアプリケーションとして動作させるという仕組みです。
ですので、Mobile webはあくまでクライアントサイドのアプリケーションを作るだけであり、データアップロードしてサーバーにデータを貯めこんでどうこうとかサーバーサイド的なことはMobile webでは出来ません。
逆を言うとCGIが許可されてないようなフリーのレンタルサーバーに気軽にポイッとアプリをデプロイすることが可能です。
ただし、勝手に広告が出るようなサイトにアプリをデプロイした場合、デザインが崩れる可能性があります。

#実際にどんな感じに動くん
[こんなかんじ](http://coe.webcrow.jp/)
このサイトでは、自分が今までリリースしたアプリをApp storeから取得して、
それをTableViewに一覧で出してます。
自分がリリースした最新のアプリ一覧を紹介するwebサイトです。
これを作成した当初はSDK3.1.1で作りました。


#開発する上での注意点とか
+ ブラウザごとの挙動
+ windowとかdocumentが使える
+ CORS対策
+ 画像などのパスについて

##ブラウザごとの挙動
はじめはTableViewではなく、ScrollableViewを使用して、一定時間で横に自動スクロールするような、よくあるランディングページみたいなものを作成していたんですけども、
IE9で動かないというのを見つけてしまい、今の形にしました。
まあMobile webって言ってますし、「ウチはモバイルじゃねえと動かねえんだよくそったれ」
って言い切ってもいいのかもしれませんね。
Mobile IEってありますね。
ちなみに公式の動作ブラウザ一覧が[ここ](http://docs.appcelerator.com/titanium/3.0/#!/guide/Mobile_Web_Platform_Overview)にあります。

## windowやdocumentが使える
window.navigator.userAgentみたいな感じでコードに書けます。
当然その部分はMobile Webでしか動かないので、OSみて処理を分けないといけません。
ちなみに僕はブラウザ判定で使いました。
Chromeで正しくi18nでの文字列国際化が出来なかったので。
ブラウザごとに処理を分けるって、Web開発してるっぽい感満載で、いいよね！

##リソースのパスについて
どうやら、リソースのパスは、ドメイン直下を基にして相対で決めているようです。
少なくともSDK3.1.1では。
なので、Mobile Webプロジェクトを
http://coe.webcrow.jp/
にデプロイするとうまく動くけど、
http://coe.webcrow.jp/hoge/
にデプロイすると正しく動かないです。
なので、然るべき場所にデプロイするかパスを考えましょう。

##CORSについて
あんまりWeb開発に関して詳しくないんでボロがでそうですが、最近のブラウザは、
「よくわかんない外部ドメインとAjax通信するなんてどんな危険があるかわからないから通信なんかさせないヨ」
と、セキュリティに気を利かせてくれるんですけども、それだとCORS対応してない外部のweb apiが使えません。
Mobile webのHTTPClientは思いっきりこれに引っかかるので、それをなんとかしないといけません。

###なんとかする方法
公式ドキュメントに書いてある方法は２つ。
1.サーバー側でCORS対応してね
不可能
2.プロキシとTi.Network.httpURLFormatterでなんとかしてね
サーバープログラム嫌い教の信者としてはなるべくサーバー立てたくないです

Titaniumに標準で備わってるYQLならいけるんじゃないかと思い、Ti.Yahoo.yqlで通信をしようとしたところ、HTTPのOPTIONSメソッドでコケました。(SDK3.1.1時点)
ということで、プロキシとTi.Network.httpURLFormatterでなんとかするしかありませんということに。

###CORS用プロキシサーバー構築
無料でやりたいのでGAEを選択。
有志の方がGAEでプロキシサーバーを構築する方法をGitHubに公開してくれていたので、それをフォークしてTitanium Mobile webでCORS対応するように作り変えてGAEにデプロイします。
（HTTPSには対応してません。誰か対応させてちょ）
https://github.com/coe/google-proxy

###Titanium側対応
あとはこいつを通してAPIにアクセスするだけで情報が引っ張ってこれるんですが、いちいちHTTPClientに対してプロキシ込みのURLを書いてたら面倒だし、何より無関係のiOSやAndroidまでプロキシ通してアクセスしてしまうのでGAEのリソースを使い切ってしまいます。
そこで登場するのがTi.Network.httpURLFormatterです。
Ti.Network.httpURLFormatterってなんなのかというと、HttpClientの通信の前にURLにフィルタをかけることができるAPIのようです。
使い方はこんな感じです。

```coffeescript:alloy.coffee

    if OS_MOBILEWEB
   
      PROXY_URL = "http://xxx.appspot.com/"
      Ti.Network.httpURLFormatter = (url) ->
   
        if url.indexOf(PROXY_URL) is -1 and url.indexOf("://") isnt -1
          url = url.replace("http://","").replace("https://","")
          url = "#{PROXY_URL}/#{url}"
        url

```

こうすることにより、Moblie webでのHttpClientは全てプロキシを通して通信するのでクロスドメイン通信で無事APIよりデータを引っ張ってくることができるようになりました。

###最後に
ということで、あんまり前例のないMobile web開発についてがっつり触れてみました。
ある意味webアプリは最強のクロスプラットフォームですので、始めはスマートフォンをターゲットにアプリ作ってたけど規約的にアウトなアプリが出来上がった場合、Mobile webに逃げるみたいなことも可能です。是非ともみなさん人柱になってほしいと思います。
あとは課金とか広告のモジュールが出れば盛り上がる気がしますね。
~~来年はBrackberryアプリ作ります。~~