Angular-cli: ng build production should minify index.html in dist

Created on 25 Jun 2018  路  19Comments  路  Source: angular/angular-cli

Bug Report or Feature Request (mark with an x)

- [] bug report -> please search issues before submitting
- [x] feature request

Area

- [x] devkit
- [ ] schematics

Versions


node -- version = v8.10.0
node -- version = v5.6.0

Repro steps


ng new proj
cd proj
ng build --prod

The log given by the failure


index.html in dist is not minified

Desired functionality


Minify the index.html in production dist

Mention any other details that might be useful

PS: it's so cool how so many of these best practices and enhancement the CLI does out of the box for you. Thanks for that!

devkibuild-angular feature

Most helpful comment

This should be built-in to Angular itself; we shouldn't have to configure a separate library to do this.

All 19 comments

Hi @Brocco. I would just like to know how issues like these gets considered to be done?

I thought Angular4 was able to do this?

AFAIK it was but was disabled as they made big changes in the core code (I think) and didn't have time to put it back in. But 8 votes so far is looking good so hopefully it will be considered soon.

I'm not sure if it will help someone, but worth try.
I found a workaround by use the html-minifier npm package and run it after the build have finished:
npm install --save-dev html-minifier

package.json:

"postbuild": "node index-minifier.js"

index-minifier.js:

var fs = require('fs');
var minify = require('html-minifier').minify;

var filePath = 'dist/index.html';

fs.readFile(filePath, function (err, buf) {
  if (err) {
    console.log(err);
  } else {

    var originalValue = buf.toString();
    var minifiedValue = minify(originalValue, {
      caseSensitive: false,
      collapseBooleanAttributes: true,
      collapseInlineTagWhitespace: false,
      collapseWhitespace: true,
      conservativeCollapse: false,
      decodeEntities: true,
      html5: true,
      includeAutoGeneratedTags: false,
      keepClosingSlash: false,
      minifyCSS: true,
      minifyJS: true,
      preserveLineBreaks: false,
      preventAttributesEscaping: false,
      processConditionalComments: true,
      processScripts: ["text/html"],
      removeAttributeQuotes: true,
      removeComments: true,
      removeEmptyAttributes: true,
      removeEmptyElements: false,
      removeOptionalTags: true,
      removeRedundantAttributes: true,
      removeScriptTypeAttributes: true,
      removeStyleLinkTypeAttributes: true,
      removeTagWhitespace: true,
      sortAttributes: true,
      sortClassName: true,
      trimCustomFragments: true,
      useShortDoctype: true
    });


    fs.writeFile(filePath, minifiedValue, function (err, data) {
      if (err) {
        console.log(err)
      } else {
        var diff = originalValue.length - minifiedValue.length;
        var savings = originalValue.length ? (100 * diff / originalValue.length).toFixed(2) : 0;
        console.log("Successfully minified '" + filePath + "'" +
          ". Original size: " + originalValue.length +
          ". Minified size: " + minifiedValue.length +
          ". Savings: " + diff + " (" + savings + "%)");
      }
    });
  }
});
{
  "postbuild": "html-minifier dist/static/index.html --collapse-whitespace --remove-comments --remove-optional-tags --remove-redundant-attributes --remove-script-type-attributes --remove-tag-whitespace --use-short-doctype -o dist/static/index.html"
}

It should be simplest solution to me.

This should be built-in to Angular itself; we shouldn't have to configure a separate library to do this.

It's definitely not a bug. I don't see why this feature should be implemented at all.

It's definitely not a bug. I don't see why this feature should be implemented at all.

It's simple, it's the same reason to apply the minification to CSS and JS.

This bug/feature must be present in combination with this issue: https://github.com/angular/angular-cli/issues/8759

It's pretty special file, so if such minification could produce any issues/bugs - better to avoid it.
I don't think many single-page angular apps have a lot of content in index.html so I don't see actual benefits - few bytes of saved space?

I'm sorry but I don't understand how the premise that a feature can cause bugs leads you to think that it can be ignored. In addition, your statement is contradicted because if index.html is such a controlled environment, it should not cause problems to treat it.

Finally, Google (through speed insights) warns you to minify the html with the consequent positioning problems. Angular is not just a framework to use in admin apps. Some of us need to take in count the Google tips to have good positioning.

I'm sorry but I don't understand how the premise that a feature can cause bugs leads you to think that it can be ignored

It is always the case. If feature gives less benefits than issues, then it should not be implemented.

Angular is not just a framework to use in admin apps. Some of us

And who of us was talking about admin apps? Could you quote please?

