Split documentation in pieces to be easier to read.
This commit is contained in:
47
docs/behind-the-scenes.txt
Normal file
47
docs/behind-the-scenes.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
Behind the scenes
|
||||
=================
|
||||
|
||||
This document assumes you already have an up and running instance of
|
||||
Django Compressor, and that you understand how to use it in your templates.
|
||||
The goal is to explain what the main template tag, {% compress %}, does
|
||||
behind the scenes, to help you debug performance problems for instance.
|
||||
|
||||
First step: Offline cache
|
||||
-------------------------
|
||||
|
||||
The first thing {% compress %} tries to do is get the offline cache for its
|
||||
nodelist if offline cache is activated. It doesn't parse, doesn't check the
|
||||
modified times of the files, doesn't even know which files are concerned
|
||||
actually, since it doesn't look inside the nodelist of the template block
|
||||
enclosed by the ``compress`` template tag. The cache should return the HTML
|
||||
containing the element code for the combined file or piece of code (which,
|
||||
if the cache key exists, is supposed to already exist on disk/custom storage).
|
||||
|
||||
Everything stops here if the cache entry exists.
|
||||
|
||||
Second step: parsing and file list
|
||||
----------------------------------
|
||||
|
||||
A compressor instance is created, which in turns instanciates the HTML parser.
|
||||
The parser is used to determine a file or code hunk list. Each file mtime is
|
||||
checked, first in cache and then on disk/storage, and this is used to
|
||||
determine an unique cache key.
|
||||
|
||||
Third step: Checking the "main" cache
|
||||
-------------------------------------
|
||||
|
||||
Compressor checks if it can get some info about the combined file/hunks
|
||||
corresponding to its instance, using the cache key obtained in the previous
|
||||
step. The cache content here will actually be the HTML containing the final
|
||||
element code, just like in the offline step before.
|
||||
|
||||
Everything stops here if the cache entry exists.
|
||||
|
||||
Fourth step: Generating the combined file if needed
|
||||
---------------------------------------------------
|
||||
|
||||
The file is generated if necessary. All precompilers are called and all
|
||||
filters are executed, and a hash is determined from the contents. This in
|
||||
turns helps determine the file name, which is only saved if it didn't exist
|
||||
already. Then the HTML output is returned (and also saved in the cache).
|
||||
And that's it!
|
508
docs/index.txt
508
docs/index.txt
@@ -1,203 +1,9 @@
|
||||
Django compressor
|
||||
=================
|
||||
Django Compressor
|
||||
=================
|
||||
|
||||
Compresses linked and inline JavaScript or CSS into a single cached file.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
* Install django_compressor with your favorite Python package manager::
|
||||
|
||||
pip install django_compressor
|
||||
|
||||
* Add ``'compressor'`` to your ``INSTALLED_APPS`` setting::
|
||||
|
||||
INSTALLED_APPS = (
|
||||
# other apps
|
||||
"compressor",
|
||||
)
|
||||
|
||||
* See the list of settings_ to modify django_compressor's default behaviour.
|
||||
|
||||
* In case you use Django 1.3's staticfiles_ contrib app (or its standalone
|
||||
clone django-staticfiles_) you have to add django_compressor's file finder
|
||||
to the ``STATICFILES_FINDERS`` setting::
|
||||
|
||||
STATICFILES_FINDERS = (
|
||||
# other finders..
|
||||
'compressor.finders.CompressorFinder',
|
||||
)
|
||||
|
||||
.. _staticfiles: http://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
|
||||
.. _django-staticfiles: http://pypi.python.org/pypi/django-staticfiles
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
{% compress <js/css> %}
|
||||
<html of inline or linked JS/CSS>
|
||||
{% endcompress %}
|
||||
|
||||
Examples
|
||||
^^^^^^^^
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" href="/static/css/one.css" type="text/css" charset="utf-8">
|
||||
<style type="text/css">p { border:5px solid green;}</style>
|
||||
<link rel="stylesheet" href="/static/css/two.css" type="text/css" charset="utf-8">
|
||||
{% endcompress %}
|
||||
|
||||
Which would be rendered something like:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
<link rel="stylesheet" href="/static/CACHE/css/f7c661b7a124.css" type="text/css" charset="utf-8">
|
||||
|
||||
or:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress js %}
|
||||
<script src="/static/js/one.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script type="text/javascript" charset="utf-8">obj.value = "value";</script>
|
||||
{% endcompress %}
|
||||
|
||||
Which would be rendered something like:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
<script type="text/javascript" src="/static/CACHE/js/3f33b9146e12.js" charset="utf-8"></script>
|
||||
|
||||
Linked files must be accesible via COMPRESS_URL_. If DEBUG is ``True``,
|
||||
off-site files will throw exceptions. If DEBUG is ``False`` they will be
|
||||
silently stripped.
|
||||
|
||||
If COMPRESS is ``False`` (defaults to the opposite of DEBUG) the ``compress``
|
||||
template tag simply returns exactly what it was given, to ease development.
|
||||
|
||||
.. warning::
|
||||
|
||||
For production sites it is **strongly recommended** to use a real cache
|
||||
backend such as memcached_ to speed up the checks of compressed files.
|
||||
Make sure you set your Django cache backend appropriately (also see
|
||||
COMPRESS_CACHE_BACKEND_ and Django's `caching documentation`_).
|
||||
|
||||
.. _memcached: http://memcached.org/
|
||||
.. _caching documentation: http://docs.djangoproject.com/en/1.2/topics/cache/#memcached
|
||||
|
||||
Remote storages
|
||||
---------------
|
||||
|
||||
In some cases it's useful to use a CDN_ for serving static files such as
|
||||
those generated by django_compressor. Due to the way django_compressor
|
||||
processes files, it requires the files to be processed (in the
|
||||
``{% compress %}`` block) to be available in a local file system cache.
|
||||
|
||||
django_compressor provides hooks to automatically have compressed files
|
||||
pushed to a remote storage backend. Simply use set the COMPRESS_STORAGE_
|
||||
setting to a storage backend that saves the result to a remote service.
|
||||
|
||||
So assuming your CDN is `Amazon S3`_, you can use the boto_ storage backend
|
||||
from the 3rd party app `django-storages`_. Some required settings are::
|
||||
|
||||
AWS_ACCESS_KEY_ID = 'XXXXXXXXXXXXXXXXXXXXX'
|
||||
AWS_SECRET_ACCESS_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
||||
AWS_STORAGE_BUCKET_NAME = 'compressor-test'
|
||||
|
||||
Next, you need to specify the new CDN base URL and update the URLs to the
|
||||
files in your templates which you want to compress::
|
||||
|
||||
COMPRESS_URL = "http://compressor-test.s3.amazon.com/"
|
||||
|
||||
.. note::
|
||||
|
||||
For staticfiles just set ``STATIC_URL = COMPRESS_URL``
|
||||
|
||||
The storage backend to save the compressed files needs to be changed, too::
|
||||
|
||||
COMPRESS_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
|
||||
|
||||
staticfiles
|
||||
^^^^^^^^^^^
|
||||
|
||||
If you are using Django 1.3's staticfiles_ contrib app or the standalone
|
||||
app django-staticfiles_, you'll need to use a temporary filesystem cache
|
||||
for django_compressor to know which files to compress. Since staticfiles
|
||||
provides a management command to collect static files from various
|
||||
locations which uses a storage backend, this is where both apps can be
|
||||
integrated.
|
||||
|
||||
First, make sure the COMPRESS_ROOT_ and STATIC_ROOT_ settings are equal
|
||||
since both apps need to look at the same directories when to do their job.
|
||||
|
||||
Secondly, you need to create a subclass of the remote storage backend
|
||||
you want to use; below is an example of the boto S3 storage backend
|
||||
from django-storages::
|
||||
|
||||
from django.core.files.storage import get_storage_class
|
||||
from storages.backends.s3boto import S3BotoStorage
|
||||
|
||||
class CachedS3BotoStorage(S3BotoStorage):
|
||||
"""
|
||||
S3 storage backend that saves the files locally, too.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CachedS3BotoStorage, self).__init__(*args, **kwargs)
|
||||
self.local_storage = get_storage_class(
|
||||
"compressor.storage.CompressorFileStorage")()
|
||||
|
||||
def save(self, name, content):
|
||||
name = super(CachedS3BotoStorage, self).save(name, content)
|
||||
self.local_storage._save(name, content)
|
||||
return name
|
||||
|
||||
Set your COMPRESS_STORAGE_ and STATICFILES_STORAGE_ settings to the
|
||||
dotted path of your custom cached storage backend,
|
||||
e.g. ``'mysite.storage.CachedS3BotoStorage'``.
|
||||
|
||||
To have Django correctly render the URLs to your static files, set the
|
||||
``STATIC_URL`` setting to the same value as COMPRESS_URL_ (e.g.
|
||||
``"http://compressor-test.s3.amazon.com/"``).
|
||||
|
||||
.. _CDN: http://en.wikipedia.org/wiki/Content_delivery_network
|
||||
.. _Amazon S3: https://s3.amazonaws.com/
|
||||
.. _boto: http://boto.cloudhackers.com/
|
||||
.. _django-storages: http://code.welldev.org/django-storages/
|
||||
.. _STATIC_ROOT: http://docs.djangoproject.com/en/dev/ref/settings/#std:setting-STATIC_ROOT
|
||||
.. _STATICFILES_STORAGE: http://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_STORAGE
|
||||
|
||||
CSS Notes
|
||||
---------
|
||||
|
||||
All relative ``url()`` bits specified in linked CSS files are automatically
|
||||
converted to absolute URLs while being processed. Any local absolute URLs (those
|
||||
starting with a ``'/'``) are left alone.
|
||||
|
||||
Stylesheets that are ``@import``'d are not compressed into the main file.
|
||||
They are left alone.
|
||||
|
||||
If the media attribute is set on <style> and <link> elements, a separate
|
||||
compressed file is created and linked for each media value you specified.
|
||||
This allows the media attribute to remain on the generated link element,
|
||||
instead of wrapping your CSS with @media blocks (which can break your own
|
||||
@media queries or @font-face declarations). It also allows browsers to avoid
|
||||
downloading CSS for irrelevant media types.
|
||||
|
||||
Recommendations
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
* Use only relative or full domain absolute URLs in your CSS files.
|
||||
* Avoid @import! Simply list all your CSS files in the HTML, they'll be combined anyway.
|
||||
|
||||
Why another static file combiner for Django?
|
||||
--------------------------------------------
|
||||
|
||||
@@ -207,13 +13,13 @@ Long version:
|
||||
|
||||
**JS/CSS belong in the templates**
|
||||
Every static combiner for Django I've seen makes you configure
|
||||
your static files in your settings.py. While that works, it doesn't make
|
||||
your static files in your ``settings.py``. While that works, it doesn't make
|
||||
sense. Static files are for display. And it's not even an option if your
|
||||
settings are in completely different repositories and use different deploy
|
||||
processes from the templates that depend on them.
|
||||
|
||||
**Flexibility**
|
||||
django_compressor doesn't care if different pages use different combinations
|
||||
Django Compressor doesn't care if different pages use different combinations
|
||||
of statics. It doesn't care if you use inline scripts or styles. It doesn't
|
||||
get in the way.
|
||||
|
||||
@@ -223,303 +29,15 @@ Long version:
|
||||
**Full test suite**
|
||||
I has one.
|
||||
|
||||
Settings
|
||||
--------
|
||||
Contents
|
||||
========
|
||||
|
||||
Django compressor has a number of settings that control its behavior.
|
||||
They've been given sensible defaults.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
COMPRESS
|
||||
^^^^^^^^
|
||||
installation
|
||||
usage
|
||||
settings
|
||||
remote-storages
|
||||
behind-the-scenes
|
||||
|
||||
:Default: the opposite of ``DEBUG``
|
||||
|
||||
Boolean that decides if compression will happen.
|
||||
|
||||
COMPRESS_URL
|
||||
^^^^^^^^^^^^
|
||||
|
||||
:Default: ``STATIC_URL`` (``MEDIA_URL`` for older Django versions)
|
||||
|
||||
Controls the URL that linked files will be read from and compressed files
|
||||
will be written to.
|
||||
|
||||
.. note::
|
||||
|
||||
This setting defaults to ``MEDIA_URL`` in case ``STATIC_URL``
|
||||
is not given or empty, e.g. on older Django versions (<1.3).
|
||||
|
||||
COMPRESS_ROOT
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``STATIC_ROOT`` (``MEDIA_ROOT`` for older Django versions)
|
||||
|
||||
Controls the absolute file path that linked static will be read from and
|
||||
compressed static will be written to when using the default COMPRESS_STORAGE_
|
||||
``compressor.storage.CompressorFileStorage``.
|
||||
|
||||
.. note::
|
||||
|
||||
This setting defaults to ``MEDIA_ROOT`` in case ``STATIC_ROOT``
|
||||
is not given, e.g. on older Django versions (<1.3).
|
||||
|
||||
COMPRESS_OUTPUT_DIR
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``'CACHE'``
|
||||
|
||||
Controls the directory inside COMPRESS_ROOT_ that compressed files will
|
||||
be written to.
|
||||
|
||||
COMPRESS_CSS_FILTERS
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``['compressor.filters.css_default.CssAbsoluteFilter']``
|
||||
|
||||
A list of filters that will be applied to CSS.
|
||||
|
||||
COMPRESS_JS_FILTERS
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``['compressor.filters.jsmin.JSMinFilter']``
|
||||
|
||||
A list of filters that will be applied to javascript.
|
||||
|
||||
COMPRESS_PRECOMPILERS
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``()``
|
||||
|
||||
An iterable of two-tuples whose first item is the mimetype of the files or
|
||||
hunks you want to compile with the command specified as the second item:
|
||||
|
||||
* mimetype
|
||||
The mimetype of the file or inline code should that should be compiled.
|
||||
|
||||
* command
|
||||
The command to call on each of the files. Modern Python string
|
||||
formatting will be provided for the two placeholders ``{infile}`` and
|
||||
``{outfile}`` whose existence in the command string also triggers the
|
||||
actual creation of those temporary files. If not given in the command
|
||||
string, django_compressor will use ``stdin`` and ``stdout`` respectively
|
||||
instead.
|
||||
|
||||
Example::
|
||||
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/coffeescript', 'coffee --compile --stdio'),
|
||||
('text/less', 'lessc {infile} {outfile}'),
|
||||
('text/x-sass', 'sass {infile} {outfile}'),
|
||||
('text/x-scss', 'sass --scss {infile} {outfile}'),
|
||||
)
|
||||
|
||||
With that setting (and CoffeeScript_ installed), you could add the following
|
||||
code to your templates:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress js %}
|
||||
<script type="text/coffeescript" charset="utf-8" src="/static/js/awesome.coffee" />
|
||||
<script type="text/coffeescript" charset="utf-8">
|
||||
# Functions:
|
||||
square = (x) -> x * x
|
||||
</script>
|
||||
{% endcompress %}
|
||||
|
||||
This would give you something like this::
|
||||
|
||||
<script type="text/javascript" src="/static/CACHE/js/8dd1a2872443.js" charset="utf-8"></script>
|
||||
|
||||
The same works for less_, too:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress css %}
|
||||
<link type="text/less" rel="stylesheet" href="/static/css/styles.less" charset="utf-8">
|
||||
<style type="text/less">
|
||||
@color: #4D926F;
|
||||
|
||||
#header {
|
||||
color: @color;
|
||||
}
|
||||
</style>
|
||||
{% endcompress %}
|
||||
|
||||
Which would be rendered something like::
|
||||
|
||||
<link rel="stylesheet" href="/static/CACHE/css/8ccf8d877f18.css" type="text/css" charset="utf-8">
|
||||
|
||||
.. _less: http://lesscss.org/
|
||||
.. _CoffeeScript: http://jashkenas.github.com/coffee-script/
|
||||
|
||||
COMPRESS_STORAGE
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``'compressor.storage.CompressorFileStorage'``
|
||||
|
||||
The dotted path to a Django Storage backend to be used to save the
|
||||
compressed files.
|
||||
|
||||
``compressor`` ships with one additional storage backend:
|
||||
|
||||
* ``'compressor.storage.GzipCompressorFileStorage'``
|
||||
|
||||
A subclass of the default storage backend, which will additionally
|
||||
create ``*.gz`` files of each of the compressed files.
|
||||
|
||||
COMPRESS_PARSER
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``'compressor.parser.BeautifulSoupParser'``
|
||||
|
||||
The backend to use when parsing the JavaScript or Stylesheet files.
|
||||
The backends included in ``compressor``:
|
||||
|
||||
- ``compressor.parser.BeautifulSoupParser``
|
||||
- ``compressor.parser.LxmlParser``
|
||||
|
||||
See `Dependencies`_ for more info about the packages you need for each parser.
|
||||
|
||||
COMPRESS_CACHE_BACKEND
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``"default"`` or ``CACHE_BACKEND``
|
||||
|
||||
The backend to use for caching, in case you want to use a different cache
|
||||
backend for compressor.
|
||||
|
||||
If you have set the ``CACHES`` setting (new in Django 1.3),
|
||||
``COMPRESS_CACHE_BACKEND`` defaults to ``"default"``, which is the alias for
|
||||
the default cache backend. You can set it to a different alias that you have
|
||||
configured in your ``CACHES`` setting.
|
||||
|
||||
If you have not set ``CACHES`` and are using the old ``CACHE_BACKEND``
|
||||
setting, ``COMPRESS_CACHE_BACKEND`` defaults to the ``CACHE_BACKEND`` setting.
|
||||
|
||||
COMPRESS_REBUILD_TIMEOUT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``2592000`` (30 days in seconds)
|
||||
|
||||
The period of time after which the compressed files are rebuilt even if
|
||||
no file changes are detected.
|
||||
|
||||
COMPRESS_MINT_DELAY
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``30`` (seconds)
|
||||
|
||||
The upper bound on how long any compression should take to run. Prevents
|
||||
dog piling, should be a lot smaller than COMPRESS_REBUILD_TIMEOUT_.
|
||||
|
||||
COMPRESS_MTIME_DELAY
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``10``
|
||||
|
||||
The amount of time (in seconds) to cache the modification timestamp of a
|
||||
file. Disabled by default. Should be smaller than COMPRESS_REBUILD_TIMEOUT_
|
||||
and COMPRESS_MINT_DELAY_.
|
||||
|
||||
COMPRESS_OFFLINE
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``False``
|
||||
|
||||
Boolean that decides if compression should also be done outside of the
|
||||
request/response loop -- independent from user requests. This allows to
|
||||
pre-compress CSS and JavaScript files and works just like the automatic
|
||||
compression with the ``{% compress %}`` tag.
|
||||
|
||||
To compress the files "offline" and update the offline cache you have
|
||||
to use the ``compress`` management command, e.g. during deployment.
|
||||
In case you don't use the ``compressor`` management command ``compressor``
|
||||
will automatically fallback to the automatic compression.
|
||||
|
||||
It'll will look in the templates that can be found with the template
|
||||
loader you specify in ``TEMPLATE_LOADERS`` for ``{% compress %}`` blocks
|
||||
and use COMPRESS_OFFLINE_CONTEXT_ to render its content. So if you use
|
||||
any variables inside the ``{% compress %}`` blocks, make sure to list
|
||||
all values you require in COMPRESS_OFFLINE_CONTEXT_.
|
||||
|
||||
The result of running the ``compress`` management command will be saved
|
||||
in the cache as defined in COMPRESS_CACHE_BACKEND_ for the number of
|
||||
seconds defined in COMPRESS_OFFLINE_TIMEOUT_.
|
||||
|
||||
COMPRESS_OFFLINE_TIMEOUT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``31536000`` (1 year in seconds)
|
||||
|
||||
The period of time with which the ``compress`` management command stores
|
||||
the pre-compressed the contents of ``{% compress %}`` template tags in
|
||||
the cache.
|
||||
|
||||
COMPRESS_OFFLINE_CONTEXT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``{'MEDIA_URL': settings.MEDIA_URL}``
|
||||
|
||||
The context to be used by the ``compress`` management command when rendering
|
||||
the contents of ``{% compress %}`` template tags and saving the result in the
|
||||
offline cache. It's similar to a template context and should be used if a
|
||||
variable is used in the blocks, e.g.:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
{% compress js %}
|
||||
<script src="{{ path_to_files }}js/one.js" type="text/javascript" charset="utf-8"></script>
|
||||
{% endcompress %}
|
||||
|
||||
Since this template requires a variable (``path_to_files``) you need to
|
||||
specify this in your settings before using the ``compress`` management
|
||||
command::
|
||||
|
||||
COMPRESS_OFFLINE_CONTEXT = {
|
||||
'path_to_files': '/static/js/',
|
||||
}
|
||||
|
||||
If not specified the COMPRESS_OFFLINE_CONTEXT will fall back to contain
|
||||
the commonly used setting to refer to saved files ``MEDIA_URL``.
|
||||
|
||||
For forward compatibility ``compressor`` will also add the ``STATIC_URL``
|
||||
setting (added in Django 1.3) to the COMPRESS_OFFLINE_CONTEXT_ if it's set.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
* BeautifulSoup_ (for the default ``compressor.parser.BeautifulSoupParser``)
|
||||
|
||||
::
|
||||
|
||||
pip install BeautifulSoup
|
||||
|
||||
* lxml_ (for the optional ``compressor.parser.LxmlParser``, requires libxml2_)
|
||||
|
||||
::
|
||||
|
||||
STATIC_DEPS=true pip install lxml
|
||||
|
||||
.. _BeautifulSoup: http://www.crummy.com/software/BeautifulSoup/
|
||||
.. _lxml: http://codespeak.net/lxml/
|
||||
.. _libxml2: http://xmlsoft.org/
|
||||
|
||||
Deprecation
|
||||
-----------
|
||||
|
||||
This section lists features and settings that are deprecated or removed
|
||||
in newer versions of django_compressor.
|
||||
|
||||
* ``COMPRESS_LESSC_BINARY``
|
||||
Superseded by the COMPRESS_PRECOMPILERS_ setting. Just make sure to
|
||||
use the correct mimetype when linking to less files or adding inline
|
||||
code and add the following to your settings::
|
||||
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/less', 'lessc {infile} {outfile}'),
|
||||
)
|
||||
|
68
docs/installation.txt
Normal file
68
docs/installation.txt
Normal file
@@ -0,0 +1,68 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
* Install Django Compressor with your favorite Python package manager::
|
||||
|
||||
pip install django_compressor
|
||||
|
||||
* Add ``'compressor'`` to your ``INSTALLED_APPS`` setting::
|
||||
|
||||
INSTALLED_APPS = (
|
||||
# other apps
|
||||
"compressor",
|
||||
)
|
||||
|
||||
* See the list of :ref:`settings` to modify Django Compressor's
|
||||
default behaviour and make adjustements for your website.
|
||||
|
||||
* In case you use Django 1.3's staticfiles_ contrib app (or its standalone
|
||||
clone django-staticfiles_) you have to add django_compressor's file finder
|
||||
to the ``STATICFILES_FINDERS`` setting::
|
||||
|
||||
STATICFILES_FINDERS = (
|
||||
# other finders..
|
||||
'compressor.finders.CompressorFinder',
|
||||
)
|
||||
|
||||
.. _staticfiles: http://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
|
||||
.. _django-staticfiles: http://pypi.python.org/pypi/django-staticfiles
|
||||
|
||||
.. _dependencies:
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
BeautifulSoup_
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
for the default :ref:`parser <compress_parser>`
|
||||
``compressor.parser.BeautifulSoupParser``::
|
||||
|
||||
pip install BeautifulSoup
|
||||
|
||||
lxml_ (optional)
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
for the optional :ref:`parser <compress_parser>`
|
||||
``compressor.parser.LxmlParser``, also requires libxml2_::
|
||||
|
||||
STATIC_DEPS=true pip install lxml
|
||||
|
||||
.. _BeautifulSoup: http://www.crummy.com/software/BeautifulSoup/
|
||||
.. _lxml: http://codespeak.net/lxml/
|
||||
.. _libxml2: http://xmlsoft.org/
|
||||
|
||||
Deprecation
|
||||
-----------
|
||||
|
||||
This section lists features and settings that are deprecated or removed
|
||||
in newer versions of Django Compressor.
|
||||
|
||||
* ``COMPRESS_LESSC_BINARY``
|
||||
Superseded by the :ref:`COMPRESS_PRECOMPILERS <compress_precompilers>`
|
||||
setting. Just make sure to use the correct mimetype when linking to less
|
||||
files or adding inline code and add the following to your settings::
|
||||
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/less', 'lessc {infile} {outfile}'),
|
||||
)
|
84
docs/remote-storages.txt
Normal file
84
docs/remote-storages.txt
Normal file
@@ -0,0 +1,84 @@
|
||||
Remote storages
|
||||
---------------
|
||||
|
||||
In some cases it's useful to use a CDN_ for serving static files such as
|
||||
those generated by Django Compressor. Due to the way Django Compressor
|
||||
processes files, it requires the files to be processed (in the
|
||||
``{% compress %}`` block) to be available in a local file system cache.
|
||||
|
||||
Django Compressor provides hooks to automatically have compressed files
|
||||
pushed to a remote storage backend. Simply
|
||||
:ref:`set the storage backend <compress_storage>` that saves the result to a
|
||||
remote service.
|
||||
|
||||
So assuming your CDN is `Amazon S3`_, you can use the boto_ storage backend
|
||||
from the 3rd party app `django-storages`_. Some required settings are::
|
||||
|
||||
AWS_ACCESS_KEY_ID = 'XXXXXXXXXXXXXXXXXXXXX'
|
||||
AWS_SECRET_ACCESS_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
||||
AWS_STORAGE_BUCKET_NAME = 'compressor-test'
|
||||
|
||||
Next, you need to specify the new CDN base URL and update the URLs to the
|
||||
files in your templates which you want to compress::
|
||||
|
||||
COMPRESS_URL = "http://compressor-test.s3.amazon.com/"
|
||||
|
||||
.. note::
|
||||
|
||||
For staticfiles just set ``STATIC_URL = COMPRESS_URL``
|
||||
|
||||
The storage backend to save the compressed files needs to be changed, too::
|
||||
|
||||
COMPRESS_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
|
||||
|
||||
Using staticfiles
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you are using Django 1.3's staticfiles_ contrib app or the standalone
|
||||
app django-staticfiles_, you'll need to use a temporary filesystem cache
|
||||
for Django Compressor to know which files to compress. Since staticfiles
|
||||
provides a management command to collect static files from various
|
||||
locations which uses a storage backend, this is where both apps can be
|
||||
integrated.
|
||||
|
||||
#. Make sure the :ref:`COMPRESS_ROOT <compress_root>` and STATIC_ROOT_
|
||||
settings are equal since both apps need to look at the same directories
|
||||
when to do their job.
|
||||
|
||||
#. You need to create a subclass of the remote storage backend you want
|
||||
to use; below is an example of the boto S3 storage backend from
|
||||
django-storages_::
|
||||
|
||||
from django.core.files.storage import get_storage_class
|
||||
from storages.backends.s3boto import S3BotoStorage
|
||||
|
||||
class CachedS3BotoStorage(S3BotoStorage):
|
||||
"""
|
||||
S3 storage backend that saves the files locally, too.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CachedS3BotoStorage, self).__init__(*args, **kwargs)
|
||||
self.local_storage = get_storage_class(
|
||||
"compressor.storage.CompressorFileStorage")()
|
||||
|
||||
def save(self, name, content):
|
||||
name = super(CachedS3BotoStorage, self).save(name, content)
|
||||
self.local_storage._save(name, content)
|
||||
return name
|
||||
|
||||
#. Set your :ref:`COMPRESS_STORAGE <compress_storage>` and STATICFILES_STORAGE_
|
||||
settings to the dotted path of your custom cached storage backend, e.g.
|
||||
``'mysite.storage.CachedS3BotoStorage'``.
|
||||
|
||||
#. To have Django correctly render the URLs to your static files, set the
|
||||
STATIC_URL_ setting to the same value as :ref:`COMPRESS_URL <compress_url>`
|
||||
(e.g. ``"http://compressor-test.s3.amazon.com/"``).
|
||||
|
||||
.. _CDN: http://en.wikipedia.org/wiki/Content_delivery_network
|
||||
.. _Amazon S3: https://s3.amazonaws.com/
|
||||
.. _boto: http://boto.cloudhackers.com/
|
||||
.. _django-storages: http://code.welldev.org/django-storages/
|
||||
.. _django-staticfiles: http://github.com/jezdez/django-staticfiles/
|
||||
.. _STATIC_ROOT: http://docs.djangoproject.com/en/dev/ref/settings/#static-root
|
||||
.. _STATIC_URL: http://docs.djangoproject.com/en/dev/ref/settings/#static-url
|
||||
.. _STATICFILES_STORAGE: http://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-storage
|
284
docs/settings.txt
Normal file
284
docs/settings.txt
Normal file
@@ -0,0 +1,284 @@
|
||||
.. _settings:
|
||||
|
||||
Settings
|
||||
--------
|
||||
|
||||
Django Compressor has a number of settings that control its behavior.
|
||||
They've been given sensible defaults.
|
||||
|
||||
.. _compress:
|
||||
|
||||
COMPRESS
|
||||
^^^^^^^^
|
||||
|
||||
:Default: the opposite of ``DEBUG``
|
||||
|
||||
Boolean that decides if compression will happen.
|
||||
|
||||
.. _compress_url:
|
||||
|
||||
COMPRESS_URL
|
||||
^^^^^^^^^^^^
|
||||
|
||||
:Default: ``STATIC_URL`` (``MEDIA_URL`` for older Django versions)
|
||||
|
||||
Controls the URL that linked files will be read from and compressed files
|
||||
will be written to.
|
||||
|
||||
.. note::
|
||||
|
||||
This setting defaults to ``MEDIA_URL`` in case ``STATIC_URL``
|
||||
is not given or empty, e.g. on older Django versions (<1.3).
|
||||
|
||||
.. _compress_root:
|
||||
|
||||
COMPRESS_ROOT
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``STATIC_ROOT`` (``MEDIA_ROOT`` for older Django versions)
|
||||
|
||||
Controls the absolute file path that linked static will be read from and
|
||||
compressed static will be written to when using the default COMPRESS_STORAGE_
|
||||
``compressor.storage.CompressorFileStorage``.
|
||||
|
||||
.. note::
|
||||
|
||||
This setting defaults to ``MEDIA_ROOT`` in case ``STATIC_ROOT``
|
||||
is not given, e.g. on older Django versions (<1.3).
|
||||
|
||||
COMPRESS_OUTPUT_DIR
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``'CACHE'``
|
||||
|
||||
Controls the directory inside COMPRESS_ROOT_ that compressed files will
|
||||
be written to.
|
||||
|
||||
COMPRESS_CSS_FILTERS
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``['compressor.filters.css_default.CssAbsoluteFilter']``
|
||||
|
||||
A list of filters that will be applied to CSS.
|
||||
|
||||
COMPRESS_JS_FILTERS
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``['compressor.filters.jsmin.JSMinFilter']``
|
||||
|
||||
A list of filters that will be applied to javascript.
|
||||
|
||||
.. _compress_precompilers:
|
||||
|
||||
COMPRESS_PRECOMPILERS
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``()``
|
||||
|
||||
An iterable of two-tuples whose first item is the mimetype of the files or
|
||||
hunks you want to compile with the command specified as the second item:
|
||||
|
||||
#. mimetype
|
||||
The mimetype of the file or inline code should that should be compiled.
|
||||
|
||||
#. command
|
||||
The command to call on each of the files. Modern Python string
|
||||
formatting will be provided for the two placeholders ``{infile}`` and
|
||||
``{outfile}`` whose existence in the command string also triggers the
|
||||
actual creation of those temporary files. If not given in the command
|
||||
string, Django Compressor will use ``stdin`` and ``stdout`` respectively
|
||||
instead.
|
||||
|
||||
Example::
|
||||
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/coffeescript', 'coffee --compile --stdio'),
|
||||
('text/less', 'lessc {infile} {outfile}'),
|
||||
('text/x-sass', 'sass {infile} {outfile}'),
|
||||
('text/x-scss', 'sass --scss {infile} {outfile}'),
|
||||
)
|
||||
|
||||
With that setting (and CoffeeScript_ installed), you could add the following
|
||||
code to your templates:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress js %}
|
||||
<script type="text/coffeescript" charset="utf-8" src="/static/js/awesome.coffee" />
|
||||
<script type="text/coffeescript" charset="utf-8">
|
||||
# Functions:
|
||||
square = (x) -> x * x
|
||||
</script>
|
||||
{% endcompress %}
|
||||
|
||||
This would give you something like this::
|
||||
|
||||
<script type="text/javascript" src="/static/CACHE/js/8dd1a2872443.js" charset="utf-8"></script>
|
||||
|
||||
The same works for less_, too:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress css %}
|
||||
<link type="text/less" rel="stylesheet" href="/static/css/styles.less" charset="utf-8">
|
||||
<style type="text/less">
|
||||
@color: #4D926F;
|
||||
|
||||
#header {
|
||||
color: @color;
|
||||
}
|
||||
</style>
|
||||
{% endcompress %}
|
||||
|
||||
Which would be rendered something like::
|
||||
|
||||
<link rel="stylesheet" href="/static/CACHE/css/8ccf8d877f18.css" type="text/css" charset="utf-8">
|
||||
|
||||
.. _less: http://lesscss.org/
|
||||
.. _CoffeeScript: http://jashkenas.github.com/coffee-script/
|
||||
|
||||
.. _compress_storage:
|
||||
|
||||
COMPRESS_STORAGE
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``'compressor.storage.CompressorFileStorage'``
|
||||
|
||||
The dotted path to a Django Storage backend to be used to save the
|
||||
compressed files.
|
||||
|
||||
Django Compressor ships with one additional storage backend:
|
||||
|
||||
* ``'compressor.storage.GzipCompressorFileStorage'``
|
||||
|
||||
A subclass of the default storage backend, which will additionally
|
||||
create ``*.gz`` files of each of the compressed files.
|
||||
|
||||
.. _compress_parser:
|
||||
|
||||
COMPRESS_PARSER
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``'compressor.parser.BeautifulSoupParser'``
|
||||
|
||||
The backend to use when parsing the JavaScript or Stylesheet files.
|
||||
The backends included in Django Compressor:
|
||||
|
||||
- ``compressor.parser.BeautifulSoupParser``
|
||||
- ``compressor.parser.LxmlParser``
|
||||
|
||||
See :ref:`dependencies` for more info about the packages you need
|
||||
for each parser.
|
||||
|
||||
.. _compress_cache_backend:
|
||||
|
||||
COMPRESS_CACHE_BACKEND
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``"default"`` or ``CACHE_BACKEND``
|
||||
|
||||
The backend to use for caching, in case you want to use a different cache
|
||||
backend for Django Compressor.
|
||||
|
||||
If you have set the ``CACHES`` setting (new in Django 1.3),
|
||||
``COMPRESS_CACHE_BACKEND`` defaults to ``"default"``, which is the alias for
|
||||
the default cache backend. You can set it to a different alias that you have
|
||||
configured in your ``CACHES`` setting.
|
||||
|
||||
If you have not set ``CACHES`` and are using the old ``CACHE_BACKEND``
|
||||
setting, ``COMPRESS_CACHE_BACKEND`` defaults to the ``CACHE_BACKEND`` setting.
|
||||
|
||||
COMPRESS_REBUILD_TIMEOUT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``2592000`` (30 days in seconds)
|
||||
|
||||
The period of time after which the compressed files are rebuilt even if
|
||||
no file changes are detected.
|
||||
|
||||
COMPRESS_MINT_DELAY
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``30`` (seconds)
|
||||
|
||||
The upper bound on how long any compression should take to run. Prevents
|
||||
dog piling, should be a lot smaller than COMPRESS_REBUILD_TIMEOUT_.
|
||||
|
||||
COMPRESS_MTIME_DELAY
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``10``
|
||||
|
||||
The amount of time (in seconds) to cache the modification timestamp of a
|
||||
file. Disabled by default. Should be smaller than COMPRESS_REBUILD_TIMEOUT_
|
||||
and COMPRESS_MINT_DELAY_.
|
||||
|
||||
COMPRESS_OFFLINE
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``False``
|
||||
|
||||
Boolean that decides if compression should also be done outside of the
|
||||
request/response loop -- independent from user requests. This allows to
|
||||
pre-compress CSS and JavaScript files and works just like the automatic
|
||||
compression with the ``{% compress %}`` tag.
|
||||
|
||||
To compress the files "offline" and update the offline cache you have
|
||||
to use the ``compress`` management command, e.g. during deployment.
|
||||
In case you don't use the ``compress`` management command, Django
|
||||
Compressor will automatically fallback to the automatic compression.
|
||||
|
||||
It'll will look in the templates that can be found with the template
|
||||
loader you specify in ``TEMPLATE_LOADERS`` for ``{% compress %}`` blocks
|
||||
and use COMPRESS_OFFLINE_CONTEXT_ to render its content. So if you use
|
||||
any variables inside the ``{% compress %}`` blocks, make sure to list
|
||||
all values you require in COMPRESS_OFFLINE_CONTEXT_.
|
||||
|
||||
The result of running the ``compress`` management command will be saved
|
||||
in the cache as defined in COMPRESS_CACHE_BACKEND_ for the number of
|
||||
seconds defined in COMPRESS_OFFLINE_TIMEOUT_.
|
||||
|
||||
COMPRESS_OFFLINE_TIMEOUT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``31536000`` (1 year in seconds)
|
||||
|
||||
The period of time with which the ``compress`` management command stores
|
||||
the pre-compressed the contents of ``{% compress %}`` template tags in
|
||||
the cache.
|
||||
|
||||
COMPRESS_OFFLINE_CONTEXT
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Default: ``{'MEDIA_URL': settings.MEDIA_URL}``
|
||||
|
||||
The context to be used by the ``compress`` management command when rendering
|
||||
the contents of ``{% compress %}`` template tags and saving the result in the
|
||||
offline cache. It's similar to a template context and should be used if a
|
||||
variable is used in the blocks, e.g.:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
{% compress js %}
|
||||
<script src="{{ path_to_files }}js/one.js" type="text/javascript" charset="utf-8"></script>
|
||||
{% endcompress %}
|
||||
|
||||
Since this template requires a variable (``path_to_files``) you need to
|
||||
specify this in your settings before using the ``compress`` management
|
||||
command::
|
||||
|
||||
COMPRESS_OFFLINE_CONTEXT = {
|
||||
'path_to_files': '/static/js/',
|
||||
}
|
||||
|
||||
If not specified the COMPRESS_OFFLINE_CONTEXT will fall back to contain
|
||||
the commonly used setting to refer to saved files ``MEDIA_URL``.
|
||||
|
||||
For forward compatibility Django Compressor will also add the ``STATIC_URL``
|
||||
setting (added in Django 1.3) to the COMPRESS_OFFLINE_CONTEXT_ if it's
|
||||
available.
|
87
docs/usage.txt
Normal file
87
docs/usage.txt
Normal file
@@ -0,0 +1,87 @@
|
||||
Usage
|
||||
=====
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
{% compress <js/css> %}
|
||||
<html of inline or linked JS/CSS>
|
||||
{% endcompress %}
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" href="/static/css/one.css" type="text/css" charset="utf-8">
|
||||
<style type="text/css">p { border:5px solid green;}</style>
|
||||
<link rel="stylesheet" href="/static/css/two.css" type="text/css" charset="utf-8">
|
||||
{% endcompress %}
|
||||
|
||||
Which would be rendered something like:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
<link rel="stylesheet" href="/static/CACHE/css/f7c661b7a124.css" type="text/css" charset="utf-8">
|
||||
|
||||
or:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress js %}
|
||||
<script src="/static/js/one.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script type="text/javascript" charset="utf-8">obj.value = "value";</script>
|
||||
{% endcompress %}
|
||||
|
||||
Which would be rendered something like:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
<script type="text/javascript" src="/static/CACHE/js/3f33b9146e12.js" charset="utf-8"></script>
|
||||
|
||||
Linked files must be accesible via :ref:`COMPRESS_URL <compress_url>`.
|
||||
If DEBUG is ``True``, off-site files will throw exceptions. If DEBUG is
|
||||
``False`` they will be silently stripped.
|
||||
|
||||
If the :ref:`COMPRESS <compress>` setting is ``False`` (defaults to the
|
||||
opposite of DEBUG) the ``compress`` template tag simply returns exactly
|
||||
what it was given, to ease development.
|
||||
|
||||
.. warning::
|
||||
|
||||
For production sites it is **strongly recommended** to use a real cache
|
||||
backend such as memcached_ to speed up the checks of compressed files.
|
||||
Make sure you set your Django cache backend appropriately (also see
|
||||
:ref:`COMPRESS_CACHE_BACKEND <compress_cache_backend>` and
|
||||
Django's `caching documentation`_).
|
||||
|
||||
.. _memcached: http://memcached.org/
|
||||
.. _caching documentation: http://docs.djangoproject.com/en/1.2/topics/cache/#memcached
|
||||
|
||||
CSS Notes
|
||||
---------
|
||||
|
||||
All relative ``url()`` bits specified in linked CSS files are automatically
|
||||
converted to absolute URLs while being processed. Any local absolute URLs (those
|
||||
starting with a ``'/'``) are left alone.
|
||||
|
||||
Stylesheets that are ``@import``'d are not compressed into the main file.
|
||||
They are left alone.
|
||||
|
||||
If the media attribute is set on <style> and <link> elements, a separate
|
||||
compressed file is created and linked for each media value you specified.
|
||||
This allows the media attribute to remain on the generated link element,
|
||||
instead of wrapping your CSS with @media blocks (which can break your own
|
||||
@media queries or @font-face declarations). It also allows browsers to avoid
|
||||
downloading CSS for irrelevant media types.
|
||||
|
||||
Recommendations
|
||||
---------------
|
||||
|
||||
* Use only relative or full domain absolute URLs in your CSS files.
|
||||
* Avoid @import! Simply list all your CSS files in the HTML, they'll be combined anyway.
|
2
setup.py
2
setup.py
@@ -105,7 +105,7 @@ setup(
|
||||
version = VERSION,
|
||||
url = 'http://django_compressor.readthedocs.org/',
|
||||
license = 'BSD',
|
||||
description = "Compresses linked and inline javascript or CSS into a single cached file.",
|
||||
description = "Compresses linked and inline JavaScript or CSS into a single cached file.",
|
||||
long_description = README,
|
||||
author = 'Jannis Leidel',
|
||||
author_email = 'jannis@leidel.info',
|
||||
|
Reference in New Issue
Block a user