2011 October 24th
WEB+DB PRESS Vol.65にCoffeeScriptの記事を書きました
WEB+DB PRESS Vol.65|gihyo.jp … 技術評論社
今回は「CoffeeScriptから学ぶJavaScriptプラクティス」と題して、CoffeeScriptが生成するJavaScriptについて、どうしてこういったJavaScriptになるのかという点を中心に解説しました。
CoffeeScriptには様々なJavaScriptの(バッド)ノウハウが詰め込まれています。生成されるJavaScriptを読んでいると、「やっぱりそうなるよね」と思わせることが多くてニヤニヤしてしまいます。
そもそも、CoffeeScriptは生成されるJavaScriptの読みやすさにかなり気を使っている点が、CoffeeScriptを気に入っている一番の理由です。(その点、Dartは…)
今回も結構苦労しましたが、なかなか面白い記事に仕上がったと思うので、手にとって頂ければ幸いです。
2011 October 4th
IE8のレンダリングモードと特定文字列によるクラッシュバグ
こんにちは、だいぶ久しぶりなブログ更新です。昨日、IE8のおもしろバグを発見してしまったので、さらしものにみなさんと共有したいと思います。
早速今回のバグの再現コードをみてみましょう。
<!DOCTYPE html>ܫ<br>1日
たったこれだけです。JavaScriptはおろか、CSSすらありません。ただのHTMLです。これだけでIE8の標準モードのレンダリングが壊れ、強制的に互換モードにフォールバックされます。
さらに次のようにmetaタグ(もしくはレスポンスヘッダ)でX-UA-CompatibleにIE=8やIE=edgeを指定して、標準モードでのレンダリングを強制していた場合はフォールバックが働かないので真っ白なページが表示されてしまいます。
<!DOCTYPE html>
<meta http-equiv="X-UA-Compatible" content="IE=8">ܫ<br>1日
<p>IE8では真っ白なページになる
このバグはIE8(正確にはWindows XPのIE8)だけで発生しており、IE6, 7, 9などでは発生しません。IE9のIE8モードでも発生しないので、MS的には修正済みなのか、たまたま直ったのかは、よくわかりません。
ちなみに、ܫというのはWindowsでは
のように表示され、
のような顔文字によく使われています。これと1日のような普通の文字の組み合わせで発生するので、実際に起こり得る組み合わせです。
今回は、このバグが発生するページと発生しないページの差分からなんとか原因を特定できましたが、正直予想し得ないバグですね。もっと追えば、より短い文字列で発生するかもしれませんし、全く別の文字列パターンでも発生するかもしれません。その辺は文字コードやWindows・IEのアレコレに詳しい方に勝手に期待しています。
2011 June 26th
AutoPatchWorkのサーバー周りのこと
地味に色々と調整しているのでまとめておきます。見よう見まねの継ぎ接ぎばかりですが…。
AutoPatchWorkはwedata(About - wedata)のAutoPagerize用SITEINFOを使わせて頂いていますが、wedataのサーバーは負荷に弱いので、SITEINFOは自前のサーバー(といっても安心のhetemlですが)に置いています。
hetemlサーバーでcronを設定して1時間に1回、SITEINFOを更新するようにしていて、AutoPatchWorkユーザーは一日に1回hetemlサーバーからSITEINFOを取得しています。
ただ、AutoPagerizeのSITEINFOは2MB近くあるので、1万人が毎日アクセスしたら転送量が20GBに達します(全員が毎日更新にくるわけではないので、実際はもっと少ないですが)。hetemlの転送量は「目安として 1日 20GB まで」(2011年6月27日時点。ちなみに以前は10GBだった)で、ChromeのAutoPatchWorkユーザーだけで6万人以上いるので余裕でアウトです(といっても、一度問い合わせてみたところ、目安を超えたら即制限がかかるようなことはないそうです)。
ただ、容量を節約するポイントは色々あって、まずオリジナルのSITEINFOは次のようなJSONデータです。
{ "name": "Google Search", "resource_url": "http:\/\/wedata.net\/items\/472", "updated_at": "2011-04-24T23:09:52+09:00", "created_by": "swdyh", "database_resource_url": "http:\/\/wedata.net\/databases\/AutoPagerize", "data": { "pageElement": "id(\"search\")\/div[ol or div]|id(\"res\")[not(@role)]\/div[ol or div]|id(\"ofr\")", "url": "^https?:\/\/[^.\/]+\\.google(?:\\.[^.\/]{2,3}){1,2}\/(?:c(?:se|ustom)|search|webhp|#)", "nextLink": "id(\"pnnext\")|id(\"navbar navcnt nav\")\/\/td[span]\/following-sibling::td[1]\/a|id(\"nn\")\/parent::a", "exampleUrl": "http:\/\/www.google.com\/search?q=AutoPagerize\r\nhttp:\/\/www.google.com\/cse?cref=http%3A%2F%2Fwww.guha.com%2Fcref_cse.xml&q=firefox&sa=Search&siteurl=www.google.co.jp%2Fcse%2Fdocs%2Fcref.html\r\nhttp:\/\/www.google.co.jp\/custom?q=firefox\r\nhttp:\/\/www.google.com\/webhp?hl=en#hl=en&expIds=17259,18167,25901,25980,26440,26459,26512&sugexp=ldymls&tok=So3knfbAtc2kJy-W-lXiWw&xhr=t&q=autopagerize&cp=10&pf=p&sclient=psy&safe=off&site=webhp&aq=f&aqi=g5&aql=&oq=autopageri&gs_rfai=&pbx=1&fp=6052204b889acdd8" }, "created_at": "2008-04-16T12:35:37+09:00" }
実際に使うのはdataの中身で、さらにexampleUrlなどはデバッグ用なので、普段は使用しません。つまり、こうできます。
{ "pageElement": "id(\"search\")\/div[ol or div]|id(\"res\")[not(@role)]\/div[ol or div]|id(\"ofr\")", "url": "^https?:\/\/[^.\/]+\\.google(?:\\.[^.\/]{2,3}){1,2}\/(?:c(?:se|ustom)|search|webhp|#)", "nextLink": "id(\"pnnext\")|id(\"navbar navcnt nav\")\/\/td[span]\/following-sibling::td[1]\/a|id(\"nn\")\/parent::a" }
これだけで1.9MBから715KBまで節約できます(ただ、元のデータを引けなくなるので、IDだけ追加しています)。結構節約できますが、まだ3万ユーザー程度しかカバーできません。
これにgzipを加えてみます。cronバッチの中でgzファイルを静的に作成して、.htaccessで次のように指定します。
RewriteEngine on
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule ^(.+)$ $1.gz
AddEncoding x-gzip .gz
- Accept-Encodingにgzipが含まれていて、
- リクエストされたファイル名+.gzなファイルが存在したら、
- URLを.gzつきに書き換え、
- ファイルタイプをjsonとして強制する
という指定です。
AddEncoding x-gzip .gz はレスポンスヘッダにContent-Encoging: gzipをつけて、ブラウザにgzipとして解釈させるようにしている(のだと思うのですが、あまり自信ない…)
gzip効果で、1.9MBのファイルは355KBに、715KBのファイルは152KBまで節約されます。
152KBならすくなくとも13万ユーザーまで大丈夫です。
実際、今のところ1日の転送量は8GB程度に抑えられています。
ついでにhetemlがmod_expiresにも対応していたので、ExpiresByTypeなんかも加えて、 http://ss-o.net/json/ の .htaccess はこんな感じになっています。
Options +Indexes
Header append Access-Control-Allow-Origin: *
ExpiresActive on
ExpiresByType application/json "access plus 12 hours"
ExpiresByType application/x-javascript "access plus 2 days"
<Files ~ "\.json">
ForceType "application/json; charset=utf-8"
</Files>
RewriteEngine on
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule ^(.+)$ $1.gz
AddEncoding x-gzip .gz
IndexIgnore .htaccess *.bak *.gz
IndexOptions FancyIndexing HTMLTable NameWidth=* XHTML
2011 June 21st
WEB+DB PRESS Vol.63からJavaScriptの連載始めました
WEB+DB PRESS Vol.63|gihyo.jp … 技術評論社
id:uupaaさんの後任な感じで、JavaScript周りのホットな話題・最新情報を中心に、書いていこうと思っています。
初回は例によってデバッグ周りの話を書きました。といってもまだブログでは触れていないスマートフォンでのデバッグ方法や、 prototype.jsからjQueryに移行するたったひとつの冴えたやりかた - 0xFFでちょっとだけ触れたonerrorの具体的な使い方などを解説しています。よろしければ手にとってみてください。って発売は24日でした…紛らわしい書き方してしまってごめんなさい。。
あわせて読みたい
- 作者: John Allspaw,Jesse Robbins,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/05/14
- メディア: 大型本
- 購入: 9人 クリック: 818回
- この商品を含むブログ (39件) を見る
- 作者: 佐々木達也
- 出版社/メーカー: 秀和システム
- 発売日: 2011/04
- メディア: 大型本
- 購入: 7人 クリック: 756回
- この商品を含むブログ (20件) を見る
2011 June 17th
君は3つのリロードを知っているか?
はい、今さら聞けないウェブ開発者の基礎知識のお時間です。
ブラウザには3つの読み込みモードがあることはご存知ですか?
2つくらいはわかるけど、3つ目が出てこないって方は少なくないかもしれません。
- リロード
- 一番オーソドックスなのがブラウザのリロードボタンを押したときの挙動ですね。普通ですね。
- スーパーリロード
- ブラウザによっては、スーパーリロードという機能を備えています。IEの場合Ctrl+F5(Ctrl+更新ボタン)、Firefoxの場合Ctrl+F5(Shift+更新ボタン)、Chromeの場合Shift+更新ボタン(Ctrl+Shift+R)などでスーパーリロードを呼び出すことができます。スーパーですね。
- ページ遷移(リフレッシュ)
- 3つ目はちょっと良い名前が思いつかないのですが、リロードではなく、通常の画面遷移での読み込みのことです。アドレスバーにフォーカスしてenterするといった方法で実現できます。むしろこれこそが普通です。
id:edvakfさん曰く、Operaにはリクエストを投げずに更新するRefresh Displayというアクションがあるらしい。確かにリフレッシュというのは適切な名前な気がする。
それぞれどう違うのか、特に1つ目と3つ目はどう違うのか不思議でしょうか?
ちゃんとリクエストの様子を眺めてみると違いがよく分かります。
リロード
スーパーリロード
ページ遷移
リロードは大元のHTMLを受け取ったら、そのページ内のリソースについてレスポンスヘッダを確認しに行っています。その結果304 Not Modifiedが帰ってきて、実際にはキャッシュを使っています。
対してスーパーリロードはキャッシュに関係なく、すべてのリソースを取得しなおしています。
そしてページ遷移時は、キャッシュがあり、Expireが効いている場合はそもそもリクエストを送っていません。完全にローカルキャッシュだけを使っています。
(ちなみに、ページを進んで(ブラウザの戻る機能で)戻ったときは大元のHTMLを含めてキャッシュが使われたりします。)
なお、当然ですがすべてのブラウザがこの3つのモードを持っているわけではありません。Operaにはスーパーリロードに相当する手段がなさそう(知らないだけかもしれませんが)だったりします。
というわけで、3つのリロードの違いを意識して、開発時に使い分けるのがウェブ開発者のたしなみです。




