Babel通过webpack v5无法为IE8或WebBrowser控件生成有效的ES3代码

dluptydi  于 2022-11-13  发布在  Webpack
关注(0)|答案(1)|浏览(286)

我正在尝试使用webpack v5.74.0和babel-loader 8.2.5来传输和打包Javascript代码,这些代码必须与微软的WebBrowser控件(即IE 8 /ES 3标准)兼容。特别是,当遇到JS代码时,WebBrowser控件会抛出“预期标识符”错误,其中方法名称也是JS关键字,例如Set.delete()。
下面是一个小测试用例:

项目结构

$ ls -l -R --hide=node_modules
.:
total 266
drwxr-xr-x 1 demo.user 197121      0 Oct 21 17:32 dist/
-rw-r--r-- 1 demo.user 197121 265954 Oct 21 16:56 package-lock.json
-rw-r--r-- 1 demo.user 197121    393 Oct 21 18:09 package.json
drwxr-xr-x 1 demo.user 197121      0 Oct 21 16:06 src/
-rw-r--r-- 1 demo.user 197121    917 Oct 21 17:45 webpack.prod.js
-rw-r--r-- 1 demo.user 197121    145 Oct 21 17:16 xxxbabel.config.json

./dist:
total 1
-rw-r--r-- 1 demo.user 197121 94 Oct 21 17:33 main.js

./src:
total 1
-rw-r--r-- 1 demo.user 197121 94 Oct 21 17:46 main.js

软件包.json:

{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "build": "webpack --config=webpack.prod.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.19.3",
    "@babel/preset-env": "^7.19.4",
    "babel-loader": "^8.2.5",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0"
  }
}

网络包产品js:

const path = require("path");

module.exports = {
  entry: {
    main: "./src/main.js"
  },
  mode: "production",
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "./dist"),
    environment: {
      arrowFunction: false  // prevent top level arrow IIFE on Webpack 5
    },
    clean: true   // clean output dir before each build
  },
  module: {
    rules: [
      {
        test: /\.js$/,  // transpile JS for older browsers
        exclude: /node_modules/,  // don't mess with node_modules
        use: {
          loader: "babel-loader",
          options: {
            "presets": [
              [
                '@babel/preset-env', {
                  targets: {
                    "ie": "8"   // target for IE 8 ES3 for WebBrowser control
                  },
                  debug: true
                }
              ]
            ],  // let's us use latest JS features
            //"plugins": [ "@babel/plugin-transform-member-expression-literals" ]
          }
        }
      }
    ]
  }
}

输入代码:源代码/main.js
这里我使用Set对象的delete方法作为示例,请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

var d = new Set("a", "b", "c");
d["delete"]("a");
console.log("Set has a? "+d.has("a"));

调用webpack使用
npm run build

$ npm run build

> webpack-test@1.0.0 build
> webpack --config=webpack.prod.js

@babel/preset-env: `DEBUG` option

Using targets:
{
  "ie": "8"
}

Using modules transform: auto

Using plugins:
  proposal-class-static-block { ie }
  proposal-private-property-in-object { ie }
  proposal-class-properties { ie }
  proposal-private-methods { ie }
  proposal-numeric-separator { ie }
  proposal-logical-assignment-operators { ie }
  proposal-nullish-coalescing-operator { ie }
  proposal-optional-chaining { ie }
  proposal-json-strings { ie }
  proposal-optional-catch-binding { ie }
  transform-parameters { ie }
  proposal-async-generator-functions { ie }
  proposal-object-rest-spread { ie }
  transform-dotall-regex { ie }
  proposal-unicode-property-regex { ie }
  transform-named-capturing-groups-regex { ie }
  transform-async-to-generator { ie }
  transform-exponentiation-operator { ie }
  transform-template-literals { ie }
  transform-literals { ie }
  transform-function-name { ie }
  transform-arrow-functions { ie }
  transform-block-scoped-functions { ie < 11 }
  transform-classes { ie }
  transform-object-super { ie }
  transform-shorthand-properties { ie }
  transform-duplicate-keys { ie }
  transform-computed-properties { ie }
  transform-for-of { ie }
  transform-sticky-regex { ie }
  transform-unicode-escapes { ie }
  transform-unicode-regex { ie }
  transform-spread { ie }
  transform-destructuring { ie }
  transform-block-scoping { ie }
  transform-typeof-symbol { ie }
  transform-new-target { ie }
  transform-regenerator { ie }
  transform-member-expression-literals { ie < 9 }
  transform-property-literals { ie < 9 }
  transform-reserved-words { ie < 9 }
  proposal-export-namespace-from { ie }
  syntax-dynamic-import
  syntax-top-level-await

