djc / askama

Type-safe, compiled Jinja-like templates for Rust
Apache License 2.0
3.37k stars 217 forks source link

Minification in outputted templates in production #456

Open kotx opened 3 years ago

kotx commented 3 years ago

Is it possible to configure Askama to output minified html?

djc commented 3 years ago

It's not possible in general because Askama doesn't really know much about HTML other than how it's escaped. I suppose you might consider a custom fmt::Write impl that handles the minification for you?

vallentin commented 3 years ago

Just in case you don't know, Askama has whitespace control. In short, if you add dashes e.g. {% ... %} vs {%- ... -%}, then along the direction of the dashes the whitespace will be trimmed. You could further use this by adding {# -#} at the end of lines, and have whitespace be removed.

Using the first solution, can easily remove a significant amount of whitespace. The second idea, is ofc a lot more tedious, but it would also work. None of them are of course not minification, but it's an option.

There's a few crates for minifying HTML. However, of all the ones I've tried, none are mature yet, and lots have various bugs. For instance the minify crate also minifies the contents of <pre> tags, which instantly breaks code snippets.

Personally, I use html-minifier (npm), where I just spawn a process with Command. Then I pipe in the HTML and receive the minified HTML from stdout. To be clear, I only use this solution for static pages, or even partial static pages. So I have not tested the performance of using this in production on a live server.

wbrickner commented 3 years ago

This would be a nice performance win to be able to do this at compile time.

The results would be difficult to make perfect, because the contents of the HTML is not actually known ahead of time, but basic things like not adding in quotations where not actually required, no newlines or whitespace between tags where it has no formatting impact, etc etc.

This would amount to dynamic modification of the string literals in the codegen stage I think?

mjanda commented 3 years ago

Or you can use some existing minifier to process template files before compilation. I have my templates in templates_raw and gulp task will minify them into templates directory on change. You just have to tell it to keep askama tags. Of course, you cannot apply every possible minification technique at this stage, but it’s good enough for me.

SkyfallWasTaken commented 1 year ago

Sorry for bumping this issue, but wanted to say what else you can do if you need minification too (since this is what comes up on Google):

[general]
dirs = ["built_templates"]
GrantGryczan commented 2 days ago

It's not possible in general because Askama doesn't really know much about HTML other than how it's escaped.

@djc I don't understand this. Askama doesn't need to know anything about HTML in order to pass the template into another HTML minifying library (which could be included conditionally via a feature flag, if unneeded dependencies is a concern) before processing it as a template.

I suppose you might consider a custom fmt::Write impl that handles the minification for you?

I'd argue this shouldn't be necessary at runtime when it could very well be done at compile time, especially since that's the reason many use Askama over some of the other popular HTML templating libraries that do more of their processing at runtime.

djc commented 1 day ago

That's fair. I'll reopen this, although I probably won't be able to work on this myself (but happy to review or provide design guidance).

GrantGryczan commented 1 day ago

Thanks, appreciate it! I don't have the time to work on this right now, but I'll throw this out there for others or for the future:

One concern I have with this would be how to generalize it. You might not just want to hard-code inclusion of a specific minification implementation since, for example, HTML might not be the language being templated. Though I wouldn't be against hard-coding it with a config option as I suggested above, since HTML minification is likely very commonly desirable for users of this library.

Another reason to generalize is for applying other arbitrary processing to the template at compile time. I have a use case for that: I'd like to generate multipart email message bodies once as minified HTML and once as plain text, with the plain text generated based on the HTML (e.g. using https://github.com/jugglerchris/rust-html2text) so I don't have to duplicate the templates for each email.

Just things worth considering! Not sure what the goals and anti-goals are here.