
# 靜態文件
一如其名,靜態文件是那些不會改變的文件。一般情況下,在你的應用中,這包括CSS文件,Javascript文件和圖片。它也可以包括視頻文件和其他可能的東西。
## 組織你的靜態文件
我們將在應用的包中創建一個叫*static*的文件夾放置我們的靜態文件。
```
myapp/
__init__.py
static/
templates/
views/
models.py
run.py
```
*static/*里面的文件組織方式取決于個人的愛好。就我個人來說,如果第三方庫(比如jQuery, Bootstrap等等)跟自己的Javascript和CSS文件混起來,我會因此而不爽。所以,我要將第三方庫全放到一個*lib/*文件夾中。有時會用*vendor/*來代替*lib/*。
```
static/
css/
lib/
bootstrap.css
style.css
home.css
admin.css
js/
lib/
jquery.js
home.js
admin.js
img/
logo.svg
favicon.ico
```
### 提供一個favicon
用戶將通過yourapp.com/static/訪問你的靜態文件夾中的文件。默認下瀏覽器和其他軟件認為你的favicon位于yourapp.com/favicon.ico。要想解決這種不一致。你可以在站點模板的`<head>`部分添加下面內容。
```
<link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.ico') }}">
```
## 用Flask-Assets管理靜態文件
Flask-Assets是一個管理靜態文件的插件。它提供了兩種非常有用的特性。首先,它允許你在Python代碼中定義*多組*(bundles)可以同時插入你的模板的靜態文件。其次,它允許你預處理這些文件。這意味著你可以合并并壓縮你的CSS和Javascript文件,這樣用戶就會僅僅得到兩個壓縮后的文件(CSS和Javascript)而免于花費太多帶寬。你甚至可以從Sass,Less,CoffeeScript或別的源碼里編譯出最終產物。
下面是這一章中也做例子的靜態文件夾的基本結構。
_myapp/static/_
```
static/
css/
lib/
reset.css
common.css
home.css
admin.css
js/
lib/
jquery-1.10.2.js
Chart.js
home.js
admin.js
img/
logo.svg
favicon.ico
```
### 定義分組
我們的應用有兩部分:公共網站和管理面板(分別稱作"home"和"admin")。我們將定義四個分組來覆蓋它:每個部分有一個Javascript和一個CSS分組。我們將它們放入`util`包里的assets模塊。
_myapp/util/assets.py_
```
from flask_assets import Bundle, Environment
from .. import app
bundles = {
'home_js': Bundle(
'js/lib/jquery-1.10.2.js',
'js/home.js',
output='gen/home.js),
'home_css': Bundle(
'css/lib/reset.css',
'css/common.css',
'css/home.css',
output='gen/home.css),
'admin_js': Bundle(
'js/lib/jquery-1.10.2.js',
'js/lib/Chart.js',
'js/admin.js',
output='gen/admin.js),
'admin_css': Bundle(
'css/lib/reset.css',
'css/common.css',
'css/admin.css',
output='gen/admin.css)
}
assets = Environment(app)
assets.register(bundles)
```
Flask-Assets按照被列出來的順序合并你的文件。如果*admin.js*依賴*jquery-1.10.2.js*,確保jquery被列在前面。
我們通過字典來定義分組,這樣方便注冊它們。[webassets](https://github.com/miracle2k/webassets/blob),實際上是Flask-Assets的核心,提供了一系列方式來注冊分組,包括上面我們演示的以字典作參數的方法。(譯注:webassets之于Flask-Assets,正如SQLAlchemy之于Flask-SQLAlchemy。)
> **參見**
> webassets在這里注冊了分組:
> <https://github.com/miracle2k/webassets/blob/0.8/src/webassets/env.py#L380>
既然我們已經在`util.assets`中注冊了我們的分組,剩下的就是在\_\_init\_\_.py中,在app對象初始化之后,來導入這個模塊。
myapp/\_\_init\_\_.py
```
# [...] Initialize the app
from .util import assets
```
### 使用你的分組
下面是我們的例子中的模板文件夾:
_myapp/templates/_
```
templates/
home/
layout.html
index.html
about.html
admin/
layout.html
dash.html
stats.html
```
要使用我們的admin分組,我們將插入它們到admin部分的基礎模板 - *admin/layout.html* - 中。
myapp/templates/admin/layout.html
```
<!DOCTYPE html>
<html lang="en">
<head>
{% assets "admin_js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% assets "admin_css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" />
{% endassets %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
```
對于home分組,我們也同樣在*templates/home/layout.html*做一樣的處理。
### 使用過濾器
我們可以使用webassets過濾器來預處理我們的靜態文件。這將方便我們壓縮Javascript和CSS文件。現在修改下我們的代碼來實現這一點。
myapp/util/assets.py
```
# [...]
bundles = {
'home_js': Bundle(
'lib/jquery-1.10.2.js',
'js/home.js',
output='gen/home.js',
filters='jsmin'),
'home_css': Bundle(
'lib/reset.css',
'css/common.css',
'css/home.css',
output='gen/home.css',
filters='cssmin'),
'admin_js': Bundle(
'lib/jquery-1.10.2.js',
'lib/Chart.js',
'js/admin.js',
output='gen/admin.js',
filters='jsmin'),
'admin_css': Bundle(
'lib/reset.css',
'css/common.css',
'css/admin.css',
output='gen/admin.css',
filters='cssmin')
}
# [...]
```
> **注意**
> 要想使用`jsmin`和`cssmin`過濾器,你需要安裝jsmin和cssmin包(使用`pip install jsmin cssmin`)。確保把它們也加入到*requirements.txt*。
一旦模板已經渲染好,Flask-Assets將在合并的同時壓縮我們的文件,而且當其中一個源文件改變時,它會自動更新壓縮文件。
> **注意**
> 如果你在配置中設置`ASSETS_DEBUG = True`, Flask-Assets將獨立輸出每一個源文件而不會合并它們。
> **參見**
> 你可以使用Flask-Assets過濾器來自動編譯Sass,Less,CoffeeScript,和其他預處理器。來看下你還可以使用哪些過濾器: http://elsdoerfer.name/docs/webassets/builtin_filters.html#js-css-compilers
## 總結
* 靜態文件歸于*static/*文件夾。
* 將第三方庫跟你自己的靜態文件隔離開來。
* 在你的模板里指定你的favicon的路徑。
* 使用Flask-Assets來在模板插入你的靜態文件。
* Flask-Assets可以編譯,合并以及壓縮你的靜態文件。