Table of contents
- Table of contents
- Foreword
- General approach
- Gulp task
- Grunt task
- Side note about purifyCSS API
- Conclusion
Foreword
I'll be using purifyCSS for that
purpose. It has plugins for the most popular task runners and module
bundlers - Grunt
, Gulp
and
Webpack
. Even though, you might think that
Webpack
will be the tool of choice that is not necessarily
true. Because of the fact that internal mechanics of Angular CLI are
hidden, it might be a good idea to use a separate task runner like
Gulp
or Grunt
to avoid ejection.
In on of mine projects I use Semantic IU, where full minified version is around 623 KB. After running purifyCSS, I've got the following output:
General approach
Under the hood purifyCSS reads
content of file (HTML/JS/PHP/etc) and returns only theĀ used
CSS. Saying that, in a case of Angular, we need to check all
*.ts
and *.html
files for used CSS classes and
remove the unused ones.
Gulp task
There are some dev dependencies that needed to be installed:
npm i -D gulp gulp-purifycss
In the root of Angular project create gulpfile.js
and
add the following code:
const gulp = require('gulp');
const purify = require('gulp-purifycss');
.task('purifyCSS', () => {
gulpreturn gulp.src('./dist/styles.*.css')
.pipe(
purify(
'./src/app/**/*.ts', './src/app/**/*.html'],
[
{info: true, // Outputs reduction information (like in the screenshot above)
minify: true, // Minifies the files after reduction
rejected: false, // Logs the CSS rules that were removed
whitelist: ['*transition*', '*dimmer*'] // Ignored css classes
},
)
).pipe(gulp.dest('./dist/'));
; })
As the a final step, run Angular CLI build and created gulp task:
ng build --env=prod --prod=true --aot=true --sourcemap=false --output-hashing=all
gulp purifyCSS
As I already mentioned, in my specific case, purifyCSS was able to reduce the bundle by ~60.2%.
Grunt task
Since grunt is used as a primary build tool for many production codebases I think it's worth to implement the same functionality using that build tool.
As always, let's install required dependencies first:
npm i -D grunt glob grunt-purifycss
In the root of Angular project create gruntfile.js
and
add the following code:
var grunt = require('grunt');
var glob = require('glob');
.loadNpmTasks('grunt-purifycss');
grunt
var cssSource = glob.sync('./dist/styles.*.css').toString();
.initConfig({
gruntpurifycss: {
options: {
info: true,
minify: true,
rejected: false, // Logs the CSS rules that were removed
whitelist: ['*transition*', '*dimmer*']
,
}target: {
cwd: '.',
src: ['./src/app/**/*.ts', './src/app/**/*.html'],
css: [cssSource],
dest: cssSource
,
},
}; })
Implementation notes: considering that Angular CLI
dynamically adds generated hash to js files during the production build
and grunt-purifycss
plugin can't read/write dynamic file
names we have to use separate variable cssSource
for that
purpose.
The final step will be run Angular build and grunt task in the pipeline:
ng build --env=prod --prod=true --aot=true --sourcemap=false --output-hashing=all
grunt purifycss
Side note about purifyCSS API
As you might notice, in both cases the same options
object was used for gulp and grunt task. You might read about it more in
the official
documentation.
In my case, too much CSS was removed and that's a reason I needed to
explicitly whitelist CSS classes that did contain
transition
and dimmer
string.
Conclusion
In this example, I had a giant framework where I was using only small fraction of it which made it possible to decrease CSS size by 60.2%. However, in some other project, where CSS is written from scratch, this number should be really small, probably close zero. In any case, it's worth to try it as it doesn't require too much effort to implement this functionality.
In addition to that, this trick can also be applied to any type of framework, such as React, Vue, etc. or even non-framework Multipage Applications, CMSes as it builds on top of framework's internal build pipeline.