Code

2015年2月28日土曜日

URL absolute path and relative path

 昨日 AngularJS の $http を使って、AJAX でデータをロードするウェブページをデプロイしたら、ページロードが失敗して、web inspector で見てみたら、xxxx/xxxx url がアクセスできないエラーでした。
 実際見てみたら、別に $location などは使ってないし、なんでロードが失敗しただろうと思って、少し調べてみました。それで、$http を呼ぶとき、"/xxxxx" ような URL を使っていました。これは root の後ろにつく absolute path になるので、ウェブページはサーバーの一フォルダに置いたので、当然アクセスできませんね。
 <a> タグの href 属性と同じように、URL を使うところもし "/xxxxx" で始まると、同じドメインのリソースになります。例えば、ウェブページの url は http://www.abc.com 場合、<a href="/def"></a> をクリックすると http://www.abc.com/def になります。これは絶対パスと言います。
 もし <a href="def"></a> の場合、もしウェブページは前と同じなら http://www.abc.com/def になりますが、もしウェブページが http://www.abc.com/pages にある場合、a タグが http://www.abc.com/pages/def の方に飛びます。これは相対パスです。
 基本的には前に "/" があるかどうかで全て分けます。相対バスの場合、単純に "def" を指定するか、"../def" のようにカレントウェブページをベースに、親フォルダの def に指すような書き方があります。
 もし static ファイルとウェブページが同じドメインにある場合、良く script タグの src を ../../Scripts/js/jQuery.js を指定したりしました。(今はロードスピードを早くするために、すべての static ファイル - images, css, js - を別ドメインに置いてます。)
 まぁ、個人的にはあまり絶対パスを使わないほうがいいと思っています。それを使うと、どこに行くかちょっとややこしくなります。もし使いたい場合、全部の http url を書いた方がいいと思います。場合にもよりますが。

 ちなみに、http を書かなくて、 //www.abc.com/def の場合、アクセスするウェブページの URL から protocol をとって、アクセスします。例えば、ウェブページが https を使ってる場合、https://www.abc.com/def になります。

 今 RESTful API を書いてますので、タグの src とか href とかとあまり関係ないが、パスが http cache とも関係があって、気をつけないといけないですね。今は CacheCow を使って、ETag を自動的に生成するライブラリを使ってますけど。後日また詳細を追加します。C# の HttpClient とか。

 今日はここまで。それでは。

2015年2月22日日曜日

C# ASP.NET Web RESTful API と Front End

 最近、仕事が Back End の方にシフトしました。以前も C# ASP.NET を使ってましたが、あまり印象が良くなかった。ただ、今回 MVC4 を使ってて、なんかコンセプトなどは Ruby on Rails に似てるなと思いました。でもやはり JavaScript の方が使い易いです。
 今作ってるのは UI いわゆる View のない API のみになります。すべてのリソースを操作できる HTTP Method を使って、RESTful です。ASP.NET Web API を使うと、結構簡単にできます。しかも Autofac を使って DI も実現できるし、あまり他の言語のフレームワークと変わらないなと思いました。
 そうすると Front End はもう最初からデータをロードするではなくて、スタティックのリソースだけロードすることになります。ページが早くロードできる利点もあるし、そのあと API を呼び出す事で、どのように表示するかも簡単に変更できます。
 さらに、Task<IHttpActionResult> の戻り値のようにマルチスレッドのコントローラーもサポートしているので、Node.js みたいに他のリソースを要求して、処理が終わったら、HttpResponseMessage などを返すようないわゆる Event Driven のスタイルもできます。このスレッドは ApplicationPool ではなく、他の pool を使うので、いつでも Request が受け付けるようになります。
 あと、NSubstitute を使ったり、Moq を使うことで、Unit Test も簡単にかけるから、全体的にいい感じです。
 
 今回もプロジェクト全体が Mobile First を利用するので、まず iOS と Android Smartphone を対象に、リリースする予定です。今までは、ほとんど Hybrid の App を作ってきたので、今回もそれになりそうですね。
 
 それでは。

2015年2月10日火曜日

