11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
16.95k stars 491 forks source link

addTransform with minifyCSS option enabled removes inline styles generated by eleventy-bundle-pluging #3195

Closed sarhov closed 5 months ago

sarhov commented 7 months ago

Operating system

macOS Sonoma Version 14.2.1

Eleventy

2.0.1

Describe the bug

    eleventyConfig.addTransform("htmlmin", async function(content) {
        // Prior to Eleventy 2.0: use this.outputPath instead
        if( this.page.outputPath && this.page.outputPath.endsWith(".html") ) {
          let minified = htmlmin.minify(content, {
            useShortDoctype: true,
            removeComments: true,
            collapseWhitespace: true,
            minifyCSS: true
          });
          return minified;
        }

        return content;
      });

if I add the option minifyCSS: true we will not have inline styles from eleventy-plugin-bundle plugin, I guess because this happens before css bundle is ready?

Because if I add manually the following, the html-minifier doesn't remove it from output

<style>
  body{
    background: #9c0;
  }
</style>

If I remove minifyCSS: true option it would minifiy html only.

Will be great to have an option to minify the output completely, including inline css, at release remove the new lines and whitespaces.

Reproduction steps

  1. Go to 'eleventy.config.js'
  2. Add transform code with minifyCss option true
  3. Run npm run build 4.Check the output html file, the inline css from bundle plugin is missing.

Expected behavior

To minify the inline css too using the transforms and minifyCSS option enabled

Reproduction URL

No response

Screenshots

image

As we can see from the screenshot the manual added code is minified

<style>
  body{
    background: #9c0;
  }
</style>

but the bundled css from eleventy-bundle-plugin is missing, just empty <style> tags

AmitParekh1771 commented 6 months ago

I've reproduced this issue on stackblitz. Do npm run dev in the console to serve the project and try toggling minifyCSS to notice the effect.

This is because eleventy-bundler-plugin which is executed after html-minifier is done with minification. So in case when minifyCSS: true, minifier removes inline CSS which is yet not bundled.

zachleat commented 5 months ago

Transform order is important! Unfortunately plugins complicate this as plugins are run in a second stage of config (and as such will be executed after any application defined transforms).

Here’s a small test case:

module.exports = function(eleventyConfig) {
    eleventyConfig.addTransform("top.before", async function(content) {
        console.log( "top.before" );
        return content;
    });

    eleventyConfig.addPlugin(eleventyConfig => {
        eleventyConfig.addTransform("plugin", async function(content) {
            console.log( "plugin" );
            return content;
        });
    })

    eleventyConfig.addTransform("top.after", async function(content) {
        console.log( "top.after" );
        return content;
    });
};

This logs:

top.before
top.after
plugin.regular
[11ty] Writing ./_site/test/index.html from ./test.md (liquid)
[11ty] Wrote 1 file in 0.03 seconds (v3.0.0-alpha.6)

You have a couple of options here.

Option 1

You can use the new 3.0+ feature to execute a plugin immediately (not in a second stage). For this plugin I believe it’s okay but it may cause complications for other plugins (if you’re using a return object in your configuration callback). Using the separate export approach in #3246 fixes this (3.0.0-alpha.6+).

const bundlerPlugin = require("@11ty/eleventy-plugin-bundle");

module.exports = function(eleventyConfig) {
    eleventyConfig.addPlugin(bundlerPlugin, { immediate: true });
};

Option 2

Your other option (which is Eleventy 2.0 friendly) is to modify the CSS output from the bundle directly. There is an example of that here:

https://github.com/11ty/eleventy-plugin-bundle/tree/main?tab=readme-ov-file#modify-the-bundle-output

zachleat commented 5 months ago

This is an automated message to let you know that a helpful response was posted to your issue and for the health of the repository issue tracker the issue will be closed. This is to help alleviate issues hanging open waiting for a response from the original poster.

If the response works to solve your problem—great! But if you’re still having problems, do not let the issue’s closing deter you if you have additional questions! Post another comment and we will reopen the issue. Thanks!