JavaScript - babel-preset-env not transpiling arrow functions for IE11

In addition to loganfsmyth's answer that solved the problem, I want to note for any other beginners reading this that I made life easier for myself afterward by moving the Babel configuration out of package.json into a .babelrc.

I also discovered that the plugins I needed, such as the one I mentioned above, babel-plugin-transform-es2015-arrow-functions, have newer versions with a different naming scheme - for that example, @babel/plugin-transform-arrow-functions. The documentation pages for the old versions don't mention that.

The module part of my webpack.config.js now looks like:

module: {
    rules: [
        {
            test: /\.m?js$/,
            exclude: /node_modules/,
            use: {
                loader: "babel-loader"
            }
        }
    ]
}

My .babelrc looks like:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "ie": "11"
                },
                "useBuiltIns": "entry"
            }
        ]
    ],
    "plugins": [
        "@babel/transform-async-to-generator",
        "@babel/transform-arrow-functions",
        "@babel/transform-modules-commonjs"
    ],
    "env": {
        "development": {},
        "test": {},
        "production": {}
    }
}

Update 2021: As of Webpack version 5, it outputs ES6 code by default. If you need that not to happen, you need to add a configuration setting. See Giorgio Tempesta's answer.


If you are using Webpack 5, you need to specify the features that you want to transpile in the ouput.environment configuration, as explained here: https://webpack.js.org/configuration/output/#outputenvironment.

output: {
  // ... other configs
  environment: {
    arrowFunction: false,
    bigIntLiteral: false,
    const: false,
    destructuring: false,
    dynamicImport: false,
    forOf: false,
    module: false,
  },
}

EDIT 08/10/22

While doing some refactoring of my webpack configuration, I figured out that the arrows had stopped transpiling (or maybe I didn't test extensively when giving the original answer).

Two things weren't setup correctly: the target key was missing, and the babel configuration had a wrong value.

For supporting legacy browsers, the target key needs to be set like this:

target: ['web', 'es5']

While in the Babel configuration, I had added 'not dead' in the browserslist configuration under targets in the Babel loader, so since IE11 is now technically dead, this configuration removed the trasnpilation of the arrow function.

So if you still need to transpile the arrow function, this would be the relevant part in the Babel configuration.

module: {
  rules: [
    {
      test: /\.m?js$/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                useBuiltIns: 'entry',
                targets: {
                  // be sure not to add 'not dead' here 
                  browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']
                },
                corejs: {
                  version: 3,
                  proposals: false,
                },
              },
            ],
          ],
          plugins: [['@babel/plugin-transform-runtime', { corejs: 3 }]],
        },
      },
    },
  ],
},