14

I inadvertently introduced a backwards compatibility issue in my React app by using Array.prototype.flat. I was very surprised this didn't get resolved by transpiling - I thought this would result in es2015 compatible code.

How can I get Babel 7 to transpile this? (If my reading of the sources is right in Babel 6 there was still a plugin for this but since this has begun to roll out to browsers support has been dropped?)

Tools:

  • @babel/core@7.0.0
  • webpack@4.18.0

My top-level configuration files look like this:

webpack.config.js

var path = require('path')

module.exports = {
  entry: "./src/index.js",
  output: {
      path: path.join(__dirname, 'dist', 'assets'),
      filename: "bundle.js",
      sourceMapFilename: "bundle.map"
  },
  devtool: '#source-map',
  module: {
      rules: [
          {
              test: /\.js$/,
              exclude: /(node_modules)/,
              loader: 'babel-loader'
          }
      ]
  }}

.babelrc

{
  "presets": [ "@babel/preset-env", "@babel/react" ],
  "plugins": [["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }]]
}

.browserslistrc

chrome 58
ie 11
DerKastellan
  • 143
  • 2
  • 7
  • 6
    Babel doesn't "transpile" object methods like this - it transpiles differing *syntax* - you'd need to use a *polyfill* (if it exists) or use the alternative documented [here on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat#Alternative) - there's also https://github.com/es-shims/Array.prototype.flat – Jaromanda X Sep 11 '18 at 21:49
  • Thank you for laying it out for me, @JaromandaX. – DerKastellan Sep 12 '18 at 12:42
  • Wouldn't babel-polyfill do it? – Colin D Jan 03 '19 at 02:16
  • Hello, @ColinD. I didn't know what a polyfill was at that point but it did solve my problem, yes. – DerKastellan Jan 28 '19 at 11:36
  • I actually asked this question in curiosity because I have a project that does perform `import babel-polyfill` but I was still receiving errors from IE11 about `Object does not support property or method 'flat'` – Colin D Jan 28 '19 at 14:23

1 Answers1

8

Here is an important note: You cannot "transpile it away". You can only polyfill this.

In order to do this you can use

  • core-js@3 installed as runtime dependency
  • a configuration of @babel/preset-env to have useBuiltIns: usage, this imports the needed polyfills where needed instead of manually having import @babel/polyfill in the source code

The entire .babelrc is configured like so

  "presets": [                                                                                                                                               
    [                                                                                                                                                        
      "@babel/preset-env",                                                                                                                                   
      {                                                                                                                                                      
        "targets": {                                                                                                                                         
          "node": 4                                                                                                                                          
        },                                                                                                                                                   
        "useBuiltIns": "usage",                                                                                                                              
        "corejs": 3                                                                                                                                          
      }                                                                                                                                                      
    ]                                                                                                                                                        
  ]                                                                                                                                                          
}     

Alternatively you could have @babel/polyfill as a runtime dependency in your package.json and import "@babel/polyfill" in your code.

All of the details you need are on this page https://babeljs.io/docs/en/babel-polyfill but there is a lot of subtlety

I created this minimal example to demonstrate

https://github.com/cmdcolin/babel-array-flat-demo

After compiling you get proper imports added to your file https://github.com/cmdcolin/babel-array-flat-demo/blob/master/dist/index.js and this works with old versions of node.

Colin D
  • 2,822
  • 1
  • 31
  • 38
  • Also I ran into a pretty obscure corner case of ts-jest, typescript, etc that required me to add "setupFiles": ["core-js"] to jest.config.js or the jest config in package.json https://github.com/kulshekhar/ts-jest/issues/828 – Colin D Mar 29 '19 at 15:55
  • Another note though: Usage of things like Object.values(obj) and Object.entries(obj) do get compiled away and can be replaced with the corejs-pure library which is a ponyfill – Colin D May 28 '19 at 14:34