导入带有可选链接的模块时出错

Error while importing a module with optional chaining

项目设置:

我们使用 vue-cli 创建了项目并将依赖项添加到库中。

然后我们导入了一个使用可选链接的项目 (Vue Currency Input v2.0.0)。但是我们在执行 serve 脚本时出现以下错误:

error  in ./node_modules/vue-currency-input/dist/index.esm.js

Module parse failed: Unexpected token (265:36)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|     getMinValue() {
|         let min = this.toFloat(-Number.MAX_SAFE_INTEGER);
>         if (this.options.valueRange?.min !== undefined) {
|             min = Math.max(this.options.valueRange?.min, this.toFloat(-Number.MAX_SAFE_INTEGER));
|         }

我了解到 Webpack 4 默认不支持可选链接。因此,我们为可选链添加了 Babel 插件。这是我们的 babel.config.js 文件:

module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"],
  plugins: ["@babel/plugin-proposal-optional-chaining"],
};

(但是,如果我是正确的,这个插件现在在 babel-preset 中默认启用。所以这个修改可能没用 ^^)

我不明白的一件事是我们可以在 .vue 文件中使用可选链接。

我创建了一个包含所有文件的沙箱:SandBox

我该如何解决这个错误?

我遇到了类似的问题。我正在使用 nuxt,但我的 .babelrc 文件如下所示,它对我有用。

{
  "presets": [
    ["@babel/preset-env"]
  ],
  "plugins":[
    ["@babel/plugin-transform-runtime",
        {
          "regenerator": true
        }
    ]
  ],
  "env": {
    "test": {
      "plugins": [
        ["transform-regenerator", {
            "regenerator": true
        }],
        "@babel/plugin-transform-runtime"
        ],
      "presets": [
        ["@babel/preset-env", {
            "useBuiltIns": false
        }]
      ]
    }
  }
}

我设法通过将这些行添加到 package.json:

来修复解决方案
...
"scripts": {
   "preinstall": "npx npm-force-resolutions",
   ...
},
"resolutions": {
  "acorn": "8.0.1"
},
...

我使用 @babel/plugin-proposal-optional-chaining 解决了这个问题,但对我来说,让 Webpack 使用 Babel 插件的唯一方法是通过 [=25] 中的 Webpack 选项推送 babel-loader 配置=]vue.config.js。这是一个最小的 vue.config.js:

const path = require('path');
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('supportChaining')
      .test(/\.js$/)
        .include
          .add(path.resolve('node_modules/PROBLEM_MODULE'))
          .end()
      .use('babel-loader')
        .loader('babel-loader')
        .tap(options => ({ ...options, 
          plugins : ['@babel/plugin-proposal-optional-chaining']
        }))
        .end()
    }
};

令人惊讶的是我 不需要 使用 NPM 安装 @babel/plugin-proposal-optional-chaining。我用 @vue/cli 4.5.13 搭建的应用程序进行了 go/no-go 测试,在我的例子中没有打字稿。我导入了一直让我伤心的 NPM 模块 (@vime/vue-next 5.0.31 BTW),运行 serve 脚本并在包含可选的行上得到 Unexpected token 错误链接。然后我将上面的 vue.config.js 插入项目根目录并再次 运行 serve 脚本,这次没有错误。

我的观点是,这个问题似乎可以在不严重污染开发环境的情况下解决。

Vue 论坛否认这个问题,声称 Vue 3 支持可选链。然而,显然不是在节点模块中。 atflick 在 2021 年 2 月 26 日在 this thread 中发表的 post 帮助很大。

没有打字稿的 Vue 2 也有同样的问题。

要解决此问题,您需要强制 babel 预设包含可选的链接规则:

presets: [
    [
      '@vue/cli-plugin-babel/preset',
      {
        include: ['@babel/plugin-proposal-optional-chaining'],
      },
    ],
  ],

也可以通过在 browserslist config 中设置旧的浏览器目标来实现。

最重要的是,您需要将失败的模块添加到 vue.config.js 中的 transpileDependencies:

module.exports = {
  ...
  transpileDependencies: ['vue-currency-input],
}

这是必需的,因为默认情况下 babel 会从转译中排除所有 node_modules(在 vue cli docs 中提到),因此不会应用配置的插件。