まずここにある内容は、このページに全て書いてあります。この記事が古くなっている場合、直接こちらを読む方が正確です。
あと、私は Ember.js 学び始めたばかりの人間なので、もし内容におかしなところがあったら、ぜひご指摘ください。
hash sign がデフォルト
例えば、以下のように http://localhost/
でアクセス可能な普通に Ember アプリをつくると以下のような例の場合(サンプルは CoffeeScript で書いています)
window.App = Ember.Application.create()
App.Router.map ->
@route("about")
以下のような例の場合 link-to 'about'
は http://localhost/#/about
へのリンクになります。
<script type="text/x-handlebars" data-template-name="application">
<p>{{#link-to 'about'}} About {{/link-to}}</p>
<p>{{outlet}}</p>
</script>
http://localhost/#/about
にアクセスすると {{outlet}}
に about
と data-template-name が指定された handlebars のテンプレートを埋めた状態で表示されます。
これを http://localhost/about
へのリンクにする場合は、以下の二つのことが必要です。
hash sign? hashbang?
・・と、その前に少し余談ですが。
昔 twitter.com など多くのサイトが採用していた twitter.com/#!/foo のような URL を hashbang と呼びますが Ember のデフォルトは /#/foo なので hashbang ではなく hash sign と呼ぶようです。hashbang にしたいんだけど、という場合は以下のように HashLocation を拡張すると良いようです。
hash sign をやめる
HistoryLocation を使う
App.Router の設定をデフォルトの HashLocation から HistoryLocation に変更します。
window.App = Ember.Application.create()
App.Router.map ->
@route("about")
App.Router.reopen
location: 'history'
こうすると link-to 'about'
は http://localhost/about
に変わり、また表示も特に問題ないようです。ただ、これでめでたしめでたし・・とはまだいきません。
サーバサイドで /about への応答
別ブラウザや別タブから http://localhost/about
へアクセスしてみてください。先ほどは JavaScript History API のおかげでアクセスできていましたが、今回は Ember アプリが処理する前にサーバサイドが 404 Not Found で応答してしまいます。
ここにある注意書きはそういう意図ですね。
Keep in mind that your server must serve the Ember app at all the routes you define.
やるべきことは単純で http://localhost/about
へのアクセスに http://localhost/
と同じ Ember アプリを含むページを応答するだけです。
これでうまくいくようになりました。
また(当然と言えば当然ですが)サーバサイドの実装を持たず HTML ファイルだけで実装された Ember アプリの場合 HashLocation でなければうまく動作しないということがわかります。
ちょっと待って、古い IE のこと考えてる?
IE9 以下は JavaScript の history API をサポートしてないため HistoryLocation で IE9 からアクセス来ると NoneLocation になってしまい、うまくいかないようです。
それをよしなにやってくれるのが AutoLocation で、基本は HistoryLocation でふるまいつつ IE9 以下からのアクセスの場合は HashLocation で動作するようです(今 IE 9 環境が手元にないので実際に確認はしていないですが)。
最終的にはこのようになりました。
window.App = Ember.Application.create()
App.Router.map ->
@route("about")
App.Router.reopen
location: 'auto'