Using polyfills: No polyfills were added, since the `useBuiltIns` option was not set.
asset main.js 94 bytes [compared for emit] [minimized] (name: main)
./src/main.js 90 bytes [built] [code generated]
webpack 5.74.0 compiled successfully in 1940 ms

webpack / babel输出:分发/主.js:

!function(){var a=new Set("a","b","c");a.delete("a"),console.log("Set has a? "+a.has("a"))}();

请注意,a.delete()调用对IE8无效。它将导致上述“Expected identifier”(预期标识符)错误消息。

预期的输出预期的输出与输入相同,即对delete方法的调用应读取a["delete"]()

我试着用他们的REPL页面单独检查babel,那里的代码是正确的:https://babel.dev/repl#?browsers=ie%208&build=&builtIns=false&corejs=false&spec=false&loose=true&code_lz=G4QwTgBAJhC8EDsCmB3CBlJAXAFAIhDwBoI8AjY0gYzwEoBuAKCgDookAbbJfQhoA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env%2Cstage-2&prettier=false&targets=&version=7.19.6&externalPlugins=&assumptions=%7B%7D
因此,我认为配置文件不正确,或者webpack/babel-loader配置没有正确传递到babel。我将感谢任何解决这个问题的帮助。

dgiusagp

dgiusagp1#

所以我找到了解决方案。显然这不是一个巴别塔的问题,而是之后发生的缩小问题。Terser(小型化器)会把代码弄得一团糟。我可以找到正确的选项来防止terser用点符号替换属性访问,文档如下:https://github.com/terser/terser#compress-options
首先,我们需要在webpack.prod.js中包含terser插件:

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

然后在“module”配置之后附加一个更短的配置:

optimization: {
  minimize: true,
  minimizer: [new TerserPlugin({
    terserOptions: {
        compress: { properties: false },
        mangle: false,
    },
  })],
}

完整的webpack. prod. js:

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

module.exports = {
  entry: {
    main: "./src/main.js"
  },
  mode: "production",
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "./dist"),
    environment: {
      arrowFunction: false  // prevent top level arrow IIFE on Webpack 5
    },
    clean: true   // clean output dir before each build
  },
  module: {
    rules: [
      {
        test: /\.js$/,  // transpile JS for older browsers
        exclude: /node_modules/,  // don't mess with node_modules
        use: {
          loader: "babel-loader",
          options: {
            "presets": [
              [
                '@babel/preset-env', {
                  targets: {
                    "ie": "8"   // target for IE 8 ES3 for WebBrowser control
                  },
                  debug: true
                }
              ]
            ],  // let's us use latest JS features
            //"plugins": [ "@babel/plugin-transform-member-expression-literals" ]
          }
        }
      }
    ]
  },
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin({
      terserOptions: {
        compress: { properties: false }, // important: don't rewrite property access using the dot notation, e.g. foo["bar"] → foo.bar
        mangle: false,
      },
    })],
  }
}

然后,输出文件dist/main.js如预期:

$ cat dist/main.js
!function(){var d=new Set("a","b","c");d["delete"]("a"),console.log("Set has a? "+d.has("a"))}();

相关问题