Building applications/websites using Angular has a downside – the bundle size. This directly affects the loading speed and user experience of our projects. Reducing the bundle size is important.

Let’s learn how we can load stylesheets only when needed without making them part of the application bundle.

Case study

Let’s assume that apart from the main styles.css file, we have 2 theme files present:

  • src/styles/themes/theme-light.scss
  • src/styles/themes/theme-dark.scss

Next, we would have them in angular.json ‘s styles option:

"styles": [
    "src/styles.css",
    "src/styles/themes/theme-light.scss",
    "src/styles/themes/theme-dark.scss"
  ]

And lastly, we would handle the loading of a particular theme based on the users’ choice or their preferences.

Everything works great, but both of our theme files are part of our application bundle all the time, and this can increase the size of a bundle, which we want to avoid

Exclude Theme Files

Let’s make a minor change in angular.json to exclude theme files from the bundle:

"styles": [
    "src/styles.css",
    {
      "input": "src/styles/themes/theme-light.scss",
      "inject": false,
      "bundleName": "theme-light"
    },
    {
      "input": "src/styles/themes/theme-dark.scss",
      "inject": false,
      "bundleName": "theme-dark"
    }
  ]

Two new options to learn here:

  1. inject: Setting this false will not include the file from “input” path in bundle
  2. bundleName: A separate bundle will be created containing the stylesheet from “input” path

Now if we try to build the project, it will create separate files and the output will look something like below:

After we build, we can locate our two files, theme-light.css and theme-dark.css, inside the dist/ folder.

Notice that theme-light.css and theme-dark.css are part of Lazy Chunk Files. Lazy chunk files speed up the application load time, because they are loaded on demand.

Lazy Load Theme Files

We managed to exclude them from the bundle and they are externally available. Now the question arises how to load these theme files?

Within the ngAfterContentInit() method of app.component.tswe define a new function named appendStyle():

// app.component.ts
ngAfterContentInit() {
  //...
  function appendScript() {
    //Here we can append script as well
  }
  function appendStyle(name: string) {
    let style = document.createElement("link");
    style.rel = "stylesheet";
    style.type = "text/css";
    style.href = name;
    document.head.appendChild(style);
  }
}

Now, we use appendStyle() function to lazy load theme_styles.scss by calling it within the window.onload event. For example, let’s say we want to load theme-dark.scss stylesheet: ( we will use the .css extension, because the .scss was transpiled during the build process)

// app.component.ts
  ngAfterContentInit() {
    //...
    window.onload = () => {
      //...
      appendStyle('theme-dark.css');
    };
  }

Complet code here:

// app.component.ts
ngAfterContentInit() {
 window.onload = () => {

      appendStyle('theme-dark.css');
    };

  function appendStyle(name: string) {
    let style = document.createElement("link");
    style.rel = "stylesheet";
    style.type = "text/css";
    style.href = name;
    document.head.appendChild(style);
  }
}

PS: The window.onload event is fired when the entire website loads.

By Shabazz

Software Engineer, MCSD, Web developer & Angular specialist

Leave a Reply

Your email address will not be published. Required fields are marked *