React-native-web: IE 11 Support

Created on 2 Apr 2017  路  13Comments  路  Source: necolas/react-native-web

Current Behavior:
An error is thrown by IE 11 at line 12 in the compiled version of NativeMethodsMixin/index.js in response to Array.from() not being supported.

Expected Behavior:
Compiled code to either include the polyfill for Array.from or not rely on the method.

OS: Windows 10
Browser: IE 11
React Native for Web (version): 0.80
React (version): 15.4.2

Most helpful comment

Sure, it can be very confusing!

Babel automatically adds the Array.from as part of the transform.

It's part of spread (the ...) in const classList = [...node.classList];

http://babeljs.io/docs/usage/caveats/#polyfills

Because for-of, spread, array destructuring all use iterators.. thus the need for Array.from or Symbol.iterator unless you use loose mode (in this case meaning we assume everything is an array). And it's a runtime check since you don't know if it's a regular array or not (unless we take advantage of type inference, which we can do in certain places https://github.com/babel/babel/pull/4747)

Regular output (REPL link)

function _toConsumableArray(arr) {
  if (Array.isArray(arr)) {
    for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
      arr2[i] = arr[i];
    }
    return arr2;
  } else {      
     return Array.from(arr);
  }
}

var classList = [].concat(_toConsumableArray(node.classList));

And node.classList is not an Array (DOMTokenList) so it doesn't hit the ^ for loop and tries to run Array.from.

Loose mode (REPL link)

http://babeljs.io/docs/plugins/transform-es2015-spread/#optionsloose

var classList = [].concat(node.classList);

If you don't use a polyfill for Array.from (recommended for an app), then library needs to include transform-runtime as a devDep (a plugin) and babel-runtime as the runtime dependency. https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-runtime

My recommendation is that the application use preset-env with the useBuiltIns option, https://github.com/babel/babel-preset-env#usebuiltins. In 2.0 (Babel 7), we'll have an option that only adds the used/necessary polyfills for compiled files https://github.com/babel/babel-preset-env/tree/2.0#usebuiltins-usage.

Hope that helps, just what I've learned? So some options:

  • Don't use [...a] (probably not)
  • Use loose mode: not recommended unless you know every use of it is an array, or you are ok with using not as spec compliant before which may cause more problems down the line when using the native spec compliant version in browsers (maybe)
  • Change Babel to infer types for this better (may be a lot of work) - maybe there's something else we can do here
  • Use babel-plugin-transform-runtime to rewrite Array.from to use babel-runtime so the user doesn't have to do anything

I think a better approach would be to warn users that you need this polyfill and provide a link for them to include.

  • Ask the user to use babel-polyfill (with my recommended https://github.com/babel/babel-preset-env) way

All 13 comments

I think a better approach would be to warn users that you need this polyfill and provide a link for them to include. This means that people not targeting IE 11 won't need bloat, and users that are have an easy way of fixing it.

I'm pretty sure this is resolvable in a way that doesn't require a polyfill and wouldn't eliminate IE support. I'll take a look at it, if no one else is interested.

It just seems really strange, because it's not actually in use in the source, but babel is utilizing it in the build.

This may be because the transpiled modules expect babel-runtime to be included as the helpers aren't inlined.

@hzoo What do you recommend doing here?

@necolas Yeah the only limitation is instance methods http://babeljs.io/docs/plugins/transform-runtime/#technical-detailscore-js-aliasing

It doesn't look like transform-runtime is in the .babelrc of react-native-web or in the preset? Otherwise I'd recommend asking users to add babel-polyfill or use https://github.com/babel/babel-preset-env. Ref http://babeljs.io/docs/usage/caveats/#polyfills

It doesn't look like transform-runtime is in the .babelrc of react-native-web or in the preset?

Do you need to use the transform-runtime plugin or babel-runtime package to avoid Babel producing code that errors in IE 11? I don't know why Array.from is in being added by Babel here. If I have to add the babel-runtime, do I set it as a peer dependency? I'm a bit confused as to what the problem and solution is.

Sure, it can be very confusing!

Babel automatically adds the Array.from as part of the transform.

It's part of spread (the ...) in const classList = [...node.classList];

http://babeljs.io/docs/usage/caveats/#polyfills

Because for-of, spread, array destructuring all use iterators.. thus the need for Array.from or Symbol.iterator unless you use loose mode (in this case meaning we assume everything is an array). And it's a runtime check since you don't know if it's a regular array or not (unless we take advantage of type inference, which we can do in certain places https://github.com/babel/babel/pull/4747)

Regular output (REPL link)

function _toConsumableArray(arr) {
  if (Array.isArray(arr)) {
    for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
      arr2[i] = arr[i];
    }
    return arr2;
  } else {      
     return Array.from(arr);
  }
}

var classList = [].concat(_toConsumableArray(node.classList));

And node.classList is not an Array (DOMTokenList) so it doesn't hit the ^ for loop and tries to run Array.from.

Loose mode (REPL link)

http://babeljs.io/docs/plugins/transform-es2015-spread/#optionsloose

var classList = [].concat(node.classList);

If you don't use a polyfill for Array.from (recommended for an app), then library needs to include transform-runtime as a devDep (a plugin) and babel-runtime as the runtime dependency. https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-runtime

My recommendation is that the application use preset-env with the useBuiltIns option, https://github.com/babel/babel-preset-env#usebuiltins. In 2.0 (Babel 7), we'll have an option that only adds the used/necessary polyfills for compiled files https://github.com/babel/babel-preset-env/tree/2.0#usebuiltins-usage.

Hope that helps, just what I've learned? So some options:

  • Don't use [...a] (probably not)
  • Use loose mode: not recommended unless you know every use of it is an array, or you are ok with using not as spec compliant before which may cause more problems down the line when using the native spec compliant version in browsers (maybe)
  • Change Babel to infer types for this better (may be a lot of work) - maybe there's something else we can do here
  • Use babel-plugin-transform-runtime to rewrite Array.from to use babel-runtime so the user doesn't have to do anything

I think a better approach would be to warn users that you need this polyfill and provide a link for them to include.

  • Ask the user to use babel-polyfill (with my recommended https://github.com/babel/babel-preset-env) way

Use babel-plugin-transform-runtime to rewrite Array.from to use babel-runtime so the user doesn't have to do anything

@hzoo aint sure if I understand this one correctly, could u elaborate with a short example? I know what transform-runtime does in general, bu aint sure what u have ment by this "to use babel-runtime so the user doesn't have to do anything"

I just mean that if you don't require the user to include a polyfill, you'll need to do it yourself in the library, which can be done with transform-runtime.

ah, misread this somehow then :) i always prefer transform-runtime as its the most efficient one imho, also it doesnt extend built-in from what I remember, which is also a good thing for me

thansk for the answer

Thanks @hzoo! I'll give some thought to this

I decided to use Array.prototype.slice to convert the nodeList, and added a note to the documentation about polyfills.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

blairio picture blairio  路  3Comments

roryabraham picture roryabraham  路  3Comments

iksent picture iksent  路  3Comments

MovingGifts picture MovingGifts  路  3Comments

buffaloDeveloper picture buffaloDeveloper  路  3Comments