Flask-Assets
Flask-Assets (current version 2.1.0) provides asset management for Flask applications, integrating the `webassets` library to efficiently merge, minify, and compile CSS and JavaScript files. It simplifies frontend workflow by handling static resource optimization, with new versions released periodically to maintain compatibility with Flask and other dependencies.
Common errors
-
TemplateSyntaxError: Encountered unknown tag 'assets'
cause The Flask-Assets Jinja2 extension is not correctly registered or initialized with the Flask application.fixEnsure `Environment(app)` or `assets.init_app(app)` is called after creating your Flask app. If using an application factory, call `assets.init_app(app)` within the factory function after the app is created. The `Environment` constructor automatically registers the Jinja2 extension when an app instance is passed. -
webassets.exceptions.FilterError: Filter 'jsmin' not found
cause A specified filter (e.g., `jsmin`, `cssmin`, `less`, `sass`) is not installed in the Python environment.fixInstall the Python package that provides the missing filter. For 'jsmin', run `pip install jsmin`. For other filters, consult the `webassets` documentation for the correct package name (e.g., `cssmin`, `lesscpy`, `pyscss`). -
GET /static/gen/packed.js HTTP/1.1" 404 -
cause The generated asset file (e.g., `packed.js` or `packed.css`) is not found, often due to incorrect paths, `ASSETS_DEBUG` configuration, or the files not being built.fixVerify that `output` paths in your `Bundle` definitions are correct and relative to your Flask app's static directory. In development, ensure `ASSETS_DEBUG` is `True` to see individual files or set `app.config['ASSETS_AUTO_BUILD'] = True` (or manually run `flask assets build`) to ensure bundles are generated. -
How to pass variables to assets in Flask (Jinja2) / JavaScript file cannot access Flask/Jinja2 variables.
cause JavaScript assets are static and processed once, before template rendering. Direct inline Jinja2 variable substitution within a linked `.js` file is not possible.fixPass data from Flask to JavaScript by rendering a `<script>` block *within* your Jinja2 template, before your linked asset. Use `window.YOUR_VAR = {{ flask_variable | tojson }};` to make Python variables accessible to your JavaScript assets. Ensure `| tojson` is used for proper JSON encoding of complex objects.
Warnings
- breaking Flask-Assets 2.1.0 (and newer versions) officially supports Flask 2.2.x and above. Older Flask versions (e.g., Flask 1.x) may experience compatibility issues or unexpected behavior.
- gotcha Filters specified in `Bundle` (e.g., 'jsmin', 'cssmin', 'less', 'sass') require their corresponding Python packages to be installed separately. Flask-Assets does not automatically install these filter dependencies.
- deprecated The Flask-Script integration (`flask_assets.ManageAssets`) is considered legacy. For command-line asset management, use the built-in Flask CLI integration (`flask assets` command) which is available for Flask 0.11+.
- gotcha Setting `Environment.directory` or `Environment.load_path` explicitly disables Flask-Assets' built-in blueprint static file resolution. All paths will then be considered relative to the specified custom directory/URL.
Install
-
pip install Flask-Assets -
pip install Flask-Assets jsmin cssmin lesscpy pyscss
Imports
- Environment
from flask_assets import Environment
- Bundle
from flask_assets import Bundle
Quickstart
from flask import Flask, render_template
from flask_assets import Environment, Bundle
import os
app = Flask(__name__)
# Configure Flask for assets
app.config['ASSETS_DEBUG'] = True # Set to False in production
# Initialize Flask-Assets
assets = Environment(app)
# Define asset bundles
js_bundle = Bundle(
'js/main.js',
'js/utils.js',
filters='jsmin',
output='gen/packed.js'
)
css_bundle = Bundle(
'css/style.css',
'css/theme.css',
filters='cssmin',
output='gen/packed.css'
)
# Register bundles
assets.register('main_js', js_bundle)
assets.register('main_css', css_bundle)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
# Create static/js and static/css directories for the example
os.makedirs(os.path.join(app.static_folder, 'js'), exist_ok=True)
os.makedirs(os.path.join(app.static_folder, 'css'), exist_ok=True)
# Create dummy asset files
with open(os.path.join(app.static_folder, 'js', 'main.js'), 'w') as f:
f.write('console.log("Main JS loaded");')
with open(os.path.join(app.static_folder, 'js', 'utils.js'), 'w') as f:
f.write('function utility() { return "utility"; }')
with open(os.path.join(app.static_folder, 'css', 'style.css'), 'w') as f:
f.write('body { font-family: sans-serif; }')
with open(os.path.join(app.static_folder, 'css', 'theme.css'), 'w') as f:
f.write('h1 { color: #333; }')
# Create a simple template (templates/index.html)
template_content = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flask-Assets Example</title>
{% assets "main_css" %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
{% endassets %}
</head>
<body>
<h1>Hello from Flask-Assets!</h1>
{% assets "main_js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
</body>
</html>
'''
os.makedirs('templates', exist_ok=True)
with open('templates/index.html', 'w') as f:
f.write(template_content)
app.run(debug=True)