/reactie

A solution that makes React stack work in IE8.

Primary LanguageJavaScriptMIT LicenseMIT

简体中文 | English

Reactie

This solution will show you how to use React stack in IE8, then you don't have to change the technology stack when the customer uses legacy browser. It uses ES6, Webpack, Babel, ESLint, Ant Design 1.x, React 16, Reach, Rematch, etc. See Reactie Todo.

Shim & Polyfill

Choose the shims and polyfills you need.

  1. es5-shim: A patch that provides all ES5 methods which can be faithfully emulated for the legacy browser;
  2. console-polyfill: Browser console polyfill. Makes it safe to run console.log() etc always;
  3. @babel/polyfill: A patch emulates a full ES2015+ environment;
  4. es6-proxy-polyfill: Proxy polyfill based on ES3 supports IE8, Node.js, etc;
  5. es6-promise: A polyfill of the ES6 Promise;
  6. bluebird: A full featured Promise library with unmatched performance;
  7. fetch-ie8: A window.fetch JavaScript polyfill supporting IE8;
  8. fetch-polyfill2: The fetch polyfill which supports all mainstream browsers, even IE6, IE7, IE8;
  9. html5shiv: This library enables use of HTML5 sectioning elements in legacy Internet Explorer and provides basic HTML5 styling for Internet Explorer 6-9, Safari 4.x (and iPhone 3.x), and Firefox 3.x;
  10. matchmedia-polyfill: A polyfill for testing whether a CSS media type or media query applies;
  11. Respond.js: A fast & lightweight polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more);
  12. ...

Main Library

  1. es5-shim: A patch emulates the ES5 environment;
  2. @babel/polyfill: A patch emulates the ES6+ environment;
  3. anujs: A React-like library, supports most features of React 16, works well in IE8, created by Shitou Nasami;
  4. reach: A React router library. I use the compatible version provided by anujs, which is modified to support IE8's hashchange;
  5. rematch: A state manager for React. Anujs also provided a compatible version;
  6. antd: A React UI framework. Antd 1.x is the last version that supports IE8.

Compile & Pack

  1. Object.defineProperty: It can't be emulated in IE8, you must not use this method;
  2. ES Module: To avoid ES Module being transformed into Object.defineProperty, the preset @babel/preset-env should be configured as follows;
{
  loader: 'babel-loader',
  options: {
    presets: [
      ['@babel/preset-env', {
        loose: true,
        modules: 'commonjs',
      }]
    ]
  }
}
  1. Reserved Words: Use es3ify, es3ify-loader or UglifyJS to transform your code;
// Config
[
  new UglifyJsPlugin({
    uglifyOptions: {
      ie8: true,
      ...
    }
  })
]

// Before
var obj = { default: 1 };

// After
var obj = { "default": 1 };
  1. Module Alias: Create aliases to import or require certain modules more easily, for example using anujs instead of React.
// Config
{
  resolve: {
    alias: {
      'react': 'anujs/dist/ReactIE',
      'react-dom': 'anujs/dist/ReactIE',
      ...
    }
  }
}

// Code
import React from 'react';  // `anujs` was loaded, actually

Error Solution

Error Reason Resolve
'JSON' is undefined Need to use IE8 Standards Mode Add <!DOCTYPE html> and <meta http-equiv="X-UA-Compatible" content="IE=EDGE"/>
无法获取未定义或 null 引用的属性“appendChild” document.head isn't exist in IE8 Add document.head = document.getElementsByTagName('head')[0]
无法获取未定义或 null 引用的属性“focus”, happen in this.calendarInstance.focus() (Use antd 1.11.6) calendarInstance is undefined, caused by this.saveCalendarRef = refFn.bind(this, 'calendarInstance') Use this.saveCalendarRef = refFn.bind(this, 'calendarInstance', this)
Object.prototype.propertyIsEnumerable: 'this' 不是 JavaScript 对象, happen in the function getLocation of Reach (Use anujs 1.4.8) After transforming by Babel, getLocation uses Object.prototype.propertyIsEnumerable.call(location, prop) to judge whether window.location has certain properties, and it doesn't work in IE8 See anujs issue #344
Accessors not supported! Your code is transformed into Object.defineProperty.
For example, Redux uses a library symbol-observable, which is transformed into Object.defineProperty
Find it, and change it.
I have rewritten the library symbol-observable
IE8 sinks into endless loop, happen in the function isPlainObject of Redux isPlainObject uses the function getPrototypeOf of es5-shim to traverse the prototype chain, that causes endless loop See es5-shim issue #458

Reference

  1. react-ie8