### 靜態文件和主動式文件緩存
你能通過在應用配置中指定 `static_path` 選項來提供靜態文件服務:
```
settings = {
"static_path": os.path.join(os.path.dirname(__file__), "static"),
"cookie_secret": "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
"login_url": "/login",
"xsrf_cookies": True,
}
application = tornado.web.Application([
(r"/", MainHandler),
(r"/login", LoginHandler),
(r"/(apple-touch-icon\.png)", tornado.web.StaticFileHandler, dict(path=settings['static_path'])),
], **settings)
```
這樣配置后,所有以 `/static/` 開頭的請求,都會直接訪問到指定的靜態文件目錄, 比如 http://localhost:8888/static/foo.png 會從指定的靜態文件目錄中訪問到 `foo.png` 這個文件。同時 `/robots.txt` 和 `/favicon.ico` 也是會自動作為靜態文件處理(即使它們不是以 `/static/` 開頭)。
在上述配置中,我們使用 `StaticFileHandler` 特別指定了讓 Tornado 從根目錄伺服 `apple-touch-icon.png` 這個文件,盡管它的物理位置還是在靜態文件目錄中。(正則表達式 的匹配分組的目的是向 `StaticFileHandler` 指定所請求的文件名稱,抓取到的分組會以 方法參數的形式傳遞給處理器。)通過相同的方式,你也可以從站點的更目錄伺服 `sitemap.xml` 文件。當然,你也可以通過在 HTML 中使用正確的 `<link />` 標簽來避免這樣的根目錄 文件偽造行為。
為了提高性能,在瀏覽器主動緩存靜態文件是個不錯的主意。這樣瀏覽器就不需要發送 不必要的 `If-Modified-Since` 和 `Etag` 請求,從而影響頁面的渲染速度。 Tornado 可以通過內建的“靜態內容分版(static content versioning)”來直接支持這種功能。
要使用這個功能,在模板中就不要直接使用靜態文件的 URL 地址了,你需要在 HTML 中使用 `static_url()` 這個方法來提供 URL 地址:
```
<html>
<head>
<title>FriendFeed - {{ _("Home") }}</title>
</head>
<body>
<div><img src="{{ static_url("images/logo.png") }}"/></div>
</body>
</html>
```
`static_url()` 函數會將相對地址轉成一個類似于 `/static/images/logo.png?v=aae54` 的 URI,`v` 參數是 `logo.png` 文件的散列值, Tornado 服務器會把它發給瀏覽器,并以此為依據讓瀏覽器對相關內容做永久緩存。
由于 `v` 的值是基于文件的內容計算出來的,如果你更新了文件,或者重啟了服務器 ,那么就會得到一個新的 `v` 值,這樣瀏覽器就會請求服務器以獲取新的文件內容。 如果文件的內容沒有改變,瀏覽器就會一直使用本地緩存的文件,這樣可以顯著提高頁 面的渲染速度。
在生產環境下,你可能會使用[nginx](http://nginx.net/)這樣的更有利于靜態文件 伺服的服務器,你可以將 Tornado 的文件緩存指定到任何靜態文件服務器上面,下面 是 FriendFeed 使用的 nginx 的相關配置:
```
location /static/ {
root /var/friendfeed/static;
if ($query_string) {
expires max;
}
}
```