Hi all,

At my current job, I spent a week of programming on a preprocessor for
Django templates.
In short, what it does is compiling the templates in a more compact
version, dropping all useless information and preprocessing
templatetags where possible. The Apache benchmark tools showed a page
load improvement up to twice as fast in Django 1.2, and 4 times as
fast in the older Django version and HTML pages are now only half as
big in filesize now.

It is completely transparent, there are no changes needed to the
templates, and should only be installed as a template loader (wrapping
around the original loaders).

What is does, in the Django language is:
* preprocess {% trans %} and {% blocktrans %} when they don't take
variables parameters. (the template loader will have a 'cache' for
each language)
* preprocess inheritance. Combining parent and child templates by
replacing the blocks, and filling in {{block.super}}. {% block %} tags
can be removed because all inheritance has been determined. (Note,
this doesn't work with {% extends variable_name %}, but I think it's a
bad idea to have variable inheritance. (but can be disabled if you
would need it.)
* preprocess {% include "path" %}, if path is not a variable.
* grouping {% load statements %}
* resolve all {% url %} when they don't take variable parameters.
* preprocess {% now "Y" %}  (we will restart our server at least once,
after a year transition. :p )
* We have a few tags, like {% google_analytics %}, which constantly
output the same code, this is implemented as a custom preprocessor
extension for ourself.

Now, if the template is HTML, we do a little more optimizations:
* Remove all whitespace between block-level HTML tags
* Removing empty class attributes, like class="", (which may appear as
a result of class="{% block name %}{% endblock %}", where the child
template din't implement the block.)
* Merge all <style type="text/css"> into the first <style/> node.
* replace all multiple whitespaces, by one space, but not in a <pre>
or <textarea> node.
* Remove HTML comments, but not conditional comments
* We have to option to merge <script/> nodes as well, but it seems
that it's not desirable in all situations.

Further, we minify embedded CSS and javascript (renaming variable
names to be as short as possible, and removing really all whitespace
where allowed.) Javascript and CSS comments are removed too.

==Technically==. We wrote a hybrid parse tree, having Django, HTML,
CSS and Javascript nodes in the same parse tree. (first parsing Django
templatetags, then with another lexer, parsing the HTML in the django
tree, etc...) This made it pretty easy to do all the necessary
operations. (Actually, it's based on a lexer that I wrote several
years ago in a dead hobby project, but improved for this:
http://code.google.com/p/python-pages/ )

This 'compilation' is not really fast (can be improved), but that's
not really important because it only has do be done once for every
template. So, for every following request, the performance is still
much better than what we noticed when using a run-time compressor like
{% compress %} before.

For parsing javascript or HTML, it's important to note that there are
a few limitations. It's still a tree structure, and like <b><i>....</
b></i> is a very bad nesting habbit in HTML, we have the same
limitation. For instance:

Don't do:
  {% if test %} <a ... {% else %} <a ... {% endif %} .... >link</a>
but do:
  <a {% if test %}... {% else %}...{% endif %}>link</a>
It's not good to open a tag twice, while closing it only once, so go
for the second.
Also don't open a javascript ' { ' in another 'scope' than were you
close the ' } '.

This are bad programming habbits anyway. Our codebase of templates is
already pretty large, and almost everything worked out of the box
after applying the preprocessor, even the Dango Debug toolbar and
Django Admin. This means that chances are small you hit these
limitations, and if you do, the preprocessor will tell you.

Isn't it cool to have a parser, which when he encounters a javascript
syntax error, is being able to tell you at which line in the django
template source file it's caused. :)

The preprocessor has not yet been released as open-source. But I'm
willing to ask my company to do, if there is a need for this in the
Django community. Personally, I'm really satisfied with the results.

What do you guys think?


-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-develop...@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to