スムーズスクロールするやつ作りなおした。
APIコール時、コールバックを受け取るのをやめてdeferredを返すようにしたかったのでそのようにし、ごちゃごちゃになってたのを整理した。
deferredでやりとりすると、コールバック設定しまくらないといけないのが防げて便利
スムーズスクロールするやつ作りなおした。
APIコール時、コールバックを受け取るのをやめてdeferredを返すようにしたかったのでそのようにし、ごちゃごちゃになってたのを整理した。
deferredでやりとりすると、コールバック設定しまくらないといけないのが防げて便利
jQuery.LazyJaxDavisというライブラリを書いた。このライブラリは、一般的な静的に生成されるようなサイトを、HTML5 history APIの力を使って素敵にダイナミックにします。
このライブラリを使うと、すべてのリンクを、通常遷移の代わりに、Ajaxベースのダイナミックな遷移にします。その際、history.pushStateして、通常の遷移と同じように見せる。言葉にするのは難しいので、実際にサイトを見てもらったほうが分かりやすいと思う。以下のサイトの左ナビをポチポチクリックするなりして。
加えて、結構汎用的なURLルーターの機能も備えてる。詳しくは上記ドキュメント(兼デモ)を見てくださいなのだけれども、このライブラリがやりたいのは、「いつも普段みんなが作ってるようなサイトを、HTML5 history API の力を使って手軽に素敵にしようぜ」です。
HTML5のAPI使いたいという話まず、HTML5がどうだと言われても、別にマークアップが変わったところでなんかドラスティックに素敵になるというわけでもない(とここでは言ってしまうけれども)し、なんか実務で使うのだと、まーその、新しいAPIは使えないよねーなかなか…っていうのがあった。でもなんかうまいこと使いたい。
そこで見つけたのが Davis.js というライブラリなのだけれども、これは、URLのルーター。Backbone.jsにも同じような機能がある。これらのURLルーターは、URLの切り替わりをhistory APIを使って制御してくれて、対応するURLになったら、はいこれやってねという類のもの。でもまー早い話、Webアプリ用だ。だってhistory API使えないブラウザじゃ何も動かんし。その場合には代わりにhashchangeをするという機能がBackbone.jsにはあるが、それはまたそれで実URLじゃないので微妙すぎでしょうよと。hashchangeによる遷移のサイトは、将来的には撲滅されるべき。Webアプリならまぁ仕方なしと思える点もあるけれども、静的なサイトでそれを使うなんてのは微妙すぎる。
でもなんか使いたいよねーと思って考えてたアイデアが、「pushStateした時に、そのページをAjaxで取ってきて、メインコンテンツ部分だけ置き換えればいいんじゃない?」というもの。そうすれば、history API対応していないブラウザでも普通に見えるよねとういことで。これをちょっと試し、弊社PixelGridが、実務で実装したのが以下。(ほぼ)すべての遷移がAjaxになる。
仕組み的には、メインエリアを示すコメントを各ページに入れ、そこだけ抜き出してきてページに突っ込む。これを、Davis.js を使って実装した。この仕事はまぁそんな感じで無事、運用も続いているけれども、心配していたhistory API周りで何かトラブル - ということはほぼ無く運用できてる。
Webアプリ実装した話別の仕事でまた、なんだか開発する人のノリがとてもよかったので、今度は、上みたいにガバッと取ってくるのではなく、サーバーは全部JSONを返して、それをフロントで全部制御するという仕事をやった。そしてジセダイでやったように、hisotry APIでやる。IEとかでは通常の遷移で見れるようにする - という風に。サーバーはすべてのURLに対して同一のHTMLを返す。これはかなり、規模の割にはチャレンジングなものだったけども、ここでも Davis.js を使ってやった。この案件は名前は出せないけど。
IEでも見れるように - ということなので、Davis.jsをそのまま使えないから、これをラップするライブラリ作り、URLルーターにしてた。
この2つの仕事で作ったものを改良し、汎用的にしたものがこのjQuery.LazyJaxDavisです。
作りたかった機能まず、ジセダイで実装した、リンク先のhtmlを取ってきてぶっこ抜く方式を、デフォルトで採用したいと思った。これは、意外にトラブルが無かったし、比較的導入のコストも低いから。なので、この機能が、jQuery.LazyJaxDavisの基本機能になってます。
あとは、Webアプリ向けすぎるURLルーターでは無く、もっと静的サイト向けのURLルーターが欲しかった。当然、そのルーターは、IEでも使えなければならない。history APIが使える場合はそれを考慮した状態で - そうでなければ、URLだけを見て、やらせたいことをやるという感じにしようと。具体的には、/product/ だったら、このコードを実行して、 /company/ だったらこのコードを実行して〜っていうのもの。上記2案件で書いていたURLルーターは、この機能を、Davis.jsの上に被せたものだったから、これをもっと汎用的にしたいと。
これらを、jQuery.LazyJaxDavisがうまいこと助けます。ここで挙げた Davis.jsに、基本的には依存してますが。
機能とかデモとかまず、ぶっこぬいてきてはめる機能。これの実装はかなり楽。なので、静的サイトやらブログやらなんやらで是非使ってみて欲しいと思ってる。
一応言っておくと、後から追加したDOMに関してはdocumentready時にいつも適用しているようなロールオーバーなりなんなりは適用されないので、その点はjQuery.LazyJaxDavisで色々とイベントを用意しているので、これらを使ってうまいことやってくださいというところ。別にそんなに難しい話じゃあ無いが、実務経験からすると、特にソーシャルボタン周りの実装が地味にめんどい。
次、URLルーティング機能。これはDavis.jsベースで動くが、IEとかでもAjaxして取ってくる関連のイベント意外は問題なく動くようになってる。このURLだったらこうして、こっちのURLだったらこうして〜というのが指定できる。
次、より高度なルーティング機能。これは、例えば、/product/foo.html では、このコードを実行したい… これは上のURLルーティングでやればいいんだけど、/product/* 全体でこれを共通で実行させたいんだよね… っていうのを実現するためのもの。透明ルーティングっていう名前にした。上から被せられる、追加のルーティング。
次、ぶっこぬき部分はやらない機能。この場合、Davis.jsに依存しない。じゃあ何してくれるんだというと、上に書いたURLルーティングの機能だけを提供する。
ここまでの機能は、基本的に、静的なサイトで使うことを考慮して作ったものだけれども、それに加えて、でもWebアプリみたいな状況でも使いたいんだよねーという場合、Davis.jsの機能を直接使える機能。
〜と、これがjQuery.LazyJaxDavisの基本的な機能ら。これらをやるために、実務でちょとハマったことだったりなんなりがやや吸収された状態になってる感じです。
ということで、お試しの上、レッツhistory APIしましょう。
ただ、静的なサイトを、軽くWebアプリに用に設計することになるため、(自己責任で)と、一応付け加えておきたいです。
CoffeeScriptは是か否かという話は、CoffeeScriptを調べていれば否応なしに引っかかる話題で、自分もそれについてはかなり考えさせられた。何回かこのブログでも書いたとおり、CoffeeScriptいいなーと思ってはいて、ここ1,2ヶ月はずっとCoffeeScriptでJavaScriptを書いているんだけども、いい点はもちろんあるにせよ、書いているうちに、最初は見えてなかった問題も見えてきたりした感じがするので、その点について少し書きます。
あんたの仕事は何なのまず、自分は受託制作がメインの会社(PixelGrid)に務めていて、一応、JavaScriptやる会社ですと謳っているのもあって、JavaScriptでUIを組む仕事が結構多い。自分は、マークアップ出身なJavaScriptプログラマーみたいな感じになってる。最近よくあるのが、いままでFlashで作っていたものをJSでーとかだったり、WebアプリをAjaxベースでーとか、そういうのとかをメインにやったりしてる。
そのような状況で、複雑なUIを組むためには、設計方法に悩む。jQueryは素晴らしいけども、入り組んだUIを設計するための手段は提供してくれない。そんな状況で、自分はjQuery UIのベースになっているwidgetというフレームワークを使ってイベントのやりくりをしていたけれども、これはあくまでjQueryプラグインをOOPで書けるようにしたようにしたもので、そこまで豊富な機能があるわけじゃない。
サーバーとの連携を多く行うような場合、最近だと、Backbone.jsを使うようにしたりしているんだけども、それでもちいさなクラス的な働きをするものはconstructorとprototypeをポチポチ自分で書いたりしていた。別にそれが悪いという気はさっぱりしないけれども、とにかく、その「ちいさなクラス的な働きをするもの」が必要だと感じていた。
あと、似たような機能を書くことが多い。自分と同じようなことをしている人は分かるかもしれないけれども、ページ上には沢山のパーツがあり、それを管理するクラスを作り、それらをイベントで連携させる - ということを無数にやるため、そこまで複雑ではないが、無くてはならない - しかし、サイトによってちがうしCSSにも依存する - みたいなものを沢山作る必要がある。
CoffeeScirptが解決したモノそんな状況で、CoffeeScriptを使い出したんだけれども、CoffeeScriptは、この欠けていた部分を補完してくれたものと感じている。The Little Book on CoffeeScriptには、こう書いてある。
Classes in JavaScript seem to have the kind of effect that cloves of garlic have to Dracula for some purists; although, let’s be honest, if you’re that way inclined, you’re unlikely to be reading a book on CoffeeScript. However, it turns out that classes are just as damn useful in JavaScript as they are in other languages and CoffeeScript provides a great abstraction.
JavaScriptにおいてクラスは、JavaScript原理主義の人にとっては、ドラキュラにニンニクを与えたように嫌がるものだが、CoffeeScriptはこれを役立つものと考え、抽象化した機能として提供する - みたいな感じ。
Webアプリのように複雑にUIが組み合わさって作られる様な状況では、自分はこの意見に同意する。そして、コレを実現しようとした時、そんなわざわざ新しい言語でラップする必要はないよ、この小さいライブラリを使いなよ - と言われるかもしれないけれども、それでも、その「小さいライブラリ」とやらを使うことで、一枚フレームワークの上に立ってコードを書くということになる。CoffeeScriptを使えば、それが既に存在する状態で始められるので、コードを書くのが非常に楽。
これは特に、Backbone.jsと組み合わせて使った時に、大きな効果を発揮したと思う。Backbone.jsのコンポーネントはクラス的に作られているので、CoffeeScriptと合わせて書くと、本当にサクサク書けた。やってみると実感できるけれども、この相性の良さはかなりすごい。
だとしても、そこでCoffeeScriptをあえて使うのは必須ではないでしょうときっと言われるだろう。それは確かにYESだけれども、僕が言いたいのは、この、CoffeeScript + Backbone.jsの組み合わせでコードを書くことで、実際に実務をこなすためにかかった時間を、かなり短縮できたというのが、一つ、事実としてあったということ。CoffeeScriptを大プッシュする人がいたら、きっと同じようなことを経験したのではないかと思う。
とあるプロジェクトで自分が書いたJavaScriptは、1万行を超えてた。これは別に、同じコードをひたすらコピペしていってそうなったわけじゃない。Backbone.jsのModelだのViewだのjQueryプラグインだのを延々必要なだけ書いて行ったらそうなった。今となっては、まぁその時はもっとCoffeeScriptは下火だったけれども、これをCoffeeScriptで書いていたら、自分の潰れた土日はもっと少なかっただろうと思う。今数えたら、 var self = this; を、おおよそ200回書いていた。
CoffeeScirptはたぶんこんな感じCoffeeScriptは、JavaScriptの煩わしい括弧だのfunctionだのを省略できますよーという点が大きなメリットの一つだけれども、それも含め、クラスだったり、argumentsの展開だったり、単純なループだったり、printfみたいな機能などなど、JavaScriptに欠けてパーツをいくつか補ったような存在だと思う。なので、それがピッタリフィットするような状況では、CoffeeScriptは最高だねと思えるだろうし、そんなものは僕の書くコードには元々いらないものだよと思うのであれば、わざわざ言語をラップした言語を作るなんて無駄にもほどがある!と感じるんじゃないんだろーか。
で、自分は、こういう、CoffeeScriptが補ったものは、緻密なライブラリを作ったりするのであれば、細かい調整もいるし、そんなのはいらんと感じるかもしれないけども、そういったライブラリを色々と使い、実プロダクトに近いコードを書くのであればあるほど、あーこれが欲しかったんですよーと感じるものじゃないかなーと思う。
なので、そういうのを普段から書いてる人であれば、使ってみるといーんでないのかとは思う。もし、将来的に使わなくなったとしても、学んで見る価値はあるものかなーと。
自分のCoffeeScriptに対する認識は、「フレームワークが一枚かまされたJavaScript」という感じだ。そういう意味で、あらゆるJavaScriptはCoffeeScriptで書かれるべきだとかは別に思わない。
CoffeeScriptメンドクセーと思うことそんなこんなで、CoffeeScriptは使うといいよと思ってる自分だけれども、これはでかい問題だと思うことがあった。CoffeeScript書きだしてから、延々とコードを書いていて、クライアントワークで使ったコードを書きなおしてライブラリ化するのが結構楽しくなってきていて、趣味になってた。以下にその、CoffeeScriptで書いたライブラリがある。
で、このライブラリを作って、それを別の仕事で使おうとコピってくるんだけれども、そうしていると、当然、バグだったり、機能追加したいことが出てくる。そんな時、つくったライブラリをいじるのが非常にめんどくさい。
なぜなら、読み込んでいるのは、コンパイルされたJavaScriptだ。CoffeeScriptをコンパイルした結果は、かなり読める感じだけれども、それを直接いじったら、オリジナルのCoffeeScriptにも反映しなければならない。もし、そうしないのであれば、バグをオリジナルのスクリプトのレポジトリで直し、またコピってくるか、ライブラリのCoffeeScriptのソースも一緒に、そのプロジェクトのソースとして扱って、一緒にビルドしたりとか、そういうことをしなければならない。まぁ、理想は、オリジナルのレポジトリで直し、コンパイルしたものを再度持ってくる - だろうけど、これは結構めんどい。gitのレポジトリをネストする形にして、ライブラリのレポジトリも、親プロジェクトに含めてしまえばいいんだろうか。ここのところのうまい方法が分からない。誰か知ってたら教えて欲しい。
で、これが他の人が書いたCoffeeScriptだったらどうだろう?自分は、CoffeeScriptのビルドを、gruntというnodeで書かれたビルドツールを使ってやってる。ただ、gruntとターミナルで打てば、設定されたとおりにコンパイルし、簡単なバナー用コメントを追加してくれるものではあるけれども、このライブラリをデバッグするためには、少なくともそのようなステップが必要。ライブラリのレポジトリごとにビルドを設定しているから。
これは、まだ自分が書いたコードだからいい。たぶん、ほかのCoffeeScriptで書かれたようなライブラリも、同じような仕組みを使ってビルドしたりしていると思う。10個のライブラリを使っていて、それぞれにバグがあったとしたら、それらをチョコっと直すのだけでも、相当しんどいんじゃないかと思うんじゃないだろうか?
これは、Ryan Florenceが、以下の記事の中でも言及している。
初めにこの記事を見た時、「フーン、まぁこの人はみんなのコードを見る立場のひとだからねー」と思っていたのだけれども、自分でちょこちょこライブラリを作っているうちに、この問題がとても大きいということがわかってきた。
上の記事のコメント欄をざっと眺めてみるといい。たぶん、どこでも同じような議論がかわされていて、「オレにとってはなんの問題もない」とか「保守的に見れば採用は避けるべき」だとか言われており、この問題の結論はきっと出ないだろう。
Source Map とやらの機能で、この問題がかなり改善されそうな兆しが見えてきているものの、このコンパイル問題は、現時点で、CoffeeScriptが抱えている、かなりでかい問題だと感じてる。
ほか、些細な利点カンマ忘れてIEでエラーとかでない利点。これは、JSlintかけろよとか言われるだろうが、実際、自分はvimでボタンをポンと押せばJSlintをかけられるようにはしているものの、それでも忘れることはある。これを、全く無くせると言うのは、思ったよりもでかいと感じる。
コードが短くなる利点。これは、特に自分のように、プロダクト用のUIみたいな、同じようなコードを沢山書く人間にとっては、思ったよりも効果がでかいと思った。特に、jQueryのdeferredなりイベントなりなんなりで、やたら括弧が入れ子になる状況を、さっぱり綺麗にできるのは、見やすくなるし、単純に書いていて楽しい。
などなど。これらは、些細ではあるものの、業務効率を大きくアップさせるものであるとは思う。自分は、var self = this; を200回書きたいとは思わない。
自分の中での結論とりあえず、自分はこれからもCoffeeScriptで書いていくつもり。もしCoffeeScriptが使われなくなったとしても、そんなことはいちいち気にしていない。もし自分の関わっているのが、大きなオープンソースのプロジェクトであれば、確かに、それをCoffeeScriptにするのは、思い切った決断のように思う。だけれども、自分は、具体的なプロダクトのためのコードをガリガリ書くような立場の人間なので、そうではない。そのような状況において、CoffeeScriptの採用は、作業スピードとメンテナンス性をあげるものだと感じている。上記で挙げたような問題はあるにせよ。
もしあなたが、CoffeeScriptに興味があるものの、その将来性を不安視して手を付けないでいるのであれば、さっさと試してみろと言いたい。特に、自分と同じような立場の仕事をしていた場合。
この人とは長く続くだろうか?などと不安ばかり抱えて恋人を作る人などいないだろう。
以下の記事では著名人がインタビューに答えているので、読んでみると面白いと思う。
この記事の中で、「ユニットテストにだけCoffeeScriptを使う人はいるだろうね」という意見がある。ユニットテストのために書いたコードが他の何かで使いまわされることは、ほとんど無いだろう。単にサクッと書けるゆえ、コードを書くのを楽にしてくれるはず。CoffeeScriptとはつまり、そういうものだ。たぶん。今のところは。
学習コストがあるという点については、それほどではないと思ってる。CoffeeScriptの恩恵を感じられる人は、そもそも、プログラムの基本的な設計の考え方が分かっている人であると思うから。