Skip to content
This repository
Browse code

Added documentation for versions.

  • Loading branch information...
commit a79aa29b80fd014bcb22e13958ffbdf57c4486c0 1 parent acefe50
Michael Elsdörfer authored
4 docs/bundles.rst
Source Rendered
@@ -29,7 +29,9 @@ arguments:
29 29 applied in the order in which they are given.
30 30
31 31 * ``output`` - Name/path of the output file. All source files will be merged
32   - and the result stored at this location.
  32 + and the result stored at this location. A ``%(version)s`` placeholder is
  33 + supported here, which will be replaced with the version of the file. See
  34 + :doc:`/expiring`.
33 35
34 36
35 37 Nested bundles
10 docs/django/settings.rst
Source Rendered
@@ -23,12 +23,16 @@ in your project's global settings.
23 23 .. autodata:: ASSETS_DEBUG
24 24 :noindex:
25 25
26   -.. autodata:: ASSETS_UPDATER
  26 +.. autodata:: ASSETS_AUTO_BUILD
27 27 :noindex:
28 28
29   -.. _django-setting-expire:
  29 +.. autodata:: ASSETS_URL_EXPIRE
  30 + :noindex:
  31 +
  32 +.. autodata:: ASSETS_VERSIONS
  33 + :noindex:
30 34
31   -.. autodata:: ASSETS_EXPIRE
  35 +.. autodata:: ASSETS_MANIFEST
32 36 :noindex:
33 37
34 38 .. autodata:: ASSETS_CACHE
8 docs/environment.rst
Source Rendered
@@ -61,11 +61,13 @@ The environment supports the following configuration options:
61 61
62 62 .. autoattribute:: webassets.env.Environment.debug
63 63
64   -.. autoattribute:: webassets.env.Environment.updater
  64 +.. autoattribute:: webassets.env.Environment.auto_build
65 65
66   -.. _environment-setting-expire:
  66 +.. autoattribute:: webassets.env.Environment.url_expire
67 67
68   -.. autoattribute:: webassets.env.Environment.expire
  68 +.. autoattribute:: webassets.env.Environment.versions
  69 +
  70 +.. autoattribute:: webassets.env.Environment.manifest
