Upload
naoya-ito
View
8.798
Download
2
Embed Size (px)
Citation preview
アジェンダ
• クライアントサイド
• PhoneGap
• Titanium Mobile
• Scripting Layer for Android
• サーバーサイド
• Node or Perl
スクリプト言語で iOS/Android アプリ
• HTML5
• Web開発、同様スクリプト言語で書きたい!
• JavaScript, CoffeeScript
• スクリプト言語な俺たち歓喜 \(^o^)/
• Perl で書ける?
PhoneGap
• UIWebView ベースのアプリ開発 F/W
• JavaScript / HTML / CSS
• UIWebView の js に Native Bridge な API
• Phone"Gap"
navigator.camera.getPictures(onSuccess, onFail) onSuccess = function (base64data) { var img = document.getElementById('myImage'); img.src = "data:image/jpeg;base64;" + base64data; }
例: Photo Receiver
• PhoneGap (+ jQuery mobile) + Node (+ Express + Socket.IO)
iOS app with PhoneGap Node
WebSocket (Socket.IO)
Photo Receiver (sender, index.html)
<html> <head> ... <script type="text/javascript" src="phonegap-1.0.0.js"></script> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="socket.io.min.js"></script> ... <script type="text/javascript" src="sender.js"></script> </head> <body> <div data-role="page"> <div data-role="header" data-theme="b"> <h1>Photo Sender</h1> </div> ...
Photo Receiver (sender, sender.coffee)
onDeviceReady = -> socket = io.connect 'http://localhost:3000/sender' onSuccess = (data) -> socket.emit 'pushPhoto', data ... $('#camera').click -> navigator.camera.getPicture onSuccess, onFailure, opt $(document).ready -> $(document).bind 'deviceready', onDeviceReady
# sender.coffee の変更を watch → sender.js を生成 $ coffee -cw *.coffee
Photo Receiver (receiver, app.coffee)
express = require "express" app = module.exports = express.createServer() app.get "/", (req, res) -> res.render "index", title: "Photo Receiver" app.listen 3000 io = require('socket.io').listen app sender = io.of('/sender').on 'connection', (socket) -> socket.on 'pushPhoto', (data) -> data_uri = "data:image/jpeg;base64," + data receiver.emit 'showPhoto', data_uri
PhoneGap あれこれ
• HTML + JS = "HTML5 ready" • jQuery / jQuery mobile
• CoffeeScript
• socket.io
• sass, less, stylus
• Facebook/Google+ と似ているが... • UIKit の制御は bridge しない
• UIWebView は Safari より遅い • UIWebView = not Nitro
• JITコンパイラなし
• Adobe が買収 • Native → HTML5 アプローチとして PhoneGap モデルは有力
Titanium Mobile
• ネイティブアプリを JavaScript で
• Titanium Studio でビルド
• インタプリタ上で動く
• iOS : JavascriptCore / Android : Rhino
• JSエンジンがUIKitを操作
• 動的に動作確認できる
Cover Flow
win = Ti.UI.currentWindow() view = Ti.UI.createCoverFlowView images: [ '../images/01.jpg' '../images/02.jpg' '../images/03.jpg' '../images/04.jpg' '../images/05.jpg' ] backgroundColor: '#000' win.add view
HBFav コード断片
require 'lib/underscore' Ti.include 'feed.js' class AbstractState toString : () -> 'AbstractState' constructor: (@feedView) -> getFeed : (url) -> self = @ onload = @.onload onerror = @.onerror xhr = Ti.Network.createHTTPClient() xhr.timeout = 100000 xhr.open 'GET', url xhr.onload = -> data = JSON.parse @.responseText onload.apply(self, [ data ]) xhr.onload = null xhr.onerror = null xhr = null xhr.onerror = (err) -> onerror.apply(self, [ err ]) xhr.send()
Titanium Mobile あれこれ
• JavaScript ready
• CoffeeScript
• CommonJS ・・・ underscore, socket.io etc.
• Titanium Mobile != HTML5
• JavaScript だからといって HTML5 へ向かってるわけではない
• 「JS でネイティブ書ける」
• 現時点では、現実的な解
• 実用的だが当然、トレードオフも – メモリ管理不要、ダイナミック更新、ラピッドに開発可
– ネイティブとは速度差 / 細かなチューニングが難しい
– デバッグ環境がこなれていない
Scripting Layer for Android (SL4A)
• Androidアプリを Perl で
• ここは YAPC だぜ?
use Android my $android = Android->new; $android->makeToast( "Hello, Android!" );
SL4A
• PhoneGap, Titanium とも別アプローチ
• Java アプリが "Scripting Layer" と JSON-RPC で通信
• Java アプリのAPIがネイティブの機能をブリッジ
• 本格的なアプリを作るのには向かない
• 速度、安定性...
クライアントサイドまとめ
• JavaScript によるネイティブブリッジFWは発展途上
• この方向性のフレームワークは増える
• PhoneGap, Titanium Mobile は"そこそこ" 実用的
• ※ debug しんどい
• Facebook/G+ の言う "Embedded Web Views" のFWはまだ
• UIWebView アプリを作りつつ
• ネイティブの "UI" と橋渡し
• Perl でクライアントサイドは、さすがに ...
• SL4A はおもちゃの領域を出ない
サーバサイド
• これまで通り Perl で書いても良いですが・・・
• クライアントを JS で、なら、サーバも JSで
• この流れは止められない
• Node.js : server-side JavaScript が現実的に
perl vs Node
Perl Node.js
プリプロセッサ N/A CoffeeScript
言語 Perl言語 JavaScript
実行環境 perlインタプリタ node
ウェブ実行環境 mod_perl, PSGI middleware, etc.
http.Server, connect etc.
Web Framework Catalyst, Mojolicious::Lite, Dancer etc.
Express, etc.
パッケージ管理 cpan npm
主なWebアプリのモデル prefork (同期) Single Process Event Driven (非同期)
Node.js
• Single Process Event Driven な server-side JavaScript Engine – Perl : POE, AnyEvent
http = require 'http' http.createServer (req, res) -> res.writeHead 200, 'Content-Type':'text/plain' res.end 'Hello World!¥n' .listen 8080
• Perl でできないことをやってるわけではない
• 一方の「手軽さ」、JavaScript との相性
% node-dev hello.coffee
underscore.js
require 'underscore' pow = _([1, 2, 3]).map (n) -> n * 2 max = _([1, 2, 3]).max() sum = _([1, 2, 3]).reduce (memo, num) -> memo + num use List::Util qw/max reduce/; my $pow = map { $_ * 2 } (1, 2, 3); my $sum = reduce { $a + $b } (1, 2, 3); my $max = max(1, 2, 3);
Express
express = require "express" app = module.exports = express.createServer() app.configure -> app.set 'view engine', "jade" app.use express.compiler src: __dirname + "/public" enable: [ "sass" ] app.get "/", (req, res) -> res.render "index", title: "Hello, Express"
• Web framework, Sinatra inspired
• Perl ... Mojolicious::Lite etc
• SASS/LESS/Stylus, Coffee, Jade/EJS, Socket.IO ready – emerging web technologies...
vows
vows = require 'vows' assert = require 'assert' test = vows.describe('ゼロでの割り算').addBatch '任意の数をゼロで割った時' : topic: -> 42 / 0 '無限大になる' : (topic) -> assert.equal topic, Infinity 'ただし、ゼロをゼロで割った場合' topic: -> 0/ 0 '以下となる' : '数値でない' : (topic) -> assert.isNan topic '自分自身とは等価でない' : -> assert.notEqual topic, topic do test.run
• Perl : Test::More, Test::Base, Test::Declare
• vows : Asynchronous BDD
xml2js
parser = new xml2js.Parser() parser.addListener 'end', (json) -> console.log json parser.parseString xml
• Perl : XML::Simple + JSON
aws-lib
aws = require 'aws-lib' aws = aws.createProdAdvClient( accessKey, secretKey, associateId, region: "JP" host: 'ecs.amazonaws.jp' ) aws.call "ItemSearch", SearchIndex: "Books" Title: "Perl" ItemPage: 1 ResponseGroup: 'Medium' (result) -> console.log result
• Perl : Net::Amazon
Socket.IO
• WebSocket-like API
– 抽象化 : WebSocket, xhr-polling, xhr-multipart, jsonp-polling ....
• Node.js の急先鋒
/* client (jade w/ express) */ script(src='/socket.io/socket.io.js') :coffeescript socket = io.connect 'http://localhost’ socket.on 'recv', (data) -> console.log data socket.emit 'send', "Hello!"
/* server (app = express object) */ io = require('socket.io').listen app io.sockets.on 'connection', (socket) -> socket.on 'send', (data) -> console.log data socket.emit 'recv', data
pocketio
• Perl の Socket.IO server – JS ⇔ Perl
– JS ⇔ Perl ⇔ Perl modules
use PocketIO; use Plack::Builder; builder { mount '/socket.io' => PocketIO->new handler => sub { my $self = shift; $self->on( 'recv' => sub { my ($socket, $data) = @_; $socket->emit('send', $data); }); ...
サーバサイドまとめ
• Node きてる – スマートフォン開発のバックエンドを Node にする"必然性"はないが
– クライアントを JS / Coffee で書くなら"優位性"はある
• npm++
• CommonJS ウマー
• node ・・・ 新しいn実装が多い
• Socket.IO
• CSS frameworks
• 一方の perl ・・・ 莫大な資産 = CPAN
• node / perl の pro/cons を比較して
• (1) アーキテクチャ
• 共存させるアプローチ ・・・ RPC, pocketio
まとめ
• スマートフォン : 今後、ネイティブからHTML5へ • Facebook/Google+
• × 100% HTML5 ○ ハイブリッド
• JS (Coffee) のみでアプリが開発できるように • PhoneGap, Titanium Mobile
• クライアントからサーバまで一気通関 • クライアントが JS なら、Node 利用の動機は大きい
• Native → HTML5 への移行は JavaScript の進化にアリ
• Node.js = Web Dev の梁山泊に (beyond Rails...?) • socket.IO / express / jade, stylus, coffeekup, CSS FW / coffee ...
• ただし、Node だけではサポートできない領域もまだまだ
• Perl の莫大な資産は活かしたい • pocketio などのアプローチ