After the upgrade from WebPack4 to WebPack5, it runs normally on Google. However, IE11 reported two compatibility problems

Webpack config

Generally, third-party dependencies are supplied to external calls using ES5 syntax, which is why the node_modules folder is often ignored when configuring Babel-Loader. In fact, most dependencies do not need to be translated, except for performance considerations

That is, when Babel is configured correctly, only the business code part of the project is polyfilled, and the syntax Babel does not apply to third-party dependencies (if you include exclude: /node_modules/).

For example, babel-loader’s 🌰:

// webpack.config.js
{
    / /...
    module: {
        rules: [{// The dependencies of node_modules are generally compiled and do not need to be compiled again
                exclude: /node_modules/  
                test: /\.(js|jsx)$/,
                loader: 'babel-loader'.options: {
                    presets: [['@babel/preset-env', {targets: 'ie 11'}]],}}]}}Copy the code

Even with this configuration, you’ll find a lot of ES6 syntax in the packaged JS files, such as the arrow function, which will simply fail when run in IE11

By default, Webpack5 does not support IE because its default runtime code uses ES6 syntax. An error will be reported when running in IE

Read the document carefully. Webpack5 configuration item Outpt. environment provides a series of configuration items about the final running environment of the code. The default configuration items do not support IE and must be specified manually

// Document configuration description
module.exports = {
  output: {
    environment: {
      // The environment supports arrow functions ('() => { ... } ').
      arrowFunction: true.// The environment supports BigInt as literal (123n).
      bigIntLiteral: false.// The environment supports const and let for variable declarations.
      const: true.// The environment supports destructuring ('{ a, b } = obj').
      destructuring: true.// The environment supports an async import() function to import EcmaScript modules.
      dynamicImport: false.// The environment supports 'for of' iteration ('for (const x of array) { ... } ').
      forOf: true.// The environment supports ECMAScript Module syntax to import ECMAScript modules (import ... from '... ').
      module: false,}}};Copy the code

Add a configuration to output.environment: this configuration indicates whether the environment in which our packaged code is running supports these syntax. Obviously, IE does not support some syntax, so change it to false

module.exports = {
/ /... Other attributes
  output: {
    environment: {
      arrowFunction: false.// The environment does not support arrow functions
      bigIntLiteral: false.// BigInt is not supported
      const: true.destructuring: false.// Deconstruction is not supported
      dynamicImport: false.// Asynchronous import is not supported
      forOf: false.// Do not support for... of
      module: false.// Module is not supported,}}};Copy the code

Another solution

Thanks to @Yukinotech for pointing out that WebPack provides another configuration that solves compatibility issues with runtime code compilation, specifying the runtime environment for WebPack so that you don’t need to change the enviroment properties one by one

// webpack.conf.js
module.export = {
    // ...
    target: ["web"."es5"]}Copy the code

Second pit: JS compression plugin -TerserWebpackPlugin

The JS compression plugin uglifyjs-webpack-plugin has been replaced by terser-webpack-plugin, and WebPack5 has built-in dependencies. The catch is that the Terser-Webpack-plugin does not use ES5 syntax by default, for example

let a = 1;
let b = {a: a}
Copy the code

This code will be compressed into:

let a=1;let b={a}
Copy the code

The ES6 syntax sugar is used in IE. This needs to be explicitly specified in the TerserWebpackPlugin

const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true.minimizer: [
        new TerserPlugin({
                ecma: 5})],}};Copy the code

The complete related configuration code is as follows:

module.exports = {
    output: {
        entry: 'main.js'.output: {
            publicPath: ' '.path: 'dist'.target: ["web"."es5"].// It can also be specified manually
            //environment: {
            // arrowFunction: false, // The environment does not support arrow functions
            // BigInt: false; // BigInt is not supported
            // Ie 10 does not support const
            // destructuring: false, // Destructuring is not supported
            DynamicImport: false, asynchronous import is not supported
            // forOf: false, // for... of
            // Module: false, // Module is not supported
            / /},
            filename: () = > (isDev ? '[name].js' : '[name].[contenthash:8].js'),
            chunkFilename: () = > (isDev ? 'assets/[name].js' : 'assets/[name].[contenthash:8].js')},target: 'web'.resolve: {
            extensions: ['ts'.'tsx'.'js'.'jsx'].alias: {
                The '@': 'src'.vue$: 'vue/dist/vue.runtime.esm.js'}},module: {
            rules: [
                // Other loaders
                {	
                    test: /\.(js|jsx)$/.// The dependencies of node_modules are generally compiled and do not need to be compiled again
                    exclude: /node_modules/
                    use: {
                        loader: 'babel-loader'.// Options can be extracted to babel.config.js, targets can be configured using. Browserslistrc
                        options: {
                                presets: [['@babel/preset-env', {targets: 'ie 11'}]],}}}],// This is normally only enabled in the Production environment
        optimization: {
            minimize: true.minimizer: [
                new TerserPlugin({
                        ecma: 5})],},}}Copy the code