69 71
70 72 .. autoattribute:: webassets.env.Environment.cache
71 73
189 docs/expiring.rst
Source Rendered
... ... @@ -0,0 +1,189 @@
  1 +.. _expiry:
  2 +
  3 +
  4 +URL Expiry (cache busting)
  5 +==========================
  6 +
  7 +For beginners
  8 +-------------
  9 +
  10 +You are using ``webassets`` because you care about the performance of your
  11 +site. For the same reason, you have configured your web server to send out
  12 +your media files with a so called *far future expires* header: Your web server
  13 +sets the ``Expires`` header to some date many years in the future. Your user's
  14 +browser will never spend any time trying to retrieve an updated version.
  15 +
  16 +.. note::
  17 +
  18 + Of course, the user's browser will already use the ``Etag`` and
  19 + ``Last-Modified/If-Modified-Since`` to avoid downloading content it has
  20 + already cached, and if your web server isn't misconfigured entirely, this
  21 + will work. The point of *far future expires* is to get rid of **even**
  22 + those requests which would return only a ``304 Not Modified`` response.
  23 +
  24 +What if you actually deploy an update to your site? Now you need to convince
  25 +the browser to download new versions of your assets after all, but you have
  26 +just told it not to bother to check for new versions. You work around this by
  27 +*modifying the URL with which the asset is included*. There are two distinct
  28 +ways to so:
  29 +
  30 +1) Append a version identifier as a querystring::
  31 +
  32 + http://www.example.org/media/print.css?acefe50
  33 +
  34 +2) Add a version identifier to the actual filename::
  35 +
  36 + http://www.example.org/media/print.acefe50.css
  37 +
  38 +How webassets helps you do this is explained in the sections below.
  39 +
  40 +.. note::
  41 +
  42 + Even if you are not using *far future expires* headers, you might still find
  43 + ``webassets`` expiry features useful to navigate around any funny browser
  44 + caching behaviour that might require a ``Shift``-reload.
  45 +
  46 +
  47 +What is the version of a file
  48 +-----------------------------
  49 +
  50 +To expire an URL, it is modified with a version identifier. What is this
  51 +identifier? By default, ``webassets`` will create an MD5-hash of the file
  52 +contents, and use the first few characters as the file version. ``webassets``
  53 +also allows you to use the *last modified* timestamp of the file. You can
  54 +configure this via the ``versions`` option::
  55 +
  56 + env = Environment(...)
  57 + env.versions = 'hash' # the default
  58 + env.versions = 'hash:32' # use the full md5 hash
  59 + env.versions = 'timestamp' # use the last modified timestamp
  60 +
  61 +It is generally recommended that you use a hash as the version, since it will
  62 +remain the same as long as the content does not change, regardless of any
  63 +filesystem metadata, which can change for any number of reasons.
  64 +
  65 +
  66 +Expire using a querystring
  67 +--------------------------
  68 +
  69 +``webassets`` will automatically add the version as a querystring to the urls
  70 +it generates, by virtue of the ``url_expire`` option defaulting to ``True``.
  71 +If you want to be explicit::
  72 +
  73 + env = Environment(...)
  74 + env.url_expire = True
  75 +
  76 +There is nothing else you need to do here. The URLs that are generated might
  77 +look like this::
  78 +
  79 + /media/print.css?acefe50
  80 +
  81 +However, while the default, expiring with a querystring is not be the best
  82 +option:
  83 +
  84 +
  85 +Expire using the filename
  86 +-------------------------
  87 +
  88 +Adding the version as a querystring has two problems. First, it may not always
  89 +be a browser that implements caching through which we need to bust. It is said
  90 +that certain (possibly older) proxies do ignore the querystring with respect
  91 +to their caching behavior.
  92 +
  93 +Second, in certain more complex deployment scenarios, where you have multiple
  94 +frontend and/or multiple backend servers, an upgrade is anything but
  95 +instantaneous. You need to be able to serve both the old and the new version
  96 +of your assets at the same time. See for example how this affects you `when
  97 +using Google App Engine <http://bjk5.com/post/4918954974/js-css-packaging-to-minimize-requests-and-randomly-evil>`_.
  98 +
  99 +To expire using the filename, you add a ``%(version)s`` placeholder to your
  100 +bundle output target::
  101 +
  102 + bundle = Bundle(..., output='screen.%(version)s.css')
  103 +
  104 +The URLs that are generated might look like this::
  105 +
  106 + /media/screen.acefe50.css
  107 +
  108 +.. note::
  109 +
  110 + ``webassets`` will use this modified filename for the actual output files
  111 + it writes to disk, as opposed to just modifying the URL it generates. You
  112 + do not have to configure your web server to do any rewriting.
  113 +
  114 +
  115 +About manifests
  116 +---------------
  117 +
  118 +.. note::
  119 +
  120 + This is mostly an advanced feature, and you might not have to bother with
  121 + it at all.
  122 +
  123 +``webassets`` supports Environment-wide *manifests*. A manifest remembers the
  124 +current version of every bundle. What is this good for?
  125 +
  126 +1) Speed. Calculating a hash can be expensive. Even if you are using
  127 + timestamp-based versions, that still means a stat-request to your disk.
  128 +
  129 + .. note::
  130 +
  131 + Note that even without a manifest, ``webassets`` will cache the version
  132 + in memory. It will only need to be calculated once per process. However,
  133 + if you have *many* bundles, and a very busy site, a manifest will allow
  134 + you to both skip calculating the version (e.g. creating a hash), as well
  135 + as read the versions of all bundles into memory at once.
  136 +
  137 + .. note::
  138 +
  139 + If you are using automatic building, all of this is mostly not true. In
  140 + order to determine whether a rebuild is required, ``webassets`` will need
  141 + to check the timestamps of all files involved in any case. It goes
  142 + without saying that using automatic building on a production site is a
  143 + convenience feature for small sites, and at odds with counting paper
  144 + clips in the form of filesystem ``stat`` calls.
  145 +
  146 +2) Making it possible to know the version in the first place.
  147 +
  148 + Depending on your configuration and deployment, consider that it might not
  149 + actually be possible for ``webassets`` to know what the version is.
  150 +
  151 + If you are using a hash-based version, and your bundle's output target has
  152 + a placeholder, there is no way to know what the version is, *unless* is
  153 + has been written to a manifest during the build process.
  154 +
  155 + The timestamp-based versioning mechanism can actually look at the source
  156 + files to determine the version. But, in more complex deployments, the source
  157 + files might not actually be available to read - they might be on a
  158 + completely different server altogether.
  159 +
  160 + A manifest allows version information to be persisted.
  161 +
  162 +
  163 +In practice, by default the version information will be written to the cache.
  164 +You can explicitly request this behaviour be setting the ``manifest`` option::
  165 +
  166 + env = Environment(...)
  167 + env.manifest = 'cache'
  168 +
  169 +In a simple setup, where you are separately building on your local machine
  170 +during development, and building on the web server for production (maybe via
  171 +the automatic building feature, enabled by default), this is exactly would
  172 +you want. Don't worry about it.
  173 +
  174 +There is a specific deployment scenario where you want to prebuild your bundles
  175 +locally, and for either of the two reasons above want to include the version
  176 +data pre-made when you deploy your app to the web server. In such a case, it
  177 +is not helpful to have the versions stored in the cache. Instead, ``webassets``
  178 +provides a manifest type that writes all information to a single file::
  179 +
  180 + env = Environment(...)
  181 + env.manifest = 'file'
  182 + env.manifest = 'file:/tmp/manifest.to-be-deployed' # explict filename
  183 +
  184 +You can then just copy this one file to the web server, and ``webassets``
  185 +will know all about the versions without having to consult the media files.
  186 +
  187 +.. note::
  188 +
  189 + The file is a pickled dict.
