Askama Minify
A procedural macro crate that minifies Askama templates at compile time.
Starting with 0.3.0, askama-minify no longer ships a CLI. It reads a template during compilation, minifies HTML and inline CSS/JavaScript, and injects the result as Askama's #[template(source = "...", ext = "...")].
Important: place #[template_minify(...)] above #[derive(Template)] so the macro can generate Askama's #[template(...)] attribute before the derive macro runs.
Usage
use Template;
use template_minify;
Path resolution:
- directories configured through Askama's
[general].dirs CARGO_MANIFEST_DIR/templates/<path>when no custom directories are configuredCARGO_MANIFEST_DIR/<path>as a compatibility fallback
This means the common Askama layout can use the short path directly:
;
With the corresponding file:
templates/index.html
Inline Templates
use Template;
use template_minify;
When source is used, ext is required.
Forwarded Askama Arguments
path, source, and ext are handled by askama-minify. Any other arguments are forwarded to Askama's #[template(...)] attribute:
;
This expands to a minified source template:
Notes
- Template files and their
include,extends, andimportdependencies are tracked throughinclude_str!, so Cargo rebuilds when any source template changes. - Askama config files are tracked too. Template dependencies are resolved relative to the source template, recursively minified, and passed to Askama through isolated generated files.
- Included HTML fragments retain boundary whitespace. If a dependency graph inserts fragments into whitespace-sensitive or raw-text contexts (
pre,textarea,script,style, or attributes), or contains incomplete markup whose context cannot be determined, its templates are preserved conservatively. This also protects inherited blocks and imported macros in these contexts. htmlandhtmtemplates are minified as HTML. JavaScript without Askama syntax is parsed before it is minified; scripts containing Askama syntax or unsupported JavaScript are preserved unchanged.- JavaScript and advanced CSS minification fall back to the original content when the result could introduce an HTML end tag. Askama strings, nested comments, raw blocks, quoted HTML attributes, and non-ASCII whitespace are preserved.
- The built-in CSS minifier preserves stylesheets containing custom-property syntax unchanged because custom-property token whitespace can be significant.
- Necessary CSS comment boundaries are retained as empty comments rather than changed into selector whitespace.
- Template file contents and compressed results are cached within each compiler process. File metadata changes invalidate the file cache; all original dependencies remain tracked, and identical generated files are not rewritten.
Features
The default features preserve the full behavior:
askama-config: reads[general].dirsfromaskama.toml, using the lightweightbasic-tomlparser. Parsed config and glob results are cached within each compiler process.js-minify: enables parser-backed JavaScript minification. Disable it to preserve inline JavaScript unchanged and avoid compiling the JavaScript parser.advanced-css: useslightningcssfor fuller CSS minification. This is opt-in because it adds a substantially larger compiler dependency graph.
For the smallest dependency graph, disable default features. In this mode template paths use the default templates/ directory (plus the manifest-root compatibility fallback), and inline JavaScript is preserved:
= { = "0.3", = false }
Enable advanced CSS minification with:
= { = "0.3", = ["advanced-css"] }
- CSS containing Askama syntax still falls back to the built-in minifier to avoid failed CSS parser work during compilation.
- Non-HTML extensions are injected unchanged as Askama
sourcetemplates.
Architecture
askama-minify is split into small modules around the procedural macro pipeline:
src/lib.rs: proc-macro entry point. It parses the attribute and target item, then delegates expansion.src/args.rs: parsespath,source,ext, and collects extra Askama arguments for forwarding.src/item.rs: parses the target derive item and rejects an existing#[template(...)]attribute.src/loader.rs: reads Askama config, recursively resolves and minifies template dependencies, and writes isolated generated templates for Askama.src/expand.rs: builds the generated#[template(source = "...", ext = "...")]attribute and addsinclude_str!tracking for template files.src/minifier.rs: public internal entry for HTML minification.src/minifier/html.rs: HTML scanner that preserves Askama syntax and delegates inline<style>and<script>content.src/minifier/css.rs: CSS minification. It uses the built-in conservative minifier by default andlightningcsswhenadvanced-cssis enabled.src/minifier/js.rs: parser-backed JavaScript minification with a lossless fallback for Askama syntax and unsupported JavaScript.src/minifier/template.rs: shared Askama block copier for{{ ... }},{% ... %}, and{# ... #}.src/minifier/util.rs: shared string trimming helpers.
The expansion flow is:
template_minify attribute
-> parse MacroArgs
-> parse TemplateItem
-> load or read source template
-> recursively resolve and minify template dependencies
-> inject Askama #[template(source = "...", ext = "...")]
-> emit include_str! tracking for source template files
Compile-time Benchmark
Run scripts/benchmark-compile.sh to measure cold cargo check time and peak memory for the minimal, default, and all-features dependency graphs. Each measurement uses an isolated temporary target directory and excludes dependency download time.
To measure dependency scanning separately from compiler startup and dependency builds: