介绍Python的Django框架中的静态资源管理器django-pipeline
django-pipeline是一个Django下非常方便的静态资源管理app,尤其是1.2版本之后,利用django-staticfiles的collectstatic命令,在开发、部署环境下切换非常方便。
写codinn.com代码的时候,静态资源管理方面遇到了一些烦人的事情:
- 为了加速页面加载速度,浏览器会缓存静态文件,静态资源更新后,浏览器很可能从缓存提取过期的静态文件
- 自己写的CSS/JS要手工minify,非常麻烦
- 零碎的CSS/JS小文件太多
- CSS/JSminified之后,开发环境下调试起来很不方便
django-pipeline通过静态资源版本化、自动minify、分组合并CSS/JS文件、兼容django-staticfilesURL规则以及collectstatic命令。
slimit/jsmin
图个省心,我通常使用jsmin/cssmin这两个Pythonminifier:
PIPELINE_JS_COMPRESSOR='pipeline.compressors.jsmin.JSMinCompressor' PIPELINE_CSS_COMPRESSOR='pipeline.compressors.cssmin.CssminCompressor'
但是jsmin年久失修,实际使用结论是:jsmin是有bug的,jQuery开发库用jsminminify后被破坏,压根无法正常工作。但是jQuery官方minify之后的JS文件再用jsminminify之后却没有问题。
虽然有规避方案,但始终对jsmin不放心,索性改用slimit,暂时还没发现JS被破坏的问题。
django-pipeline未提供对slimit的支持,不过pipeline的扩展性还不错,写一个slimit扩展也是分钟的事情:
from__future__importabsolute_import frompipeline.compilersimportCompilerBase classSlimItCompiler(CompilerBase): """ JScompressorbasedonthePythonlibraryslimit (http://pypi.python.org/pypi/slimit/). """ defcompress_js(self,js): fromslimitimportminify returnminify(js)
将以上代码保存成slimit文件,扔在项目中的某个包目录下即可,再修改settings:
PIPELINE_JS_COMPRESSOR='lib.slimit.SlimItCompiler'
UnicodeDecodeError:'ascii'codeccan'tdecodebyte问题
启用django-pipeline后,执行manage.pycollectstatic如果碰到下面的错误提示:
File".../ENV/local/lib/python2.7/site-packages/django/contrib/staticfiles/storage.py",line226,inpost_process content=pattern.sub(converter,content) UnicodeDecodeError:'ascii'codeccan'tdecodebyte0xefinposition0:ordinalnotinrange(128)
八成是因为CSS文件中含有中文或其它非拉丁文字。我在使用@font-face图标文字时碰到了这个问题,这是djangostaticfiles包的一个bug,解决方法是修改/django/contrib/staticfiles/storage.py文件,把出错的那行代码:
content=original_file.read()
替换成:
content=original_file.read().decode('utf-8')
用这个方法的前提是:你的CSS文件必须保证utf-8编码,否则依然会出错。
PS,给Django项目提交了一个bug报告:https://code.djangoproject.com/ticket/18430