Skip to content

Webpack – package: @babel/polyfill has been deprecated – How to use an alternative?

I came back to my Webpack 4 configuration and all the packages after 4 months. It always surprises me how fast a package get’s updated or deprecated.

I have this problem, that I used to include the @babel/polyfill directly to the Webpack’s entry => src together with my other JS and SASS source.

This is my current .babelrc file:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "entry",
                "corejs": "[email protected]",
                "debug": false
            }
        ]
    ]
}

And my Webpack’s entry setting:

entry: {
    src: [paths.entry.polyfill(), paths.entry.js(), paths.entry.sass()]
},

And the config where i setup all the exports:

entry: {
    sass: () => path.resolve(module.exports.sass(), './style.scss'),
    js: () => path.resolve(module.exports.js(), './index.js'),
    polyfill: () => '@babel/polyfill'
},

My package.json with the Babel files:

"@babel/core": "^7.4.4",
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"autoprefixer": "^9.4.4",
"babel-eslint": "10.0.1",
"babel-loader": "^8.0.5",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",

Is there any replacement that i can use for the @babel/polyfill as of today?

I would like to keep a polyfill but replace it with the deprecated package.

Thanks!

EDIT:

JS file causing an error for some reason Arrow functions are not working in production mode only:

(() => {
    // Do not remove this console log. It serves as a reminder to build in production mode.
    // Building in production mode removes all console, alert and debug statements.
    // NM.
    console.log(
        '%c Running main script in development mode.',
        'color: #bada55; font-size: 12px; font-weight: 700'
    );

    // Add class top HTML tag if a mobile device is detected.
    const primaryHTML = document.querySelector('html');

    if (
        /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
            navigator.userAgent
        )
    ) {
        primaryHTML.classList.add('touchdevice');
    }
})();

Webpack file:

require('checkenv').check();

// Webpack Setup
const { THEME_AUTHOR, THEME_NAME, HOST, PORT } = require('./env.config');

const path = require('path');
const paths = require('./paths.config');
const pkg = require('../package.json');
const webpack = require('webpack');

