Several days ago I released ionic-twitter-pwa, an Open Source project that aims to rewrite mobile.twitter.com Progressive Web App (PWA) with Ionic. I created this project to prepare this blog post but also the talk I will be delivering in the Mobile Era conference in October.

People loved it and made it trending within the Angular community for a couple of days.

This article is the first one of a serie of articles about building PWAs with Ionic-Angular and aims to help you reduce the CSS bundle of your PWA by up to 91%.

Create an app with Ionic CLI

It all starts with Ionic CLI:

$ npm install -g ionic@latest

Once installed, start a new project by running ionic start and follow the steps. To make things simple, we will create a brand new blank application, but you select the one you prefer.

$ ionic start
? What starter would you like to use:
> blank .............. ionic-angular A blank starter project

The installation takes several minutes.

Measure performance

We cannot optimize something that we have not measured first. When you start a new project, take some time to install tools that will help you doing so.

I recommend those services:

Before you measure anything make sure you build the production app. The production app minifies the JS and CSS, runs the tree shaking (remove useless imports), removes dead code etc.

$ ./node_modules/.bin/ionic-app-scripts build --prod

Open www/build/ folder and check the size of main.css file. It should be around 192 KB (for reference the entire Bootstrap CSS is only 118KB).

Let’s see what we can improve here!

Build for one platform only

Maybe you do not know but Ionic is meant to render with a different UI on three different platforms: Android, iOS and Windows Phone.

This is great when building an hybrid app but not really when building a PWA. Indeed in a PWA the size of assets really matters. Unfortunetly for us those three different styles are included in the SAME css file. That is mostly the reason why the CSS is so big.

To reduce the size of the CSS we are going to build only one design: Material Design (Android).

Open src/app/app.module.ts and replace:

IonicModule.forRoot(MyApp)

by:

IonicModule.forRoot(MyApp, {
  mode: 'md' // 'md' | 'ios' | 'wp'
})

the result is that we now have Material Design style on every platform! That’s great but the size of our CSS has not changed a bit… it is still 192 KB.

To remove iOS and WP styles we need to overwrite ionic-app-scripts sass configuration.

Create a sass.js file a the root of your project and dump the content of this file: https://github.com/ionic-team/ionic-app-scripts/blob/master/config/sass.config.js

Open package.json and add the following at the end:

"config": {
  "ionic_sass": "./sass.js"
}

Now when running any build, sass.js configuration will be used instead of the default one.

Open sass.js and modify the excludeFiles section with the following:

  excludeFiles: [
    /\.(wp|ios).(scss)$/i,
  ],

Open src/theme/variables.scss and remove @import "noto-sans"; (iOS fonts)

This will exclude Windows Phone and iOS styles out of your bundle.css. The result is a reduction by 43% (down to 109KB) of your bundle!

Remove ionicons

Ionicons are great but way too big out of the box.

I suggest to remove it, build it yourself or use icomoon with only the icons you need.

Open src/theme/variables.scss and remove @import "ionic.ionicons";.

The result is another reduction by 36% (down to 69KB) of your bundle!

Remove CSS that you do not use

If we analyse the rest of the CSS bundle, we will find out that a lot of styles are for components that we do not even use.

The complete list of component styles can be found here.

Open sass.js and modify the excludeFiles section once again with the following:

  excludeFiles: [
    /\.(wp|ios).(scss)$/i,
    /(action-sheet|alert|backdrop|badge|button|card|checkbox|chip|datetime|fab|grid|icon|img|infinite-scroll|input|item|label|list|loading|menu|modal|note|picker|popover|radio|range|refresher|searchbar|segment|select|show-hide-when|slides|split-pane|spinner|tabs|toast|toggle|virtual-scroll|cordova)/i,
  ],

For the blank app we only need to keep: app, content and toolbar but of course in a more advanced app you will need more.

The result is another reduction by 36% (down to 44KB) of your bundle!

Run purify-css

purify-css will analyse the usage of your CSS and remove what you do not use.

$ npm install purify-css --dev

Even though we managed to build only the style of the components we use, there are still styles that we do not use. If we take the toolbar for instance, the style contains definitions for toolbar-md-danger or toolbar-md-dark which are styles we won’t use.

#!/bin/bash
PATH=$PATH:$(npm bin)
set -x

BUILDFOLDER=www/

# clean up previous build
rm -fr $BUILDFOLDER

# Prod build
ionic-app-scripts build --prod \
                        --wwwDir $BUILDFOLDER

# remove unused css
purifycss $BUILDFOLDER"build/main.css" \
          $BUILDFOLDER"build/*.js" \
          --info \
          --min \
          --out $BUILDFOLDER"build/main.css" \
          --whitelist .bar-button-default

Sometimes purify-css removes style that you use. If that happens you only need to add a new whitelist rule under --whitelist.

Run the following script to reduce the bundle size by another 62.5% (down to 17KB)!

Result

Before CSS optimization

After CSS optimization

We reduced the CSS size from 192KB to 17KB which is a reduction by 91%! The size of our gzipped CSS bundle is now 3.8KB and represent only 2.1% (instead of 11.5%) of our assets size.

For reference ionic-twitter-pwa’s CSS bundle is 86KB (14.3KB Gzipped)

Thanks for reading, if you liked this article do not hesitate to share it and follow me on twitter @julienrenaux!