EDIT: FROM ANGULAR V13, IE11 CAN NO LONGER BE SUPPORTED. IF YOU NEED TO SUPPORT IE11, PLEASE USE A VERSION OF ANGULAR <13
In this article I will show you the steps I took to support Internet Explorer 11 with Angular. The first half of this will quickly show the steps you need to take, and the second half will break these steps down in more detail for anyone wishing to learn more. At the end I'll add some additional tips that may come up in a real-world application.
💪 Let's get it done
🎯 Step 1 - Targeting ES5
IE11 only supports at best ES5. Therefore we have to update our tsconfig.json
.
Update the target
property in compilerOptions
to match the following, if not already:
"compilerOptions": {
...
"target": "es5"
}
🌐 Step 2 - Update broswerlist
Open you browserlist
file and change the line not IE 9-11
to match:
not IE 9-10
IE 11
🔧 Step 3 - Polyfills
If you or any of your dependencies use features from ES6+, you're going to need to polyfill those. CoreJS is included with Angular install, and can be used for the majority of the polyfills you require.
Open your polyfills.ts
file and place the following at the top under BROWSER POLYFILLS
:
If you need a quick win (NOT RECOMMENDED):
import 'core-js';
Otherwise, try to discern what polyfills you need. I found that these covered my use-case:
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';
import 'core-js/es6/array';
import 'core-js/es7/array'; // for .includes()
The next part we need to do is to find the following lines, near the top of polyfills.ts
:
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
As instructed run:
npm install --save classlist.js
and then uncomment the import:
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
import 'classlist.js'; // Run `npm install --save classlist.js`.
If you use Angular Material or the AnimationBuilder
from @angular/platform-browser/animations
then find the following line:
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
Uncomment it and run npm install --save web-animations-js
.
Your final polyfills.ts
file should look similar to:
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';
import 'core-js/es6/array';
import 'core-js/es7/array'; // for .includes()
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
import 'classlist.js'; // Run `npm install --save classlist.js`.
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/
✅ Completed
And that's it! You should be good to go! 🚀🚀
You may well run into further issues. Some of these will now be discussed in the second half of this article.
🤯 But why?
Let's go quickly go through the why's of each step above before we go into some further tips on additional problems that may arise.
- Target ES5: Pretty straightforward, IE11 only supports ES5 or lower. Therefore, TypeScript needs to Transpile your code to ES5 compatible code.
- Browserlist: This is an interesting one. We need to say we are supporting IE 11, but if we are not supporting IE 9 or 10, it's equally important to specifically say we aren't supporting them, otherwise the differential loader will include a lot of guff. (Thanks @wescopeland_ for that advice)
- Polyfills - Some of the libraries we work with, or code we write, relies on features from versions of ECMAScript that IE11 doesn't support, therefore we need to provide this functionality to ES5 manually using workarounds. This will allow the code using modern features to continue to work correctly. (Note: Each polyfill will increase the bundle size, so be careful when choosing which polyfills to import)
💡 Some additional tips
Ok, so the motivation to write this article came from being tasked to support IE11 in our green-field app. It was particularly painful as it was an afterthought that then highlighted compatibilities issues with supporting IE11:
Third-party dependencies need to support ES5
This became evident quickly as the errors were easily spit out into the console. But it did highlight an interesting problem.
Now if we want to include a new dependency or library in our application, we need to make sure that it builds to and supports ES5, otherwise, we have to skip it. This could potentially limit our choices going forward, which is never ideal.
IE11 doesn't support CSS Custom Properties
This became hell quickly. IE11 doesn't support CSS Custom Properties such as --primary-color: blue;
which meant our theming solution was potentially on the ropes.
After a lot of investigation, I found that it could be polyfilled, however, the polyfills that I found were slow, had a huge impact on the bundle size and not entirely perfect. missing features such as multiple Custom Properties in one line among other issues.
They also didn't work for our particular use-case and our theming solution which relied on runtime setting of the Custom Properties.
My solution to this came from the css-vars-ponyfill that allowed the setting of global Custom Properties at runtime. Awesome 🔥🔥
Setting the style
attribute in IE11
IE11 will only allow the setting of a DOM Element's style
attribute with CSS Properties it supports.
For example, doing the following:
document.body.style = '--primary-color: blue; font-size: 18px';
results in the following on IE11, losing the --primary-color: blue
.
<body style="font-size: 18px"></body>
Styling issues arising from flexbox support
IE11 does support flexbox, but it's very picky about how it does so. I noticed that if I wanted to use flex: 1;
to allow an element to fill the remaining space, on IE11 I had to set the full flex property: flex: 1 0 auto;
or something similar.
Running DevTools in IE11 conflicts with zone.js
Yep. For some reason, when you open dev tools whilst having ng serve
running on IE11 causes conflicts with zone.js
;
To fix this you need to add a global ZONE FLAG
for zone to execute slightly additional code.
You do this in polyfills.ts
. Find the zone.js
import and add the following so it looks like this:
(window as any).__Zone_enable_cross_context_check = true;
import 'zone.js/dist/zone'; // Included with Angular CLI.
😭 Conclusion
I did not have fun trying to get this to work during the week. Now that I have it supported; I feel pretty accomplished 💪.
I hope this article can save someone some pain in the future!
Hopefully you have gained something from reading this article, maybe a tidbit you didn't know before.
If you have any questions, feel free to ask below or reach out to me on Twitter: @FerryColum.
Top comments (14)
Nice summation on what is required. Our team had already implemented most of these but others using our Angular library were not able to get some of the features in our library to work. Thank you for putting this together!
To give support for IE 11 is huge pain in the ass.. I trying my butt off from past 2 days tried each and every solution given on any blog or any video... tried the which is here as well still there is no luck with me...
I'm still facing the issue.
What issues are you seeing?
Here is my pollyfills.js
/***************************************************************************************************
$localize
onto the global scope - used if i18n tags appear in Angular templates. / import '@angular/localize/init'; /*/***************************************************************************************************
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';
/** Issue with IE and FormData **/
import 'formdata-polyfill';
/** IE10 and IE11 requires the following for NgClass support on SVG elements /
import 'classlist.js'; //Run
npm install --save classlist.js
./*
@angular/platform-browser/animations
import 'web-animations-js'; // Run
npm install --save web-animations-js
.import 'core-js/client/shim';
/**
zone.js
being loaded, and webpackzone.js
patch for IE/Edge */***************************************************************************************************
Also I have attached the IE11 Error page.
IE11Screenshot
Doesn't look like images attached. Can you message me on Twitter @FerryColum ?
I have also added the necessary Meta tag edited the tsconfig.js to target es5 edited browserlist pretty much everything.
TIL IE11 support in Angular is a huge pain.
Without having looked into it much and knowing that
ng eject
is now nonviable, I wonder if @angular-builders/custom-webpack might be a gateway to having a webpack config that transpiles 3rd party libraries into es5 to fit this use case.Funnily enough, I explored this option when I was trying to get the CSS Custom Properties to work.
I did not consider this for the dependencies. I'm sure there might be a Babel Plugin that might do this. It's worth the investigation.
I would state that Angular is not the best solution if you have to support IE 11 then. For whatever reason you still have to support IE11 (enterprise maybe?), using modern frameworks with it is never an ideal solution, so going back to something more easier would be probably the way to go then.
I'm actually going to disagree. It was still possible to support IE11, fully, despite the polyfills and ponyfills.
Knowing the limitations now allows us to move forward keeping these restrictions in mind, but Angular on its own is not to fault, and potentially shouldn't be overlooked just because IE11 has to be supported.
It also allows us to continue to develop in a modern environment, which keeps the option that if we ever no longer have to support IE11, due to changes in SLAs, then we can remove the polyfills and alter the target in the tsconfig compilerOptions to target a more modern version of ECMAScript.
I've worked on a few apps with Angular that support IE11, had no issues that were Angular specific. Also with Angular 8 there's
differential loading
which produces polyfill bundles for older browsers alongside smaller bundles for modern browsers (it's very clever!)It is, I have a note in the article how it can increase bundle size if you allow it to run for IE9 and 10.
From what I've experienced though, was that dropping the target to es5 meant that your dependencies have to support es5.
I left a comment under one of the feedback to this article to state that it was very possible to support IE11, and in truth, Angular did not in itself have any issues, however, the additional tools you might use along with it will need extra work
I am getting the below error in IE11. I am using promise in App_initializer.
Can you please help.
https://www.google.com/url?sa=i&url=https%3A%2F%2Fcodepureandsimple.com%2Fpolyfilling-internet-explorer-11-a715c5b3c72&psig=AOvVaw3qAkJ2dlplBjbH95alGDN1&ust=1600592007830000&source=images&cd=vfe&ved=0CAIQjRxqFwoTCODhwoPs9OsCFQAAAAAdAAAAABAJ