gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
73.9k stars 7.41k forks source link

Hugo Pipes: Add post-render transformation support #5632

Open bep opened 5 years ago

bep commented 5 years ago

@regisphilibert posted this link https://github.com/client9/csstool the forum. It strips unused CSS rules from a CSS.

I had a look at it and thought initially that it would be hard to add to the current Hugo Pipes, as the current transformers (PostCSS, SCSS etc.) does not have the information needed (e.g. public/**/*.html) for something like "CSS filtering" to work.

But we can, of course, add a concept of "delayed transformations" to Hugo pipes, so one could do something like:

{{ $css := resources.Get "scss/main.scss" | toSCSS | minify | css.Cut "**/*.html" | fingerprint }}

With the above, we delay the execution until the rendered content is available.

Note that the new namings in the above is just dropped in there without too much thought. The above would typically be a "production only" thing, as I suspect it would take more than some milliseconds to run.

regisphilibert commented 5 years ago

Its awesome you're adding this to the roadmap. Couple of things:

User will need to specify (as parameter) a slice of classnames to whitelist as some classes may be added by javascript and not clearly identifiable from html files. (not sure csstools has that ability yet, but should be trivial for its author to add...)

It's not clear if csstool's algorithm is different than PurgeCSS' but the author points out it's very adapted to css frameworks and utility class system which for me is the prime use cases for css "purging". So I'm personally fine with it but maybe others will have some reservations.

With the above, we delay the execution until the rendered content is available.

Won't the fingerprint have to be rewritten throughout the already rendered HTML files though?

css.Cut "*/.html"

I suppose the parameter is a sensible default, it's not clear to me why people would need to change it though ? Skip a very large directory to improve build time?

Also, is the css namespace a technical requirement?

Note that the new namings in the above is just dropped in there without too much thought

Yes, Cut is a bit harsh isn't it ? I would advise against calling it PurgeCSS in case the algorithm differs too much. We could go with Prune though which sounds like Purge but is more accurate to the operation performed I think (always thought the verb purge did not really reflected the "careful" picking involved, but rather a rash cleaning).

@budparr am I missing something?

bep commented 5 years ago

It's not clear if csstool's algorithm is different than PurgeCSS' but the author points out it's very

Note that this issue is a little on the conceptual side of it.

I suppose the parameter is a sensible default, it's not clear to me why people would need to change it though ? Skip a very large directory to improve build time?

You may want to "partition your CSS", e.g.:

{{ $blogStyles := resources.Get "scss/blog.scss" | toSCSS | minify | css.Cut "/blog/**/*.html"  }}

Won't the fingerprint have to be rewritten throughout the already rendered HTML files though?

Yes, that is a problem ... But I guess solvable somehow ...

budparr commented 5 years ago

A welcome addition indeed.

I think it's problematic to run a tool like this on output HTML because of the overhead in terms of build-time. I run PurgeCSS on my templates to avoid that. Doesn't look like this library does that.

regisphilibert commented 5 years ago

Yes I was about to say we can content with using the template files rather than the rendered html. And to this end do do we need the lib to be able to interpret go template though ?

It couldn’t read dynamically generated class names but surely it could identify the hard coded ones which represents a big percentage of the overhaul used classnames.

With a set whitelisted class this may be a sufficient approach for many.

inwardmovement commented 5 years ago

That would be a great thing.

For now I do this with gulp to perform code style rules and apply typography rules after the hugo build process, but it would be a good feature to include these kind of tasks in the hugo pipeline: one would not rely on gulp anymore.

PS. targeting public/**/*.html has the advantage to allow modifications where markdown is not effective (menus, etc.)