Моя борьба с javascript ч.2.

Ок. Компилятор выбран. Однако, это только половина задачи. Вторая половина задачи выходит из того факта, что, если я хочу подключать .py файлы из шаблона — мне нужно кеширование и компиляция кода в зону static. Я совсем не хочу, чтобы при каждом рендере шаблона вызывался довольно тяжелый компилятор. Кроме того, для установки сервера в productive режим, у меня на руках должен оказаться работающий набор скомпилированных скриптов. А еще, я хочу не думать о том, что библиотеки могут загружаться на страницу позже кода. Сопроводительные задачи должен решать робот. Для этой цели собственно и был написан django-compressor.

Вообще, django-compressor довольно спорный tool. Спорный с точки зрения необходимости — гораздо правильнее строить приложение так, чтобы задачи которые решает компрессор, вообще не вставали. Гораздо правильнее использовать CSS для стилей, и скрипт для клиентской части. Но питон силен именно тем, что позволяет быстро делать прототипы. А в прототипе главное не оптимальность. В прототипе главное — быстро и эффективно перейти от этапа создания среды для эксперимента, к собственно эксперименту. Компрессор был написан какраз исходя из того, что сначала должен быть создан прототип, и создан он должен быть быстро.

Про компрессор

Если коротко, то компрессор действует следующим образом — он берет все, что находится между тегами {% compress "group_name" %}{% endcompress %}, и переставляет “это все” в то место, где находится тег {%compressed "group_name" "compiler_name"%}. Перед подстановкой проверяется наличие контрольной суммы в кеше компрессора, и на этом основании принимается решение — нужна ли компиляция с использованием компилятора compiler_name или можно просто вернуть содержимое файла (или путь к файлу) соответствующее контрольной сумме. Компрессор умеет разбирать наследование шаблонов, инклуды, блоки и переменные. Поэтому можно спокойно выстраивать удобную для себя структуру шаблонов, не оглядываясь. Содержимое нескольких тегов {% compress %} будет встречаться в на странице в том же порядке, в котором происходил рендер.

Компилятор задается в settings.py как элемент словаря COMPRESSOR_COMPILERS следующего вида:

"pycow_file":{"result_wrapper":"""<script type="application/javascript" src="%(rendered)s"></script>""", 
                        "returns_url":True,
                        "extension":"js",
                        "compiler":"pycow_compressor.pycow"},

Здесь result_wrapper определяет, какой текст будет окружать результат компиляции. returns_url определяет что надо возвращать — путь в кеше к скомпилированному файлу или содержимое скомпилированного файла. extension определяет какое расширение указывать для скомпилированных в кеш файлов. compiler определяет где взять функцию для компиляции.

Вторым аргументом для функции компилятора будет передан контекст. Так что, если внешний компилятор умеет работать с контекстом — можно приютить и его. Обращаю внимание — контекст будет закеширован после первой компиляции. Отслеживать и кешировать изменения переменных контекста я считаю избыточным. Поэтому, изменения в контексте не будут отражаться в скомпилированном файле, но для верстки стилей с использованием clevercss - сойдет.

Это какбы все. Следует еще добавить, что в реальном мире, никто не захочет держать клиентский (или еще какой) код внутри шаблонов, поэтому есть тег {% compress_file "group_name" "file/path" %}, который позволяет вынести код в отдельный файл. Путь считается относительным к корню проекта.

Производительность компрессора

Особо не вникал, т.к. это утилита времени разработки. Сравнение времени рендера шаблона в 10 строк без компрессора и с ним дало отличие в 4 раза — с 0.018 до 0.056 секунд. Очевиден выиграш в количестве запросов к серверу, но за все надо платить.

Add post to: Delicious Reddit Slashdot Digg Technorati Google
(already: 1) Comment post

Comments

No comments for this post

Required. 30 chars of fewer.

Required.