用 jinja2 来合并 css 或者 js

May 23, 2012

起因

因为在我的 http://digzhu.com 中,用了几个 UI 框架,各自有一些 css 和 js,再加上一些我自己的 css 和 js

于是要 import 10 多个 css 和 js

结果就是 YSlow 的评分只有 60 多.

我用的是 web.py,模板系统用了 jinja2, 一层层的 html 继承下来,很舒服. 但是也因为这样,为了明晰,每一层都有一个自己的 css 或者 js, 于是乎就蹦了那么多零散的 css 文件了

影响了站点打开的速度

人肉合并

人肉合并? 可以是可以,但是不利于我今后的文件修改

而且层次没那么清晰了,得不偿失. 这个方案废弃

jinja2

为毛不直接用 jinja2 的现成的模板系统呢?

设定自己的 render

默认的 web.py 针对 jinja2 的模板,只支持 html,看源码改之 可以看到, render_jinja 是从这个包引进来的

from web.contrib.template import render_jinja
gvim /usr/lib/python2.7/site-packages/web/contrib/template.py

看到

class render_jinja:
    """Rendering interface to Jinja2 Templates
    
    Example:

        render= render_jinja('templates')
        render.hello(name='jinja2')
    """
    def __init__(self, *a, **kwargs):
        extensions = kwargs.pop('extensions', [])
        globals = kwargs.pop('globals', {})

        from jinja2 import Environment,FileSystemLoader
        self._lookup = Environment(loader=FileSystemLoader(*a, **kwargs), extensions=extensions)
        self._lookup.globals.update(globals)
        
    def __getattr__(self, name):
        * Assuming all templates end with .html
        path = name + '.html'
        t = self._lookup.get_template(path)
        return t.render

很简单的一个 class,建立一个自己的 render.py

复制过来,html 改为 css

class render_css_jinja:
    """Rendering interface to Jinja2 Templates
    
    Example:

        render= render_jinja('templates')
        render.hello(name='jinja2')
    """
    def __init__(self, *a, **kwargs):
        extensions = kwargs.pop('extensions', [])
        globals = kwargs.pop('globals', {})

        from jinja2 import Environment,FileSystemLoader
        self._lookup = Environment(loader=FileSystemLoader(*a, **kwargs), extensions=extensions)
        self._lookup.globals.update(globals)
        
    def __getattr__(self, name):
        * Assuming all templates end with .html
        path = name + '.css'
        t = self._lookup.get_template(path)
        return t.render

再建一个获取 render 对象的函数,同时指定 template

def getCssRender():
    web.header('Content-Type', 'text/css')
    render = render_css_jinja('/home/bigzhu/portal2/static/css', encoding = 'utf-8')
    return render

最后建立一个响应 GET 的 class,暴露到 URL 上就行了

class GetCss:
    def GET(self):
        return render.getCssRender().all_css()

建立模板 css 文件

在 /home/bigzhu/portal2/static/css 下,建立自己的 all_css.css 文件

注意, include 文件的时候,是不允许指定路径的,只能用定义好的 tempalte 下的文件. 看了下源码,反正 jinja2 发现你指定路径就报错,不知道为什么.

没关系,那就都拷贝进来就是了

内容如下:

/* wijmo 
cp ../Wijmo.2.0.5/Wijmo-Open/development-bundle/themes/rocket/jquery-wijmo.css ./
cp ../Wijmo.2.0.5/Wijmo-Open/css/jquery.wijmo-open.2.0.5.css ./
  * */
{% include 'jquery-wijmo.css' %}
{% include 'jquery.wijmo-open.2.0.5.css' %}
/* yaml
cp ../yaml401-120306/yaml/core/base.min.css ./
cp ../yaml401-120306/yaml/navigation/hlist.css ./hlist.css
cp ../yaml401-120306/yaml/screen/screen-FULLPAGE-layout.css ./
cp ../yaml401-120306/yaml/forms/gray-theme.css ./
cp ../yaml401-120306/yaml/screen/typography.css ./
cp ../yaml401-120306/yaml/print/print.css ./
 *
 * */
{% include 'base.min.css' %}
{% include 'hlist.css' %}
{% include 'screen-FULLPAGE-layout.css' %}
{% include 'gray-theme.css' %}
{% include 'typography.css' %}
{% include 'print.css' %}

/* my css */
{% include 'button.css' %}
{% include 'menu.css' %}
{% include 'l_c_r.css' %}
{% include 'panel.css' %}

缓存

因为是通过 web.py 取到的 css 文件,没法在 nginx 上设定缓存时间了,别忘记设定缓存

web.header('Cache-Control', 'public, max-age=300')

因为我还要经常修改 css ,就暂时不缓存了.

js 的也是一样


comments powered by Disqus