How to Support IE11 Users as You Move to Angular 13
Tags: angular, tutorial, codequality, ie11
Published: 2021-11-11 16:54:00

IE 11 won't be supported in Angular 13. You can support it in 12 while you migrate to 13, or drop support. Either way, you need to act.

Internet Explorer 11 is a legacy browser and support for it in Angular 13 is being dropped officially. Sticking with Angular 12 is not a viable long term option. Here are ways to support your users when upgrading your Angular version.


## Table Of Contents
* [Update tsconfig.json and populate polyfills](#tsconfig)
* [Use Differential Loading](#differential-loading)
* [How to Customize User Experience for IE 11](#customize-user-experience)
* [How to Drop Support for IE 11 the Good Way](#drop-support-the-good-way)
    


As an Angular developer, you want to provide support for as many browsers as you can, but in the case of Internet Explorer 11, this is becoming increasingly difficult, and soon will no longer be possible. Current market share is [likely less than 1%](https://gs.statcounter.com/browser-market-share#monthly-202103-202103-bar) and will drop even more as [Microsoft retires IE 11 in June 2022](https://docs.microsoft.com/en-us/lifecycle/faq/internet-explorer-microsoft-edge). 

Even more challenging is that Angular 12 doesn't offer support for IE 11 by default, and Angular 13, coming out next week, is [completely dropping support](https://github.com/angular/angular/issues/41840).

[![Angular browser support](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4phx885s2uzyxk1bb300.jpeg)](https://angular.io/guide/browser-support)


## Choose a Support Path

There are two ways you can support IE 11 with Angular 12 as you prepare to migrate to Angular 13:

1. Update `tsconfig.json` to use ES5 and update polyfills.ts for ES6/ES7

2. Use Differential Loading

Or you could decide to drop support for IE 11.  You should customize the user experience because if you don't, users will get a blank screen.


## Update tsconfig.json and populate polyfills <a name="tsconfig"></a>

By default, Angular compiles ES6 or ES7. IE 11 only supports ES5. You can update your `tsconfig.json` to target ES5. You'll also need to populate your Angular project polyfills.

Advantages of updating tsconfig.json and including polyfills:

1. Configuration prepares building and local development for IE 11 support
2. Faster builds than using Differential Loading

Disadvantages:

1. Imports a lot of polyfills and bloat bundle for legacy AND modern browsers
2. This approach has been abandoned as a standard after Angular 7


### Definitions

You'll change the target variable in tsconfig.json, and populate the polyfills file that came with the Angular project. If you're not familiar with these things, here's what they are.

<b>target</b>: JavaScript language version for emitted JavaScript.

<b>Angular polyfills</b> are fallbacks for missing JavaScript behavior. There are two types:

1. Browser polyfills that are applied before loading ZoneJS.
2. Application imports that are files imported after ZoneJS that should be loaded before your main file.

Polyfills are applied in this order: Browser polyfills &rarr; Import ZoneJS &rarr; Application imports. You will only need to focus on browser polyfills.

### The Steps

1. Open `tsconfig.json` and update `target` to `es5`.

![tsconfig example with target es2017](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qhcbt52k8zifu8fiou0a.png)

2. Open `polyfills.js` found in the src directory and add `import 'core-js';` under browser polyfills.

![es5 polyfill example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/srlznhb3rzlr37y8jqv2.jpeg)

NOTE: When serving the application, the build was at 505.3 kB. After adding the import of core-js,  it's 1.2 MB. 😬


## Use Differential Loading <a name="differential-loading"></a>

Differential Loading is the more modern technique introduced in Angular 8. The approach here is  to make two builds. One uses ES5 syntax and a more modern one that uses ES6 syntax. The ES6 build won't include as many polyfills and  going to be much smaller. The ES5 build will have polyfills and be more bloated. 


### Considerations

Advantages of using differential loading:

1. Smaller bundle sizes for modern browsers
2. ES5 bundle includes all required polyfills for legacy browser support automatically
3. Latest approach to supporting legacy browsers

Disadvantages:

1. Creates two bundles so longer build times
2. Extra configuration is required for local development for legacy browsers

### The Steps

1. Find your browser's list file. Depending on the version of Angular, it will be `.browserslistrc` or `browserslist`. 

2. Remove the word "not" from the IE 11 line.

![where to update browsers list for IE 11 support](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sdqg4dcxep5dv5srijjq.png)

Before I continue, I'll explain what just happened.

After you changed the browser's list file, when you look at your Angular project through Inspector, you'll see three additional scripts. Here's what it looked like before:

![No differential loading dom example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/50ibik1v1t2e09h1pwhu.png)

And after:

![Using differential loading dom example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okz6ej0irbs8wwa9f0hc.png)

You will have two runtimes, two polyfills, and two mains. Modern browsers will only run the top script that is of type `module`. Legacy browsers like IE 11 will run the second one, the `nomodule`.

![module vs nomodule scripts examples example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tq8te6jzcsrtnssxsv9z.png)

NOTE: The rest of these steps are only needed if you want to run the project locally in development mode if you only use differential loading.

3. Next up, you're going to create two new custom files in your application, a `polyfills.es5.js` in the src directory and `tsconfig.es5.json` at the root of your project.

4. Next steps are similar what you did for older `tsconfig.json` method above. Populate the polyfills file with your import. Then switch the tsconfig target to ES5 and to include your new polyfills file.

![es5 custom polyfill and tsconfig example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18s95616drt7zkbf1n7q.png)

5. Now you're going to update `angular.json`.

![angular json custom es5 build configuration example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swaidcz0rqk3ex3hclno.png)

Add a new build configuration. You can see on line 72 that I've added `development-es5`, where I copied all of the properties for `development`, and added two extra ones:

`"tsConfig": "tsconfig.es5.json",`

`"polyfills": "src/polyfills.es5.ts"`

6. To use this build when you serve locally, you need to add this new build configuration to the serve configurations. 

![angular json custom es5 serve configuration example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w4uooec98cfzvdkt7q8k.png)

As I did starting at line 94 above, use the same identifier, `development-es5`, and set `browserTarget` to "`handling-ie:build:development-es5"`. Now you can serve your project for IE 11 using `ng serve --configuration development-es5`.


## Why You Shouldn't Just Drop Support

You could drop support for IE 11. If you do, here's what an IE 11 user will see:

![blank page using IE 11 since IE 11 is trash](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/az7bnustz576t86c6tbe.png)

Not a good user experience. Instead, we can change a few things to let our visitor know that they need a different browser.


## How to Customize User Experience for IE 11 <a name="customize-user-experience"></a>

You don't want IE 11 users to see a white page. Instead, you can warn them about their browser or tell them to do something. Instead, you can use the same approach as you did with Differential Loading. Set a flag and take advantage of that flag to write specific code for legacy browsers.

![module vs nomodule scripts example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4mdnmi8wzjjkjeusnc4z.png)

So you can call a `no-es6.js` script that will only run for legacy browsers by using the `nomodule` attribute.

![no-es6 script example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/95wd9ir04xhjwt9al82o.png)

In this script, I set a property, `nomodule`, to true on `window`. Throughout my application, I can check for that value and I can see whether or not you are using IE.

![custom property on window example to flag IE 11](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zh9sdgsenngmotp9vzvo.png)

Note that `nomodule` is a custom property. That's not something that `window` has. Create a `window.d.ts`  in the src directory and add that property to `global`.

![types support for custom property on window or global example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sn437spsoek9hvmmxa0v.png)


## How to Drop Support for IE 11 the Good Way <a name="drop-support-the-good-way"></a>

Finally, there will probably come a time when you offer no support for IE 11 and you've turned off differential loading or whatever you were using. How do you still provide a good user experience?

You can update your browser's list to say not IE, but your users will see a blank page.

![example of where to include not to drop support for IE 11 in browsers list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ffqqykrvu6flk1mm2lx3.png)

Instead, you can update the `no-es6.js` script.

![redirecting from legacy browser example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3klzibtgy8ncu92zye6a.png)

You can do all sorts of things here. In my example, I check for iIE. If I think you’re using IE, I’m going to try to use the `microsoft-edge` handler and open Edge to navigate the site. On IE, I’ll navigate you to a [Microsoft support page](https://support.microsoft.com/en-us/topic/this-website-works-better-in-microsoft-edge-160fa918-d581-4932-9e4e-1075c4713595) that explains that IE is dropping support soon. If you're not using IE, I navigate you to a generic "hey, your browser is bad"page.


## What Will You Do?

To sum it all up, there are two main ways to support IE 11. You can update your `tsconfig.json`, or you can use Differential Loading.

And you can provide a better user experience when you are dropping support and you can also provide a better user experience when you fully drop support. It's definitely time to decide what you'll do. 

What do you think you'll do? Have these methods been helpful? Do you have other techniques for managing IE 11 and Angular 13? We'd love to know your thoughts. Drop us a note in the comments section below.


## Resources

- [Angular polyfills docs](https://angular.io/guide/browser-support#enabling-polyfills-with-cli-projects)
- [core-js](https://github.com/zloirock/core-js/tree/master/packages/core-js/es)
- [Angular 13 deprecating IE 11](https://angular.io/guide/deprecations#internet-explorer-11)
- [Angular blog on Differential Loading](https://blog.angular.io/version-8-of-angular-smaller-bundles-cli-apis-and-alignment-with-the-ecosystem-af0261112a27)
- [Javascript modules vs standard scripts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#other_differences_between_modules_and_standard_scripts)
- [Adding custom properties to Window type](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation)