JavaScriptのみで構築するWebサイト

# お仕事の相談が来た！

* 2000年作成の古いWebサイトをリニューアルしたい
* VB6の管理ツールとPHPとPerlが混在するシステム
* サイトで使用するデータの元ネタはAccess MDBファイルで管理
* 現状10万／1日アクセス、たまにアクセスが集中（10倍超）することがある
* サイトが共用サーバーにあり、たびたびテンポ(503)ったりしている
* キャッシュサーバーを導入したけどそれでもエラーが発生する

なんでこんなになるまで、放っておいたのよ(；´д｀)

# お客さんの要求

* エラーが起こらないようにして（ですよねー）
* Webサーバーとキャッシュサーバーはこのままいくよ（えっ）
* 新しい切り口の検索機能を追加したい
* PCとスマホに対応してね（スマホ持ってない・・・）
* セキュリティホールをなんとかして（数十カ所のXSS脆弱性）
* 15～30日に1回の頻度でサイトのデータを更新する予定だよ

なんでサーバーを増強しないの(ﾟдﾟ)？
と聞いてみたところ政治的コストが高いからだそうです
な、なるほど・・・(´・ω・`)
私のスキルでなんとかなるかなぁ・・・


# 引き受けてみることにして調査開始

無職なので仕事があれば積極的に請けないと飢えてしまうｗ
よし！がんばるぞぉ(`・ω・´)b

* VB6は ~~やったことないけど~~ Excelマクロとほとんど一緒なんですね！
* PHPとPerlの実装はノンフレームワークでHTMLが混在するカオスだった
* 単純な名称検索ページのソースが3000ステップもある（他もこんな調子）
* PHPが読み込むデータはVB6アプリで出力した "<>" 区切りのテキストファイル
* サイトの機能は基本的に検索と表示のみ（性質上動的な更新はありえない）
* サーバーにDBがない。DBがないよ！嘘じゃないよ本当ダヨ！
* データは3階層構造で1階層目が1000件、2階層目が5000件、3階層目が70万件
* 表示対象のデータには個別に掲載期間がある

1ページ3000ステップもあるPHPは酷すぎて作り直した方が早そうだし、VB6なんてビルドする環境も持ってないわ・・・
既存のソースはもはやゴミでした・・・

# よし！JavaScriptで作ろう（錯乱）

* サイトデータはJSON形式にして、機能ごとにファイル分割しておこう
* JSONの元になるAccess MDBから読み出すツールはC#で作ろう(Json.NET)
* JS/CSSはC#で圧縮しよう（YUI Compressor）
* キャッシュサーバー対策でJS/CSS/PNGなどのURLにパラメータを付けよう
* JavaScript側はjQuery/jQuery Mobileで頑張ろう
* .htaccess を使って静的URLにしよう

RewriteRule の負荷ってどのくらいなんだろう・・・。
正直調べる方法も分からないので実際にやってみてダメなら、やめられるように準備しておこう
Ruby on Rails とかでも似たようなこと普通にやってるしたいしたことないよね、たぶん(￣▽￣；)

# 作成開始！

C#側のやることは大して書くこともないので割愛・・・

JavaScriptはソースは1ファイルのみにしました（ただしjQueryは別）
ページごとにファイルを分けてもライブラリメソッドなどを考えるといくつも読み込む必要が出て優しくないと思ったんですよね。

そして現在どのページを表示しているのかをJavaScriptが分かるように以下のような目印を付けました。

```html
<body id="ページID">
```

これをJavaScriptから取得して処理を分岐します。

```js
$(document).ready(function() {
  switch (document.body.id) {
  case 'pageA':
    pageA();
    break;
  case 'pageB':
    pageB();
    break;
  //省略...
  }
});
```


パラメーターは location.pathname を正規表現で分解して取得。

```js
  // URLは /パラメータ名-ID/パラメータ名-ID/... という形式
  var matches = location.pathname.match(/\/[a-z]+-[^\/]+/g);
```


データの掲載期間内かを判定するためにDateオブジェクトを使ったけど・・・
これだとクライアントの時刻設定を変えると、まだ表示しないものが見えてしまう

```js
var _now = new Date();
```


仕様と割り切るのも手だけれど、どうせ毎回JSONファイルを読むのだからGETのレスポンスからDateヘッダ拾えばいいんじゃない？

```js
function loadJSON(requests, callback) {
  var baseUrl = _baseDir + 'json/';
  var jqXHRs = [];
  for (var i = 0; i < requests.length; i++) {
    var param = requests[i].params ? requests[i].params + '&' : '';
    jqXHRs.push($.ajax({
      url: baseUrl + requests[i].url,
      data: param + _lastModified,
      type: 'GET',
      dataType: 'json'
    }));
  }

  $.when.apply($, jqXHRs).done(function () {
    var args = requests.length > 1 ? Array.prototype.slice.call(arguments) : [ arguments ];
    var json = [];
    for (var i = 0; i < args.length; i++) {
      json.push(args[i][0]);
    }

    if (jqXHRs[0].getResponseHeader('Date')) {
      // レスポンスヘッダから日付を取り出す
      _now = new Date(jqXHRs[0].getResponseHeader('Date'));
    }
    callback(json);
  });
}
```

うまくいった・・・かのように見えたがIEでブラウザの戻るを使用したときに、ローカルキャッシュが使用されるとレスポンスヘッダに Date: が無いことが分かった orz
日付を取るにはサーバーにアクセスしないといけないし、でも毎回やってると負荷が上がって貧弱なサーバーが死ぬかもだし・・・
~~CDNの小さなファイルを可変のパラメータ付けて読みこんじゃう？~~

とりあえず、Date: がないときだけクライアント時刻を使おう(￣▽￣；)
なにかスマートな解決方法があったら是非アドバイスをお願いします。


# とりあえず完成

JavaScriptのコードはサイト全体で1200ステップ。
C#で出力したJSONファイルは1400個。
いまのところテンポることもなく動いてます(ノ▽≦*)

スマホ版はスマホ持ってないので [Mobilizer](http://www.springbox.com/mobilizer/) っていうエミュレーター？で確認しながら作成して、最終的にスマホを複数台時間レンタルしているサービスを利用して動作確認しました。

作ってみた印象としては、スマホはCSSもJavaScriptもよく対応されていてあまり苦労することはなかったです。
むしろIE7/8/9が地獄でした。
こいつらのせいで、どれだけ苦しめられたことか・・・。
サイト作るのって簡単そうでかなり難しいですね(´・ω・`)