24 docs/faq.rst
Source Rendered
@@ -6,10 +6,7 @@ FAQ
6 6 Is there a cache-busting feature?
7 7 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 8
9   -Yes! It's turned on by default. See the
10   -:ref:`Environment.expire <environment-setting-expire>`
11   -option (or :ref:`ASSETS_EXPIRE <django-setting-expire>` if using
12   -``django_assets``).
  9 +Yes! See :doc:`/expiring`.
13 10
14 11
15 12 Relative URLs in my CSS code break if the merged asset is written to a different location than the source files. How do I fix this?
@@ -28,20 +25,15 @@ See :doc:`css_compilers` for how this is best done.
28 25 Is Google App Engine supported?
29 26 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 27
31   -It generally works, though further improvements are planned. Due to the
32   -way Google App Engine works (static files are stored on separate servers),
33   -you need to build your assets locally, possibly using one of the management
34   -commands provided for your preferred framework, and then deploy them.
  28 +Yes. Due to the way Google App Engine works (static files are stored on
  29 +separate servers), you need to build your assets locally, possibly using one
  30 +of the management commands provided for your preferred framework, and then
  31 +deploy them.
35 32
36   -In production mode, you therefore want to disable the
37   -``Environment.updater``/``ASSETS_UPDATER`` setting.
  33 +In production mode, you need to disable the ``Environment.auto_build`` setting.
38 34
39   -Further, you currently need to disable
40   -``Environment.expire``/``ASSETS_EXPIRE`` for webassets to work on Google's
41   -servers. This means you will not get url expiration functionality. This will
42   -be fixed in the future. In the meantime, you can write some custom code
43   -to provide the feature. See `this gist <https://gist.github.com/1307521>`_
44   -for an example.
  35 +For URL expiry functionality, you need to use a manifest that holds version
  36 +information. See :doc:`/expiring`.
