Search code examples
reactjswebpackbabeljsbabel-polyfill

bundle.js still contains arrow function and default parameters after using babel pollyfill


I have added many settings given by Babel or others from stack overflow but the new features of ES6 such as arrow function and default parameter are still in my bundle.js

The bundle.js has content like below:

    var nn = function(e={}) {
        const {baseClasses: t, newClasses: n, Component: r} = e;
        if (!n)
            return t;
        const a = At()({}, t);
        return Object.keys(n).forEach(e=>{
            n[e] && (a[e] = `${t[e]} ${n[e]}`)
        }
        ),
        a
    };

As a result, when I open my page in IE11, the error missing ')' happened which point to function(e={}).

Here is my webpack.config.js:

const entries = require("./config/pages").reduce(function(map, page) {
  map[page] = `./src/${page}/index.js`;
  return map;
}, {});

module.exports = {
  mode: 'development',
  entry: ["@babel/polyfill",...entries],

  output: {
    path: path.resolve(__dirname,'dist'),
    publicPath: '/',
    filename: 'myapp/static/js/[name]/bundle.js'
  },
  devtool: 'source-map',
  module: require("./config/loaders"),
  devServer:{
    open: true,
    publicPath: '/',
    historyApiFallback: true,
    disableHostCheck: true
  },
  plugins: [
    new MiniCssExtractPlugin({
        filename: "[name].css",
        chunkFilename: "[id].css"
    }),
    new webpack.ProvidePlugin({
        fetch: "isomorphic-fetch",
    })
  ]
};

and ./config/loaders for module

module.exports = {
  rules: [
    {
      test: /\.(js|jsx)$/,
      // exclude: /node_modules/,
      loader: 'babel-loader',
    },
    {
      test: /\.(css|less)$/,
      use: ["style-loader", "css-loader", "less-loader"]
    },
    {
      test: /\.(png|jpg|gif)$/,
      use: [
        {
          loader: 'url-loader',
          options: {
            limit: 500, //small than 500 use url, otherwise use base64
            outputPath:'inquiry/static/img/'
          }
        }
      ]
    },
    {
      test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
      use: [{
        loader: 'file-loader',
        options: {
          outputPath: 'myapp/static/fonts/'
        }
      }]

    }
  ]
};

the .babelrc:

{
  "presets": [
    // ["@babel/env",
    //   {
    //     "targets": {
    //       "browsers": "ie 11"
    //     },      
    //     "useBuiltIns": "usage",
    //     "corejs": "3.0.1",
    //   }
    // ],
    ["@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": "3.0.1",
      }],
    "@babel/react"
  ],
  "plugins": [
    ["@babel/transform-runtime"],
    ["@babel/plugin-transform-parameters"],
    ["@babel/plugin-transform-arrow-functions"],
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ],
  ]
}

Also, I have imported '@babel/polyfill' in my index.js

PS: I have noticed that the code contains ES6 features is from Meterial UI lib in node_modules, so I deleted exclude: /node_modules/, in babel loader rule but it still does not work.