AngularJS パフォーマンスは良くない?ー>いいえ、使い方次第です。

 アップデート 2016/05/01:AngularJS 1.0 に比べて、React.js のほうが良いです。AngularJS の bi-direction binding、ng-repeat などは使い易いですが、DOM 操作が多くて、重いです。React.js も同じ機能が簡単に作れます。さらに、AngularJS 1.0 の Learning Curve が高いから、習うにはなかなか時間がかかります。React.js を使うと、どんどん Component が作れて、ますます開発効率が上がります。

 追加 2016/03/07:最近、React.js を使うたびに、AngularJS は難しいなと感じ始めています。1.0 では概念が多くてなかなか使いにくいですね。React.js の場合、概念も簡単だし、Flux を使うと、アプリの構造はかなり簡単になります。また速いです。まぁ、速くするためには、shouldComponentUpdate 関数を細かく実装すればいいので、はっきりしています。今後続けて React.js を使おうと思います。新規プロジェクトの場合、AngularJS 2.0 を待ったほうがいいです。でも、古いバージョンのブラウザをサポートするためには、React.js のうほうがよさそうです。時間があれば、また http://aurelia.io/ を見てみようかと。Polymer はどうやら、遅いようなきがしています。。。後日、ちゃんと勉強してみよう。

 最近、隣のグループは react.js に転向したので、再び AngularJS のパフォーマンス問題が提起されました。実際はどうですかね。。。
 まぁ、個人的な感じでは、JavaScript 根本的にパフォーマンスが良くないです。AngularJS は良く重いと言われてます。特に Dirty Check の実行サイクルが考えば考えるほど重いと思われています。でも、どんなフレームワークでも、react.js、ember.js でも、そういう長いループが存在しています。だから、Dirty Check はそんなに大きいな問題でもないと思います。
 問題は利用者側にあると思います。なぜなら、たぶん結構な数の開発者は $timeout や, $http の中に $rootscope.$apply 関数が呼ばれてると知らないです。それで、無意味に $timeout を呼んだり、自分でその中に $apply を使ったりしています。そうすると、AngularJS は2回 Dirty Check をやるので、重いですね。
 つまり、フレームワークとして、AngularJS はあまり複雑で、なかなか全部理解するには時間がかかります。そのあと、チューニングとかもしないから、問題を発見して、解決するプロセスが欠けてます。
 じゃ、どうしたら AngularJS のパフォーマンスが向上できますかね?
 まず、$apply 関数を理解しましょう。$apply 関数は $digest 関数を読んで、もしエラーとか、Exception が発生したら、ちゃんとエラースタックをリストできます。(中に try-catch があるので)。$digest  は登録した expression を実行して、過去の値と現在の値を比較して、変更があったら、変更の Handler 関数を呼びます。Handler 関数の中にもし何か値変更があったら、また $digest が実行されます、変更がないまで、実行し続けます。それで、$digest が10回まで繰り返し呼ばれます。10回以上の場合、Exception が Throw されます。
 それで、もし登録した expression の数が最小限に抑えるなら、そのサイクルが短くなります。AngularJS 1.3 から {{::express}} が導入されました。もし expression が最初の一回のみ値を設定する必要があるなら、:: で一回のみ binding されます。これも bind-once という関数があります。また bindonce という別のライブラリもあります。
 あと、すべての HTML 要素を ng-app 範囲にする必要がないので、例えば ng-non-bindable を使ったりして、directive の parse 範囲を小さくすることができます。以前も書いたように、jQuery UI を使うと、かなりの量の HTML 要素が作られます。それを parse するあまり必要ないし、"IE FIX" コメントも追加されますので、たまに Widget を壊します。だから、必要のない部分はもう non-bind して、apply directive 過程を止めます。
 次、1ページはすべて AngularJS の ng-app 範囲にすると、かなりの expression 量が増えますので、controller を親子にしないで、独立のスコープなら、もうそのスコープの $digest 関数を呼ぶとか、Dirty Check の量を減らせます。
 
 まぁ、よほど大きい web app じゃない限り、AngularJS のパフォーマンスは悪いと言えないと思います。すべて使い方次第ですね。
 どんなフレームワークを使うと、必ず overhead が発生しますので、良くデザインして、必要な部分と必要ない部分をちゃんと分けて、パフォーマンスは良くなります。

 #余談ですが、jQuery のパフォーマンスはかなり悪いです。通常の Vanilla JS を使うと、同じ関数が jsperf.com でテストすると、なん百倍の差が出ます。なぜなら、ライブラリだから、エラーチェックや、browser の違いを綺麗にカバしたいからです。以前 iOS の WebView も jQuery を使うと重く感じましたので、jQuery Lite を作って、パフォーマンス向上できました。使い方次第ですね。