question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Non-optimal production build of unused CSS in all components/directives

See original GitHub issue

I created the component and added a CSS file to it, let’s say our developers write a lot of suboptimal code and forget to clean it up:

image

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [
  	'./app.component.css',
  	'./materialize.css'
  ]
})
export class AppComponent {
  title = 'app';
}
$ ng build --prod 
chunk {0} polyfills.f20484b2fa4642e0dca8.bundle.js (polyfills) 59.4 kB [initial] [rendered]
chunk {1} main.9414139e8f04fe910b03.bundle.js (main) 351 kB [initial] [rendered]
chunk {2} styles.9c0ad738f18adc3d19ed.bundle.css (styles) 79 bytes [initial] [rendered]
chunk {3} inline.7d41986913723cd10387.bundle.js (inline) 1.45 kB [entry] [rendered]

PS: main.js 351Кb? Why? I usage one component and I expect that the collector will do everything for me as it should (removed unused CSS code).

image

If I were using assets, I probably would not need to delete the unused code. And so it turns out, not only that I was generated a huge CSS, so for him also added attributes for emulating Shadow DOM.

Tested By unusedCSS extension

image

Why do not you set config up the .angular-cli.json for remove unused css?

You use webpack, but you do not use steep plugins (and loaders): plugin: https://github.com/purifycss/purifycss (8k stars) loader: https://github.com/webpack-contrib/purifycss-webpack

@IgorMinar Your team is chasing the decrease in the size of the bundle, but in the end, some novice developers may not be aware of such moments and do not believe that their applications may decrease in size.

Versions

$ ng -v
_                      _                 ____ _     ___
/ \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
/ ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
|___/

Angular CLI: 1.6.6
Node: 8.9.1
OS: win32 x64
Angular: 5.2.5
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

@angular/cli: 1.6.6
@angular-devkit/build-optimizer: 0.0.42
@angular-devkit/core: 0.0.29
@angular-devkit/schematics: 0.0.52
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.6
@schematics/angular: 0.1.17
typescript: 2.5.3
webpack: 3.10.0

Repro steps

https://github.com/splincode/css-unused-angular https://stackblitz.com/github/splincode/css-unused-angular

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:43
  • Comments:14 (4 by maintainers)

github_iconTop GitHub Comments

8reactions
mgechevcommented, Jun 2, 2019

That’s what I prototyped here http://codelyzer.com/rules/no-unused-css/.

6reactions
splincodecommented, Mar 6, 2018

@jotatoledo @IgorMinar We were able to destroy unused styles at the component level

import * as path from 'path';
import * as ngcWebpack from 'ngc-webpack';
import * as fs from 'fs';

const cssDependants = {};

function extractCssDependants(componentPath, source) {
  if (source.includes('@Component')) {
    const decorator = source.match(/@Component\(([\s\S]*)\)/)[1].split('\n').join('');
    const templateUrl = decorator.match(/templateUrl: '(.*?)'/)[1];
    const styleUrls = decorator.match(/styleUrls: \[(.*?)\]/)[1].split(',').map(x => x.trim().slice(1, -1));

    const templatePath = path.resolve(path.dirname(componentPath), templateUrl);
    const stylePaths = styleUrls.map(x => path.resolve(path.dirname(componentPath), x));

    stylePaths.forEach((v) => {
      if (!cssDependants[v]) { cssDependants[v] = []; }
      if (templateUrl) { cssDependants[v].push(templatePath); }
      cssDependants[v].push(componentPath);
    });
  }
  return source;
}
function purifyCSS(cssPath, source) {
  if (cssDependants[cssPath]) {
    const files = cssDependants[cssPath]
      .map(f => fs.readFileSync(f, 'utf8'))
      .reduce((a, b) => a + b);
    console.log(cssPath);
    return purify(files, beautify(source), {minify: true, info: true});
  }
  return source;
}

export function purifyIzolated(config: webpack.Configuration, options: WebpackConfigOptions<BuildOptions>) {
  if (options.buildOptions.environment === 'prod' && options.buildOptions.aot) {
    const root = path.resolve(options.projectRoot, options.appConfig.root);
    const tsConfigPath = path.resolve(root, options.appConfig.tsconfig);
    const mainPath = path.resolve(root, options.appConfig.main);

    const mayBeComponentRegexp = new RegExp(`^${root}.*ts$`);
    const ngc = new ngcWebpack.NgcWebpackPlugin({
      AOT: options.buildOptions.aot,
      tsConfigPath: tsConfigPath,
      mainPath: mainPath,
      readFileTransformer: {
        predicate: mayBeComponentRegexp,
        transform: extractCssDependants
      },
      resourceTransformer: purifyCSS
    });

    const compilerPluginIndex = config.plugins.findIndex(x => x.constructor.name === 'AngularCompilerPlugin');
    config.plugins[compilerPluginIndex] = ngc;
  }
  return config;
}

https://github.com/Angular-RU/angular-cli-webpack/issues/9

monkey patching angular cli: https://github.com/Angular-RU/angular-cli-webpack

Read more comments on GitHub >

github_iconTop Results From Across the Web

Optimizing for Production - Tailwind CSS
For the smallest possible production build, we recommend minifying your CSS with a tool like cssnano, and compressing your CSS with Brotli.
Read more >
4 Ways to Remove Unused CSS - Bits and Pieces
Open your Chrome browser, go to “Developer Tools”, click on “More Tools” and then “Coverage”.
Read more >
How to Remove Unused CSS for Leaner CSS Files - KeyCDN
Select a CSS file from the Coverage tab which will open the file up in the Sources tab. Any CSS that is next...
Read more >
Remove Unused CSS on Angular 9 build process
I'm trying to keep everything within Angular's build process avoiding ng eject. How do you do when deploying an Angular App to Production?...
Read more >
PurgeCSS: Remove unused CSS code - LogRocket Blog
Getting Started · Checks every CSS file in your build/static/css · Matches the selectors used in your files and removes any unused CSS...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found