Solution

  • We are targeting specific browsers in the @babel/preset-env plugin, defined in the babel.config.js (which is a another way of declaring the babel configuration).

        presets: [
            [
                '@babel/preset-env',
                {
                    modules: 'commonjs',
                    useBuiltIns: 'entry',
                    targets: {
                        chrome: '58',
                        firefox: '54',
                        ie: '11',
                        safari: '10',
                        opera: '44',
                        edge: '16'
                    }
                }
            ],
            [
                '@babel/preset-react'
            ]
        ],
        plugins: [
            '@babel/plugin-syntax-dynamic-import',
            '@babel/plugin-proposal-class-properties'
        ]
    

    Please try the target declaration like I posted above. We use babel/preset-env 7.3.1 and it's corejs is not a top-level config option.

    Update

    I was able to make it work with a test project of which I tried to match your setup as best as possible. You can use this to slowly add complexity and modules that you use in your project to isolate the problem. This basic setup matches yours and works well. You can use this as a starting point.

    package.json

    {
      "name": "babel-transprile-error",
      "version": "1.0.0",
      "main": "index.js",
      "license": "MIT",
      "dependencies": {
        "@babel/core": "^7.4.3",
        "@babel/plugin-proposal-class-properties": "^7.4.0",
        "@babel/plugin-proposal-decorators": "^7.4.0",
        "@babel/plugin-transform-arrow-functions": "^7.2.0",
        "@babel/plugin-transform-parameters": "^7.4.3",
        "@babel/plugin-transform-runtime": "^7.4.3",
        "@babel/polyfill": "^7.4.3",
        "@babel/preset-env": "^7.4.3",
        "@babel/preset-react": "^7.0.0",
        "@babel/runtime": "^7.4.3",
        "babel-loader": "^8.0.5",
        "mini-css-extract-plugin": "^0.6.0",
        "react": "^16.8.6",
        "react-dom": "^16.8.6",
        "webpack": "^4.30.0",
        "webpack-cli": "^3.3.1"
      }
    }
    

    webpack.config.js

    const path = require('path');
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    const webpack = require('webpack');
    
    module.exports = {
        mode: 'development',
        entry: ["@babel/polyfill", './src/page/index.js'],
    
        output: {
            path: path.resolve(__dirname,'dist'),
            publicPath: '/',
            filename: 'myapp/static/js/[name]/bundle.js'
        },
        devtool: 'source-map',
        module: require("./config/loaders.js"),
        devServer:{
            open: true,
            publicPath: '/',
            historyApiFallback: true,
            disableHostCheck: true
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: "[name].css",
                chunkFilename: "[id].css"
            }),
            new webpack.ProvidePlugin({
                fetch: "isomorphic-fetch",
            })
        ]
    };
    

    .babelrc

    {
      "presets": [
        // ["@babel/env",
        //   {
        //     "targets": {
        //       "browsers": "ie 11"
        //     },
        //     "useBuiltIns": "usage",
        //     "corejs": "3.0.1",
        //   }
        // ],
        ["@babel/preset-env",
          {
            "useBuiltIns": "entry",
            "corejs": "3.0.1",
          }],
        "@babel/react"
      ],
      "plugins": [
        ["@babel/transform-runtime"],
        ["@babel/plugin-transform-parameters"],
        ["@babel/plugin-transform-arrow-functions"],
        [
          "@babel/plugin-proposal-decorators",
          {
            "legacy": true
          }
        ],
        [
          "@babel/plugin-proposal-class-properties",
          {
            "loose": true
          }
        ],
      ]
    }
    

    src/page/index.js

    import React, { Component } from 'react';
    
    class someComponent extends React.Component {
    
        constructor(props) {
            super(props);
        }
    
        method(e = {}) {
            console.log(e);
    
            var nn = function(e={}) {
                const {baseClasses: t, newClasses: n, Component: r} = e;
                if (!n)
                    return t;
                const a = At()({}, t);
                return Object.keys(n).forEach(e=>{
                        n[e] && (a[e] = `${t[e]} ${n[e]}`)
                    }
                ), a
            };
        }
    
        render() {
            return (
                <div onClick={ e => { this.method(e) }}/>
            )
        }
    }
    
    export default someComponent;
    

    config/loaders.js

    module.exports = {
        rules: [
            {
                test: /\.(js|jsx)$/,
                // exclude: /node_modules/,
                loader: 'babel-loader',
            },
            {
                test: /\.(css|less)$/,
                use: ["style-loader", "css-loader", "less-loader"]
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 500, //small than 500 use url, otherwise use base64
                            outputPath:'inquiry/static/img/'
                        }
                    }
                ]
            },
            {
                test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
                use: [{
                    loader: 'file-loader',
                    options: {
                        outputPath: 'myapp/static/fonts/'
                    }
                }]
    
            }
        ]
    };