// Plugins
const HappyPack = require('happypack');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
    .BundleAnalyzerPlugin;
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const HardSourceWebpack = require('hard-source-webpack-plugin');
const BrowserSync = require('browser-sync-webpack-plugin');
const MiniCssExtract = require('mini-css-extract-plugin');
const styleLint = require('stylelint-webpack-plugin');
const CopyWebpack = require('copy-webpack-plugin');
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
const WebpackBuildNotifierPlugin = require('webpack-build-notifier');
const CleanTerminalPlugin = require('clean-terminal-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const Imagemin = require('imagemin-webpack-plugin').default;
const threadPool = HappyPack.ThreadPool({ size: 4 });

// Config utils
const { removeEmpty, getIfUtils } = require('webpack-config-utils');
const { NODE_ENV } = process.env;
const { ifProduction, ifDevelopment } = getIfUtils(NODE_ENV);

module.exports = {
    target: 'web',
    mode: ifDevelopment ? 'development' : 'production',

    stats: {
        hash: false,
        version: false,
        timings: false,
        assets: false,
        chunks: false,
        modules: false,
        reasons: false,
        children: false,
        source: false,
        errors: false,
        builtAt: false,
        errorDetails: false,
        entrypoints: false,
        warnings: false,
        publicPath: false
    },

    externals: {
        jquery: 'jQuery'
    },

    optimization: {
        minimize: ifProduction(true, false),
        namedModules: ifDevelopment(true, false),
        runtimeChunk: 'single',
        noEmitOnErrors: true,
        splitChunks: {
            hidePathInfo: true,
            chunks: 'all',
            automaticNameDelimiter: '-',
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            name: THEME_NAME,
            cacheGroups: {
                style: {
                    enforce: true,
                    priority: 1
                },
                vendors: {
                    test: /[\/]node_modules[\/]/,
                    priority: 2,
                    name: 'vendors',
                    enforce: true,
                    chunks: 'all'
                }
            }
        },

        minimizer: [
            new UglifyJsPlugin({
                uglifyOptions: {
                    parallel: true,
                    cache: false,
                    warnings: false,
                    comments: false,
                    compress: {
                        drop_console: ifProduction(true, false)
                    },
                    output: {
                        comments: false
                    }
                }
            })
        ]
    },

    entry: {
        src: [paths.entry.js(), paths.entry.sass()]
    },

    output: {
        path: paths.output.base(),
        filename: paths.filename.js()
    },

    module: {
        rules: [
            {
                test: /.js$/,
                exclude: /node_modules/,
                loaders: ['happypack/loader?id=js']
            },

            {
                test: /.scss$/,
                exclude: /node_modules/,
                loaders: [MiniCssExtract.loader, 'happypack/loader?id=scss']
            }
        ]
    },

    plugins: removeEmpty([
        new CleanWebpackPlugin({
            // Write Logs to Console
            verbose: ifDevelopment(true, false),

            // Automatically remove all unused webpack assets on rebuild
            cleanStaleWebpackAssets: true,

            // Do not allow removal of current webpack assets
            protectWebpackAssets: false
        }),

        new ExtraWatchWebpackPlugin({
            files: ['.stylelintrc', '.stylelintignore', '.eslintrc']
        }),

        new HappyPack({
            id: 'js',
            verbose: ifDevelopment(true, false),
            threadPool: threadPool,
            loaders: ['babel-loader', 'eslint-loader']
        }),

        new HappyPack({
            id: 'scss',
            verbose: ifDevelopment(true, false),
            threadPool: threadPool,
            loaders: [
                {
                    loader: 'css-loader',
                    options: {
                        url: false,
                        modules: false
                    }
                },
                'sass-loader'
            ]
        }),

        new styleLint({
            configFile: '.stylelintrc',
            context: paths.sass(),
            files: '**/*.s?(a|c)ss'
        }),

        new MiniCssExtract({
            filename: paths.filename.sass()
        }),

        new CopyWebpack([
            {
                from: paths.images(),
                to: paths.output.images()
            }
        ]),

        new CopyWebpack([
            {
                from: paths.fonts(),
                to: paths.output.fonts()
            }
        ]),

        ifProduction(
            new Imagemin({
                test: /.(jpe?g|png|gif|svg)$/i
            })
        ),

        new HardSourceWebpack.ExcludeModulePlugin([
            {
                // HardSource works with mini-css-extract-plugin but due to how
                // mini-css emits assets, assets are not emitted on repeated builds with
                // mini-css and hard-source together. Ignoring the mini-css loader
                // modules, but not the other css loader modules, excludes the modules
                // that mini-css needs rebuilt to output assets every time.
                test: /mini-css-extract-plugin[\/]dist[\/]loader/
            },
            {
                test: /my-loader/,
                include: path.join(__dirname, 'vendor')
            }
        ]),

        new HardSourceWebpack({
            environmentHash: {
                root: process.cwd(),
                directories: [],
                files: ['package-lock.json', 'yarn.lock']
            },

            info: {
                mode: 'none',
                level: 'debug'
            },

            // Clean up large, old caches automatically.
            cachePrune: {
                // Caches younger than `maxAge` are not considered for deletion. They must
                // be at least this (default: 2 days) old in milliseconds.
                maxAge: 2 * 24 * 60 * 60 * 1000,
                // All caches together must be larger than `sizeThreshold` before any
                // caches will be deleted. Together they must be at least this
                // (default: 50 MB) big in bytes.
                sizeThreshold: 50 * 1024 * 1024
            }
        }),

        new BrowserSync(
            {
                proxy: HOST,
                open: false,
                notify: false,
                port: PORT,
                files: [
                    'wp-content/themes/**/*.css',
                    {
                        match: ['wp-content/themes/**/*.php']
                    }
                ],
                snippetOptions: {
                    ignorePaths: ['wp-admin/**', 'wp-content/**']
                }
            },

            {
                reload: false
            }
        ),

        new FriendlyErrorsPlugin(),

        // new BundleAnalyzerPlugin({
        //     openAnalyzer: false,
        //     generateStatsFile: false,
        //     statsOptions: {
        //         exclude: /node_modules/,
        //         errors: false,
        //         warnings: false,
        //         errorDetails: false,
        //         reasons: false,
        //         cached: false,
        //         cachedAssets: false
        //     }
        // }),

        new CleanTerminalPlugin(),

        new webpack.optimize.ModuleConcatenationPlugin(),

        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(NODE_ENV),
            'process.env.VERSION': JSON.stringify(pkg.version)
        }),

        new webpack.optimize.OccurrenceOrderPlugin(true),

        new webpack.BannerPlugin({
            banner: `Copyright ${new Date().getFullYear()} ${THEME_AUTHOR} - v${
                pkg.version
            }`,
            exclude: /(main-vendor|main-runtime).js/i
        }),

        ifDevelopment(new webpack.HashedModuleIdsPlugin()),

        ifDevelopment(
            new webpack.SourceMapDevToolPlugin({
                exclude: /(main-vendor|main-runtime).js/i
            })
        ),

        ifDevelopment(
            new WebpackBuildNotifierPlugin({
                title: `${THEME_AUTHOR}`,
                sound: false,
                suppressSuccess: true
            })
        )
    ])
};

Answer

core-js is currently replacing bable-polyfill. You do not have to set it anywhere except for the .babelrc file I have a question, why do you duplicate libraries you have @babel/polyfill and babel-pollyfill the same applies to @babel/preset-env and babel-preset-en. You have declared in .babelrc corejs but I do not see that package.json has been installed?

My example may not be perfect but I try to strive for it 🙂

.babelrc

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

package.json

"devDependencies": {
  "@babel/core": "^7.5.5",
  "@babel/preset-env": "^7.5.5",
  "babel-loader": "^8.0.6",
  "core-js": "^3.1.4" // this is now your polyfill
  ...
}

webpack.config.js

entry: {
  app: './index.js',
},

index.js

import './style.scss';
import module from './module.js';
...

UPDATE

add to package.json, you can prepare your own list of supported browsers

"browserslist": [
  "last 2 version",
  ">1%",
  "not dead"
],

add to .babelrc

{
  "debug": true,
  "useBuiltIns": "usage",
  "corejs": 3
}

After all these additional changes in the console will appear what browsers are supported and what pollyfill have been added. And of course the most important thing is to test it in IE11. I always test on 6-7 desktop and 3-4 mobile browsers.