Расширение Flask-Assets
предназначено для объединения и сжатия файлов JavaScript и CSS, а также преобразования разметки sass
и less
в реальный CSS.
# создаем виртуальное окружение, если нет $ python3 -m venv .venv --prompt VirtualEnv # активируем виртуальное окружение $ source .venv/bin/activate # обновляем `pip` (VirtualEnv):~$ python3 -m pip install -U pip # ставим модуль `Flask-Assets` (VirtualEnv):~$ python3 -m pip install -U Flask-Assets
Flask-Assets
;flask_assets.Environment()
;flask_assets.Bundle()
;Flask-Assets
.При инициализации приложения, необходимо создать экземпляр класса flask_assets.Environment
и зарегистрировать в нем необходимые ресурсы в виде так называемых пакетов flask_assets.Bundle
.
from flask import Flask from flask_assets import Environment, Bundle app = Flask(__name__) assets_env = Environment(app) js = Bundle('jquery.js', 'base.js', 'widgets.js', filters='jsmin', output='gen/packed.js') assets_env.register('js_all', js)
Пакет Bundle
состоит из любого количества исходных файлов (может содержать другие вложенные пакеты), конечного результата и списка применяемых фильтров.
Все пути относятся к директории со статическими файлами приложения или директории со статикой схемы Flask.
Если есть необходимость, то можно определить статические активы (css и js) во внешнем файле конфигурации и прочитать их оттуда. Используемый в зависимостях модуль webassets
включает ряд вспомогательных классов для некоторых популярных форматов, таких как YAML.
Экземпляр Flask-Assets
может использоваться с несколькими приложениями путем инициализации через вызовы init_app()
, а не передачи фиксированного объекта приложения:
app = Flask(__name__) assets_env = flask_assets.Environment() assets_env.init_app(app)
Flask-Assets
Теперь, когда ресурсы правильно определены, можно их объединить и минимизировать, а также включить ссылку на сжатый результат на веб-странице:
{% assets "js_all" %} <script type="text/javascript" src="{{ ASSET_URL }}"></script> {% endassets %}
Модуль Flask-Assets
автоматически объединит и сожмет исходные файлы пакета при первом отображении шаблона и автоматически обновит сжатый файл при каждом изменении исходного файла. Если в конфигурации приложения установить ASSETS_DEBUG
в значение True
, то каждый исходный файл будет выводиться по отдельности.
Flask-Assets
со схемами blueprint
Если используются схемы Flask (blueprint
), то можно ссылаться на статические файлы схем через префикс, точно так же, как Flask позволяет ссылаться на шаблоны схем:
js = Bundle('app_level.js', 'blueprint/blueprint_level.js')
В приведенном выше примере пакет будет ссылаться на два файла: {APP_ROOT}/static/app_level.js
и {BLUEPRINT_ROOT}/static/blueprint_level.js
.
Если ранее приложение Flask использовало модуль webassets
, то скорее всего знакомы с требованием установки в конфигурации базового каталога и URL-адреса. Расширение Flask-Assets
этого не требует, т.к. используется поддержка статических папок Flask. Обратите внимание, что если необходимо, то можно установить собственный корневой каталог Environment.directory
или URL-адрес Environment.url
. Но при этом отключается поддержка схем Flask, то есть ссылка на статические файлы в разных схемах с использованием префикса, как описано выше, уже невозможна. Все пути будут рассматриваться относительно каталога и указанного URL-адреса.
Flask-Assets
только в шаблоне.Если необходимо, то можно обойтись без определения пакетов в коде приложения и просто определить все внутри шаблона:
{% assets filters="jsmin", output="gen/packed.js", "common/jquery.js", "site/base.js", "site/widgets.js" %} <script type="text/javascript" src="{{ ASSET_URL }}"></script> {% endassets %}
Flask-Assets
Режим отладки можно установить через конфигурацию Flask. Следующие два утверждения эквивалентны:
assets_env.debug = True # или app.config['ASSETS_DEBUG'] = True
Если установить ASSETS_DEBUG
в значение True
, то каждый исходный файл будет выводиться по отдельности.
flask_assets.Environment()
.Объект flask_assets.Environment(app=None)
используется для хранения набора пакетов и конфигурации.
Если он инициализирован экземпляром приложения Flask, тогда расширение webassets-Jinja2
регистрируется автоматически (смотрите "Использование Flask-Assets
только в шаблоне").
app = Flask(__name__) assets = Environment(app)
Объект Environment
определяет несколько методов:
Environment.directory
: базовый каталог, к которому будут относиться все пути. По умолчанию 'static'
. Служит только в качестве выходного каталога output
.Environment.url
: префикс URL-адреса, используемый для построения URL-адресов файлов в Environment.directory
. По умолчанию 'static'
.Environment.from_module(path)
: регистрирует пакеты из модуля Python, указанного в аргументе path
.Метод Environment.from_yaml(path)
: регистрирует пакеты из файла конфигурации YAML
, переданный аргументу path
.
Ожидается следующий формат YAML
:
bundle-name: filters: sass,cssutils output: cache/default.css contents: - css/jquery.ui.calendar.css - css/jquery.ui.slider.css another-bundle: # ...
Пакеты могут ссылаться друг на друга:
js-all: contents: - jquery.js - jquery-ui # Это ссылка на пакет jquery-ui: contents: jqueryui/*.js
flask_assets.Bundle()
.Класс flask_assets.Bundle(*contents, **options)
представляет собой пакет - набор файлов *contents
, которые необходимо сгруппировать вместе, с некоторыми присоединенными свойствами **options
. К таким свойствам относятся фильтры, которые следует применять, или место, где должен храниться выходной файл.
Обратите внимание, что все имена файлов и пути считаются относительными к настройке Environment.directory
, а сгенерированные URL-адреса будут относиться к настройке Environment.url
.
js = Bundle('common/inheritance.js', 'portal/js/common.js', 'portal/js/plot.js', 'portal/js/ticker.js', filters='jsmin', output='gen/packed.js')
Ключевые аргументы **options
могут содержать:
filters
: один или несколько фильтров для применения. Если фильтры не указаны, то исходные файлы *contents
будут просто объединены в выходной файл. Фильтры применяются в том порядке, в котором они заданы.
Встроенные фильтры:
jsmin
- сокращает Javascript, удаляя пробелы, комментарии и т. д.cssmin
- сокращает CSS, удаляя пробелы, комментарии и т. д.less
- преобразует разметку less
в реальный CSS.sass
- преобразует разметку sass
в реальный CSS. Требует, чтобы исполняемый файл Sass
был доступен извне. Чтобы установить его, можно сделать следующее: $ sudo gem install sass
output
: имя/путь выходного файла.
depend
: дополнительные файлы, которые должны отслеживаются на предмет изменения и определения, нужно ли пересобирать пакет. Этот аргумент необходим, если используются компиляторы, допускающие инструкции @import
. Для простоты можно использовать символы подстановки в стиле модуля glob
, например, Bundle(depends=('**/*.scss'))
.
Пакеты также могут содержать другие пакеты. Вложенные пакеты позволяют применять разные наборы фильтров к разным группам файлов, но при этом все они объединяются в один выходной файл. Вложенные пакеты не должны содержать аргумент output
, т.к. служат контейнером, которые, в свою очередь, будут преобразованы в соответствующий выходной файл.
from flask_assets import Bundle all_js = Bundle( # jQuery Bundle('common/libs/jquery/jquery.js', 'common/libs/jquery/jquery.ajaxQueue.js', 'common/libs/jquery/jquery.bgiframe.js',), # jQuery Tools Bundle('common/libs/jqtools/tools.tabs.js', 'common/libs/jqtools/tools.tabs.history.js', 'common/libs/jqtools/tools.tabs.slideshow.js'), # собственные скрипты Bundle('common/inheritance.js', 'portal/js/common.js', 'portal/js/plot.js', 'portal/js/ticker.js'), # фильтр минификации для всех вложенных пакетов filters='jsmin', # результирующий файл output='gen/packed.js')
В примере, использование вложенных объектов Bundle
для группировки файлов JavaScript носит чисто эстетический характер. С тем же успехом можно передать все файлы в виде плоского списка. Но есть и более серьезное применение:
Использование компиляторов CSS, например:
Расширение Flask-Assets
включает встроенные фильтры для ряда популярных компиляторов CSS, которые можно использовать как любой другой фильтр. Фильтры компилятора запускаются даже в режиме отладки:
less = Bundle('css/base.less', 'css/forms.less', filters='less,cssmin', output='screen.css')
Блок кода примера при отладке скомпилирует CSS, но не минимизируется. В продакшене будут применяться оба фильтра.
Иногда нужно объединить код CSS, и файлы написанные с использованием расширения sass
:
sass = Bundle('*.sass', filters='sass', output='gen/sass.css') all_css = Bundle('css/jquery.calendar.css', sass, filters='cssmin', output="gen/all.css")
В приведенном выше случае фильтр sass
применяется только к исходным файлам Sass
во вложенном пакете (которому необходим output='gen/sass.css'
!). Минификация применяется ко всему содержимому CSS во внешнем пакете.
Использование предварительно сжатых файлов JS, например:
jquery.min.js
;Например, если проект использует предварительно сжатые JS-файлы, которые нужно объединить с несжатыми, то можно сделать это следующим образом:
js = Bundle('jquery.min.js', Bundle('uncompressed.js', filters='jsmin'), output='gen/packed.js')