45 37
46 38 There is a barebone Google App Engine example in the
47 39 `examples/appengine/ <https://github.com/miracle2k/webassets/blob/master/tests/>`_
4 docs/generic/index.rst
Source Rendered
@@ -52,7 +52,7 @@ you do this depends a bit on how your site is rendered.
52 52 .. code-block:: python
53 53
54 54 >>> my_env['js_all'].urls()
55   - ('../static/media/gen/packed.js',)
  55 + ('../static/media/gen/packed.js?9ae572c',)
56 56
57 57 This will always work. You can call your bundle's ``urls()`` method, which
58 58 will automatically merge and compress the source files, and return the
@@ -95,4 +95,4 @@ Further Reading
95 95 /css_compilers
96 96 /loaders
97 97 /integration/index
98   - /faq
  98 + /faq
3  docs/index.rst
Source Rendered
@@ -25,9 +25,10 @@ of framework used:
25 25 bundles
26 26 script
27 27 builtin_filters
  28 + expiring
28 29 custom_filters
29 30 css_compilers
30 31 loaders
31 32 integration/index
32 33 faq
33   - upgrading
  34 + upgrading
6 examples/appengine/assets.py
@@ -4,9 +4,9 @@
4 4
5 5 env = Environment(path.join(path.dirname(__file__), 'static'), '/stylesheets')
6 6 # App Engine doesn't support automatic rebuilding.
7   -env.updater = False
8   -# URL expiry not currently supported on App Engine
9   -env.expire = False
  7 +env.auto_build = False
  8 +# This file needs to be shipped with your code.
  9 +env.manifest = 'file'
10 10
11 11 bundle = Bundle('in.css', filters="cssmin", output="out.css")
12 12 env.add(bundle)
6 src/django_assets/settings.py
@@ -23,8 +23,10 @@ def __init__(self, object, append=None):
23 23
24 24 ASSETS_DEBUG = Environment.debug
25 25 ASSETS_CACHE = Environment.cache
26   -ASSETS_UPDATER = Environment.updater
27   -ASSETS_EXPIRE = Environment.expire
  26 +ASSETS_AUTO_BUILD = Environment.auto_build
  27 +ASSETS_URL_EXPIRE = Environment.url_expire
  28 +ASSETS_MANIFEST = Environment.manifest
  29 +ASSETS_VERSIONS = Environment.versions
28 30 ASSETS_URL = docwrap(Environment.url, """\n\nBy default, ``STATIC_URL``
29 31 will be used for this, or the older ``MEDIA_URL`` setting.""")
30 32 ASSETS_ROOT = docwrap(Environment.directory, """\n\nBy default,
7 src/webassets/env.py
@@ -241,8 +241,6 @@ def _get_cache(self):
241 241
242 242 *custom path*
243 243 Use the given directory as the cache directory.
244   -
245   - Note: Currently, the cache is never used while in production mode.
246 244 """)
247 245
248 246 def _set_auto_build(self, value):
@@ -325,7 +323,8 @@ def _get_versions(self):
325 323
326 324 A bundle's version is what is appended to URLs when the
327 325 ``url_expire`` option is enabled, and the version can be part
328   - of a Bundle's output filename by use of the %(version)s placeholder.
  326 + of a Bundle's output filename by use of the ``%(version)s``
  327 + placeholder.
329 328
330 329 Valid values are:
331 330
@@ -384,7 +383,7 @@ def _get_url_expire(self):
384 383 webassets will have their version (see ``Environment.versions``)
385 384 appended as a querystring.
386 385
387   - An alternative approach would be to use the %(version)s
  386 + An alternative approach would be to use the ``%(version)s``
388 387 placeholder in the bundle output file.
389 388
390 389 By default, this option is enabled.

0 comments on commit a79aa29

Please sign in to comment.
Something went wrong with that request. Please try again.