Internet Explorer retires on June 15 - what can developers do?
Tags: webdev, browser, javascript, ie11
Published: 2022-05-24 16:12:15

Microsoft will finally stop supporting Internet Explorer 11 on June 15, 2022. That is ~~3 weeks from now~~ **RIGHT NOW**!

If a Windows 10 or Windows 11 user tries to open IE after this date, the Edge browser will launch instead (or the user will be taken to the download page for Edge). 

![Edge notification](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oedpxscxsqwbni2ej266.png)

There is an IE11 compatibility mode to support legacy apps, but it may not work exactly the same. This legacy mode is supported until 2029, so we won't be completely rid of Internet Explorer for some time. However, if you are a developer that is building modern web apps, I think it's better to drop support for Internet Explorer completely.

In this article, I will explain what the problems of supporting Internet Explorer are and how you can move to a better alternative.

# What's the problem with IE11?

According to Microsoft itself, [IE is not a browser but a compatibility solution](https://www.zdnet.com/article/microsoft-security-chief-ie-is-not-a-browser-so-stop-using-it-as-your-default/) for legacy apps. New browser features are not supported by it, which means new apps do not work out of the box in IE. By using IE, you are effectively going back in time to experience the web as if it were [2013](https://en.wikipedia.org/wiki/Internet_Explorer_11#History) (the most recent updates being only security patches).

The global market share (desktop - April '22) of IE is as low as [0.4%](https://gs.statcounter.com/browser-market-share/desktop/worldwide), compared to 64% for Chrome, 10% for Edge, 10% for Safari and 7.9% for Firefox. So who is still using it? Mostly [users of legacy applications](https://qz.com/2011408/some-companies-will-still-use-internet-explorer-after-its-retired/),  people who work at companies with strict browser policies and... [Japan](https://www.ft.com/content/a71ace1b-37b8-49f4-b8a5-baddbdb67b8b), apparently.

From a technical perspective, developers that need to support IE cannot make full use of new browser features in their apps that work out of the box in evergreen browsers such as Chrome, Firefox and Microsoft's newest Edge browser. 

IE11 only works with an older version of JavaScript, namely ECMAScript 5 (ES5). Developers can use tools like Babel so they can still write modern JavaScript (ES6 and beyond), which gets translated back to ES5 so it works in every browser. This "transpilation" inevitably creates overhead in the resulting code bundle. Furthermore, some third party JavaScript libraries may only be available in ES6, so an app developer has to make additional effort to ensure those libraries are transpiled as well.

Other frameworks and tools are also abandoning IE11: [Webpack 5 bundles for ES6 by default](https://webpack.js.org/migrate/5/#need-to-support-an-older-browser-like-ie-11), [React 18](https://reactjs.org/docs/javascript-environment-requirements.html) and [CRA](https://create-react-app.dev/docs/supported-browsers-features/) dropped support, to name a few. If you want to stay up to date, that means you will need to make the decision at some point.

Dropping support for a browser means that you potentially lose revenue of its users. A bigger problem, however, is that supporting IE11 causes a degraded performance for *all other browsers*. It will also lock your app out of innovative new features such as [Progressive Web App features](https://web.dev/progressive-web-apps/) (unless you apply [graceful degradation](https://developer.mozilla.org/en-US/docs/Glossary/Graceful_degradation)).

# Unsupported features in IE11

[This page](https://caniuse.com/?compare=ie+11,edge+101&compareCats=all) compares supported browser features between IE11 and Edge version 100. The length of this list is staggering, to be honest. Some notable features:
  - [DOM manipulation methods](https://caniuse.com/?search=dom%20manipulation)
  - Full [CSS Flex](https://caniuse.com/?search=css%20flex) and [CSS Grid](https://caniuse.com/?search=css%20grid) support
  - [CSS sticky](https://caniuse.com/css-sticky)
  - [CSS filters](https://caniuse.com/css-filters)
  - Input types for [date and time](https://caniuse.com/input-datetime) and [color](https://caniuse.com/?search=color%20input)
  - [Service Workers](https://caniuse.com/serviceworkers) and most other PWA related features
  - [Fetch](https://caniuse.com/fetch)
  - [Custom elements](https://caniuse.com/custom-elementsv1)
  - [Resize observer](https://caniuse.com/resizeobserver)

Missing JS language features I personally use almost every day:
  - [ES6 language features in general](https://kangax.github.io/compat-table/es6/)
  - [Arrow functions](https://caniuse.com/?search=arrow%20function)
  - [Template literals](https://caniuse.com/template-literals)
  - [Promises](https://caniuse.com/promises) and [Async functions](https://caniuse.com/async-functions)
  - [Object.entries](https://caniuse.com/object-entries)
  - [Array.find](https://caniuse.com/array-find)
  - [Classes](https://caniuse.com/es6-class)

## Transpilation example

Consider the following piece of code where I showcase some ES6 features:

```js
const doStuff = async () => {
  const foo = "bar";
  let qux = `${foo} with extra ${foo}`;
  
  return await new Promise((resolve) => {
    resolve(qux);
  });
};
```

This code doesn't do anything useful, but if you press F12 in a modern browser to open your developer tools and paste it in the console, it will run just fine.

Now [watch the result](https://babeljs.io/repl#?browsers=ie%2011&build=&builtIns=false&corejs=3.6&spec=false&loose=false&code_lz=MYewdgzgLgBAJiAylArgMzTAvDAhhATzGBgAoBKbAPhgG8AoGGUSWNEEbGAIgCNcATtwDcjGOxAA6AJbEANijgBTCKW6Du5UWLlLYARxQAPLgAMAJLQkBfGAHdpUABYwlRqANwxLN06KZiAnooAmB4driOMGBKdjAACgIgALbSEEqkpEEQIHIAbkqUWDQMTEzZuQVq_ABemv4w1lr01sJAA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env&prettier=false&targets=&version=7.18.1&externalPlugins=&assumptions=%7B%7D) if we transpile this code using Babel to something that IE11 understands. If you scroll down to line 11 in the frame on the right you will see something that looks like our original function. All the cruft above it is required to make it run in old browsers.

```js
var doStuff = /*#__PURE__*/function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
    var foo, qux;
    return _regeneratorRuntime().wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            foo = "bar";
            qux = "".concat(foo, " with extra ").concat(foo);
            _context.next = 5;
            return new Promise(function (resolve) {
              resolve("baz");
            });

          case 5:
            return _context.abrupt("return", _context.sent);

          case 6:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));

  return function doStuff() {
    return _ref.apply(this, arguments);
  };
}();
```

This example showcases how building for IE11 negatively impacts your bundle size, build time, total byte size sent over the network, parse time and page load time! More about transpilation bloat in [this article](https://webreflection.medium.com/avoiding-babels-production-bloat-d53eea2e1cbf).

# Benefits of dropping IE11 in your web app

- Use modern browser features (such as the ones listed above) out of the box. 
- No need to support IE11 quirks. Ugly hacks to make edge cases work on IE11 can be removed, which leads to cleaner code that is easier to maintain.
- The JavaScript code that is served by your app in production can be optimized for modern standards, which means transpilers such as Babel have less features to polyfill. This can potentially reduce the size of your code bundle by as much as 30%!
- Simplify your testing and quality assurance process.

# How to phase out IE11

As a developer, you can lead the discussion about whether or not to support IE11 with technical arguments mentioned above. Make dropping IE11 support a company goal! Put it on a roadmap! This is not just a development issue, other departments should also contribute and inform customers about the plan. As with most things in life: communication is key! 

- Communicate the deadline for dropping IE support to your customers, so they can prepare if needed. Switching to different browser may not be an issue for them at all. The not so tech-savvy users may not be aware they are still using an outdated browser. Companies may have an outdated browser policy which only allows IE11 for legacy reasons (or no policy at all).
- Show a banner at the top of your app to warn the user if it detects IE11 usage.
- If possible, gather browser usage statistics for your app.
- Document any features of your app that require IE11 support on your Wiki/Confluence/README. Are these features still relevant or can they be refactored to modern JavaScript?
- Write a knowledge base article about the browsers your app supports and how users can switch to a safe alternative.

# How to drop IE11 support from your web app

The following steps explain how to optimize your project to drop IE11 support. Sometimes we need to tell our build tools that they don't need to transpile code for older browsers. The production bundle will no longer include patches for missing features, which will save you some precious bytes.

## Use browserslist

If you are developing a web application, you are most likely using technologies such as [Babel](https://babeljs.io/) with the [preset-env plugin](https://babeljs.io/docs/en/babel-preset-env) and Webpack to bundle your code. You can set a `browserslist` ([docs](https://github.com/browserslist/browserslist)) property in `package.json` (or `.browserslistrc` file) to set the browsers you want to target:

```json
"browserslist": {
     ">0.2%",
      "not dead",
      "not IE 11"
   }
}
```

You can customize the query using [this tool](https://browserslist.dev/?q=PjAuMiUgIGFuZCBub3QgZGVhZCBhbmQgbm90IGllIDEx).

## Remove redundant Babel plugins

Furthermore, some Babel plugins for ES6 language features can be removed from your project and from the babel configuration, if you were still using them. Check [this list](https://babeljs.io/docs/en/plugins-list#es2015) and remove them from your project. 

Note: These plugins are all included in [preset-env](https://babeljs.io/docs/en/babel-preset-env), so chances are small you were using them. Still worth checking though.

## Specific tool examples

Most frameworks and tools will automatically use the `browserslist` configuration. Just because your framework says it does not support IE11 doesn't mean the code it produces is optimized for ES6. Sometimes you still need to set the `browserslist` yourself.

Here is the behaviour of some of those tools:

- [Create React App](https://create-react-app.dev/docs/supported-browsers-features/#configuring-supported-browsers): generates a `browserslist` config for you, but you need adjust it to exclude IE11 (as above).
- [Next.js](https://nextjs.org/docs/basic-features/supported-browsers-features) supports IE11, *does not respect browserslist for JS (only CSS)!* It seems you need a custom [babel config](https://nextjs.org/docs/advanced-features/customizing-babel-config) and configure the [preset-env targets option](https://babeljs.io/docs/en/babel-preset-env#targets)
- [Remix](https://remix.run/docs/en/v1/guides/browser-support): no IE11 support, promises progressive enhancement
- [Angular](https://angular.io/guide/browser-support): no IE11 support out of the box(?) 🎉
- [Svelte](https://github.com/sveltejs/svelte/issues/558): ???
- [Vue 3](https://cli.vuejs.org/guide/browser-compatibility.html#browser-compatibility): Configure browserslist as above. Also offers [modern mode](https://cli.vuejs.org/guide/browser-compatibility.html#modern-mode) for differential serving.
- [Nuxt](https://nuxtjs.org/docs/configuration-glossary/configuration-modern/): need to build with the `--modern` option.
- [Ember 4](https://emberjs.com/browser-support/): no IE11 support, set targets in `./config/targets.js` using [ember-cli](https://github.com/babel/ember-cli-babel)
- [Webpack 5](https://webpack.js.org/configuration/target/): You need to configure the `browserslist` as above.
- [Vite](https://vitejs.dev/guide/build.html#browser-compatibility): targets ES6 by default and uses a `browserslist` query that does not target IE11 (so it works out of the box 🎉).

# Progressive enhancement for modern browsers, fallback for IE

If you want to show at least _something_ to IE users, instead of an empty, broken page, you could use the `<script>` tag with a `nomodule` attribute. This is only used by browsers that don't support [JS modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), which happens to be IE!

```html
<!-- Your ES6+ bundle for modern browsers -->
<script type="module" src="index.mjs"></script>

<!-- Fallback for IE -->
<script nomodule>
  console.error("No module support, could not load app");
  document.body.classList.add("has-old-js");
</script>
```

You could go down the path of creating one ES5 bundle for IE users and an ES6+ bundle for other browsers. This technique is called [differential serving](https://johnstew.github.io/differential-serving/). But now that IE11 is no longer supported, you should really ask yourself if this is worth the effort.

# Detect IE11 using JavaScript

Checking supported browser features:
```js
!!window.MSInputMethodContext && !!document.documentMode
```

Checking the user agent:
```js
navigator.userAgent.indexOf('MSIE') !== -1
|| navigator.appVersion.indexOf('Trident/') > -1
```

# Conclusion

So should your app still support IE? Unless you are working on a legacy app for a customer with specific needs, the answer is **probably not**. Microsoft does not even support IE in its own [Teams](https://docs.microsoft.com/en-us/microsoftteams/limits-specifications-teams#browsers) app. You should at least have a plan to move away from supporting IE and inform your customers about it.

Ask yourself: What is the cost of supporting IE11, in terms of time spent on maintenance, fixing obscure bugs, code complexity, technical debt, negative performance impact, exceptions in the build process and even testing?

It's time to move forward and start writing code for the modern web.

# Sources

- https://css-tricks.com/a-business-case-for-dropping-internet-explorer/
- https://medium.com/doctolib/supporting-internet-explorer-11-in-2019-12dc1f1ebc3c
- https://codeandchaos.medium.com/the-end-of-life-of-internet-explorer-11-12736f9ff75f
- https://dev.to/samthor/what-to-expect-when-you-re-expecting-to-drop-ie11-ifg