Finally, Google (through speed insights) warns you to minify the html

When using Angular, almost all of your HTML content is not in index.html.

@e-oz I just said the "Angular is not just a framework to use in admin apps" because the unique case to ignore this Google tip is when you are developing an admin app.

One thing I learned by developing public apps (not admins), is that if you want to be a good site for Google, you must follow the Google tips. If Google says: Minify your html, you must minify it. You can't answer: I'm sorry Google, "almost of our html content is not in index.html"

Anyway, I think a discussion about it in 2020 makes no sense.

If you want to know if Angular Team wants or not this feature you can see the comments here: https://github.com/angular/angular-cli/commit/75311c2a4541cd498b5376e1a5e79f515a8c7d79#commitcomment-29616137

I have nothing more to say about it, just wait to Angular Team implements it to be able to use it

Lol, this comment actually reveals my suspicions. Thank you.

If Google says: Minify your html, you must minify it.

And it's exactly what is happening.

You can't answer: I'm sorry Google, "almost of our html content is not in index.html"

You absolutely can, don't lie.

for those who load some javascripts (e.g. gtag.js)

npm i html-minifier --save-dev

node_modules/.bin/html-minifier dist/[app-name]/index.html --collapse-whitespace --remove-comments --remove-optional-tags --remove-redundant-attributes --remove-script-type-attributes --remove-tag-whitespace --use-short-doctype --minify-css true --minify-js true -o dist/[app-name]/index.html

Discussed this in our CLI triage meeting. We recognize that optimizing index.html is a clear area of improvement for Angular, and understand the desire for automated metrics to accurately reflect the state of the application. We previously did support minification of index.html but were forced to disable it due to tooling incompatibilities at the time. It also slowed down builds, required additional dependencies with varying levels of support, and generally increased complexity of the CLI.

To implement this properly, we need to minify the file as a post-process step in order to support differential loading and localization. The CLI doesn't have a great way of doing that right now, so we need to update our internal infra to better support this. There is the possibility of leveraging the Angular compiler for HTML minification (rather than an external dep), since it already needs to parse HTML for Angular templates, but that will require coordination with the compiler to support. Whether using ngc to minify HTML is actually good idea is still TBD.

In summary, minifying index.html _probably_ isn't that hard by itself, but to do it correctly would require a non-trivial amount of infrastructure work to support.

I ran PageSpeed Insights on angular.io, and I believe the HTML minification check has been removed (JS and CSS checks are present, but no HTML check was passed or failed). If someone is still seeing automated systems complaining about this, let me know. A potential 40% page size decrease sounds useful, but when it's only a few hundred bytes (before compression), the tool should be surfacing other, more impactful optimizations.

Screenshot from 2020-05-15 10-36-51

It seems that an HTML minification audit was considered by PageSpeed Insights but dropped as it was not considered impactful enough to justify the cost. Considering PageSpeed's mission of making a faster web, the amount of research and investigation they put into these questions, and the fact that this wasn't significant enough to implement, minifying an already trivial index.html file won't have a noticeable impact to users.

Considering the high infrastructure cost and the low impact of the feature I don't expect this to be prioritized soon. There are other benefits to adding the discussed CLI infrastructure, and when that gets prioritized and implemented we can revisit index.html minification as the implementation and maintenance cost will become much lower.

A note in case this gets implemented (some day 馃槢):
For apps using @angular/service-worker, we should ensure that the SW manifest is built _after_ the minification, so that the content-based hashes are correct in the manifest's hash table. See #17700 (and references in there) for details.

This issue has been assigned to the _backlog_ milestone on Jan 24, 2019.

Has there been any progress since then?

In case anybody is still looking for this kind of functionality there is another approach, you gonna need @angular-builders/custom-webpack and provide your indexTransfrom e.g.:

angular.json

{
  // ...
  "architect": {
    "build": {
      // "builder": "@angular-devkit/build-angular:browser",
      "builder": "@angular-builders/custom-webpack:browser",
      "options": {
        "indexTransform": "./path/to/index.transform.ts",
        // ...
      }
    }

  }
}

index.transform.ts

import { TargetOptions } from '@angular-builders/custom-webpack'
import { minify } from 'html-minifier'

export default (targetOptions: TargetOptions, indexHtml: string) => minify(indexHtml, {
    removeComments: true,
    collapseWhitespace: true,
    minifyCSS: 'clean-css'
  })

Benefit of this is that you do not need any additional npm scripts and as a result wont forget to run them

Was this page helpful?
0 / 5 - 0 ratings