Lazy-loading CSS in your AngularJS app – Opinionated AngularJS – Medium
- You are already loading CSS files using the link element but are facing CSS reflow issues you want to avoid.
- Remember the browser has to download the content after adding the link element and even after that, the new stylesheets take few more ms to be available to the DOM.In Angular your routes are a good place to start when chopping up your application into sections.
- You could inject CSS into your template but then you will be missing out on browser caching and making your templates bigger.Splitting CSS files using $route.resolveIn order to inject our CSS file while navigating to a new route we will use $route.resolve.
- See VIISON/RequireCSS and stackoverflow.In order to inject our CSS we:inject a link tag into the head elementhook to link.onload event (fires only in some browsers)check document.styleSheets for changesIn case the CSS fails to load, Eg.
- $http will always make an initial request even after being cached on the browser using the link tag.It makes no difference having called $http with the same CSS file.
It’s common practice to use one big CSS file for the whole application. This file is usually the result of various build steps: compilation, concatenation and minification. Tools such as Gulp or…
Download and inject stylesheets on demand using $route.resolve
Follow me on Twitter for latest updates @gerardsans.
It’s common practice to use one big CSS file for the whole application. This file is usually the result of various build steps: compilation, concatenation and minification. Tools such as Gulp or Grunt are great at this.
Relying on one big stylesheet is all good and fine for small projects but what happens when the website keeps growing and more rules are added to it? As you keep adding new sections and components, it gets bigger and bigger. One day it hits your desk… The first visit to your app is taking few seconds to load… You dig a little into it and find that there is a big monolithic CSS sitting in your browser.
What options are there for you now? Well, you clearly have to split your CSS into separate files. A sensible option would be to make a stylesheet for the different sections of your application.
This is just one of the reasons why you would want to cut down on CSS. Here’s some other scenarios why you should lazy-load your stylesheets:
In Angular your routes are a good place to start when chopping up your application into sections. Each route already loads its corresponding template and attaches the controller. It would make sense to also load stylesheets this way, but unfortunately that’s not supported. You could inject CSS into your template but then you will be missing out on browser caching and making your templates bigger.
In order to inject our CSS file while navigating to a new route we will use $route.resolve. We are going to use resolve in a way that navigation will only happen after we have injected our CSS. See $routeProvider.when() for more details.
We moved the actual code to a factory Service called injectCSS that contains a function set(id, url) returning a promise. This is the actual implementation of the service.
This code takes ideas from different sources and adds some personal choices in. See VIISON/RequireCSS and stackoverflow.
In order to inject our CSS we:
In case the CSS fails to load, Eg. network failure, it will keep on going after the browser adds an entry on styleSheets.
While working on the final solution I found out about a couple of things I didn’t know before:
Find an online workbench I used to try different configurations here. Have any questions? Ping me on Twitter @gerardsans.
Thanks Gert Hengevelt for kindly reviewing this post and publishing it at Opinionated AngularJS.