Babel:无法让“@babel/plugin-transform-destructuring”插件工作

Posted

技术标签:

【中文标题】Babel:无法让“@babel/plugin-transform-destructuring”插件工作【英文标题】:Babel: can't get "@babel/plugin-transform-destructuring" plugin to work 【发布时间】:2019-12-18 01:00:22 【问题描述】:

PS:这是我第一次放弃在这里撰写我的第一个问题。如果有人可以提供帮助,将不胜感激。谢谢!

我正在尝试在相对较旧的 iPad 上的 ios 10 Safari 中加载我的 ReactJS 网络应用程序(我使用 webpack 和 babel-loader,并使用 webpack-dev-server 提供服务)。

我收到以下语法错误:

SyntaxError: Unexpected token '...'. Expected a property name.

(到目前为止,该页面在我尝试过的所有设备/浏览器上都能正常加载。)

错误是由这行转译代码引起的:

eval("\nconst publicIp = __webpack_require__(/*! public-ip */ \"./node_modules/public-ip/browser.js\");\n\nconst isOnline = async options => \n\toptions = \n\t\ttimeout: 5000,\n\t\tversion: 'v4',\n\t\t...options\n\t;\n\n\ttry \n\t\tawait publicIp[options.version](options);\n\t\treturn true;\n\t catch (_) \n\t\treturn false;\n\t\n;\n\nmodule.exports = isOnline;\n// TODO: Remove this for the next major release\nmodule.exports.default = isOnline;\n\n\n//# sourceURL=webpack:///./node_modules/is-online/browser.js?");

在源代码https://github.com/sindresorhus/is-online/blob/master/browser.js 中我们可以观察到的地方:

const isOnline = async options => 
    options = 
        timeout: 5000,
        version: 'v4',
        ...options
    ;

    // ...
;

在我看来,不支持使用 ... 扩展运算符进行对象解构。代码来自我正在使用的名为“is-online”的 npm 模块。

我尝试将“@babel/plugin-transform-destructuring”插件添加到.babelrc,看看它是否可以解决这个问题。一切编译,但这部分代码是相同的,所以它仍然产生同样的错误。

我发现这个 Twitter 对话描述了与 Safari 相同的问题,但他设法解决了这个问题,因为他“还需要为其激活转换插件:transform-object-rest-spread”:

https://twitter.com/beberlei/status/984083670012256258

所以我试了一下,还是不行。

然后我在.babelrc 加强了我的插件游戏,在网上搜索了类似的案例,尝试了不同的配置,使用npx babel-upgrade 更新babel,删除并重新安装node_modules 并将插件直接放入module.rules[0].options.plugins 我给了继续努力:

// .babelrc


    "presets": [
        "@babel/preset-env",
        "@babel/preset-react"
    ],
    "plugins": [
        "@babel/plugin-transform-spread",
        "@babel/plugin-transform-destructuring",
        "@babel/plugin-transform-parameters",
        "@babel/plugin-proposal-object-rest-spread",
    ]

...但它仍然给出错误。它还尝试将“@babel/plugin-transform-runtime”放在那里:相同。

我现在的 webpack 配置:

// webpack.dev.js

const path = require("path");
const webpack = require("webpack");

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

module.exports = [

    // App

    

        mode: 'development',

        entry: 
            app: "./src/index.js"
        ,

        module: 
            rules: [
                
                    test: /\.(js|jsx)$/,
                    exclude: /(node_modules|bower_components)/,
                    loader: "babel-loader",
                    options: 
                        presets: ["@babel/env"],
                    
                ,
                
                    test: /\.css$/,
                    use: ["style-loader", "css-loader", "postcss-loader"]
                ,
                
                    test: /\.(png|svg|jpg|gif)$/,
                    use: [
                        'file-loader'
                    ]
                
            ]
        ,

        resolve:  extensions: ["*", ".js", ".jsx"] ,

        output: 
            filename: "app-v0.9.6.js",
            path: path.resolve(__dirname, "public/dist/"),
            publicPath: "/dist/"
        ,

        plugins: [new webpack.HotModuleReplacementPlugin()],

        devServer: 
            host: '0.0.0.0',
            disableHostCheck: true,
            port: 80,
            contentBase: path.join(__dirname, "public/"),
            publicPath: "http://localhost:3000/dist/",
            hotOnly: true
        ,

// Fixes Safari 10-11 bugs
// Has nothing to do with this question: already tried to comment this out
        optimization: 
            minimizer: [new TerserPlugin(
                terserOptions: 
                    safari10: true,
                ,
            )],
        ,
    ,

    // Library

    

        mode: 'development',

       // ... 
       // another output that's exposed as a global variable (library)

    
];

这里是开发依赖:

// package.json

...

  "devDependencies": 
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
    "@babel/plugin-transform-destructuring": "^7.0.0",
    "@babel/plugin-transform-parameters": "^7.0.0",
    "@babel/plugin-transform-runtime": "^7.5.5",
    "@babel/plugin-transform-spread": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.6",
    "babel-preset-env": "^1.7.0",
    "css-loader": "^3.2.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "postcss-loader": "^3.0.0",
    "style-loader": "^0.23.1",
    "webpack": "^4.39.1",
    "webpack-cli": "^3.3.6",
    "webpack-dev-server": "^3.8.0",
    "webpack-merge": "^4.2.1"
  ,

...

如果有人知道如何正确配置它,我将不胜感激。

【问题讨论】:

【参考方案1】:

正如您所理解的,从您导入的模块中使用“ES2018 对象文字中的扩展语法”(又名省略号)会泄漏到您的转译包中,从而使最可怜的浏览器感到不安。发生这种情况是因为:

Webpack 设置为忽略您的 node_modules,因此 is-online 不会被转译。

这里有一个实用的解决方案——修改webpack.config.jsexclude 规则如下:

exclude: /(node_modules\/(?!is-online)|bower_components)/,

阿卡。 “排除 bower_components,以及除了 is-online 之外的所有 node_modules”

以防万一 -- 排除更多模块,写:

exclude: /(node_modules\/(?!is-online|another-es6-module|yet-another-one)|bower_components)/,

可能还有更漂亮的表达方式;如果你是个美学家,试试你的运气here。

完成后,检查输出文件中的字符串“...”。希望它消失了!

如果您喜欢,您可以在每次构建后自动检查“...”的输出,以确保不会错过任何模块。但话又说回来,它会触发包含省略号的合法字符串文字......

呸!我差点以为other forces were at play...


由于有问题的错误导致的旧响应:

你的 fat-arrow 函数返回一个没有括在括号中的对象字面量。

Mozilla says:

返回对象字面量

请记住,使用简洁的正文返回对象字面量 语法 params => object:literal 将无法按预期工作。

var func = () =>  foo: 1 ;
// Calling func() returns undefined!

var func = () =>  foo: function()  ;
// SyntaxError: function statement requires a name

这是因为大括号 () 内的代码被解析为 语句(即foo 被视为标签,而不是对象中的键 字面意思)。

您必须将对象字面量括在括号中:

var func = () => ( foo: 1 );

【讨论】:

嗨雨果!感谢您回答您的解释。很抱歉,我注意到我在显示转译代码的“未包装”版本的部分犯了一个错误,如果可以的话,请查看更新的部分。你认为这仍然是同样的问题吗?编辑:代码不是我的,我通常从不使用这种复杂的语法。有什么方法可以配置 Babel 来应对这个问题? 你说“我们可以在哪里观察options = \n\t\ttimeout: 5000,\n\t\tversion: 'v4',\n\t\t...options\n\t”。我看到的是写成(blahblahblah)const isOnline = async options => \n\t\ttimeout: 5000,\n\t\tversion: 'v4',\n\t\t...options\n\t(blahblahblah)。这是正确的吗? 我找到了来源:github.com/sindresorhus/is-online/blob/master/browser.js 是的,来源是正确的,但不是您的eval("...") 代码。你知道它是由什么产生的吗? 好的,我想我找到了问题,我更新了我的答案:)【参考方案2】:

修复了它,感谢@hugo。

原来的问题是模块本身没有被 babel-loader 处理。

正如@hugo 建议的那样(将“is-online”添加到排除列表中),我的排除变成了这样:

exclude: /(node_modules\/(?!is-online|public-ip)|bower_components)/

然后我开始收到另一个错误:

在寻找解决方案后,我想我还必须添加 import "regenerator-runtime/runtime”; 在我导入“is-online”模块之前在我的代码中,如下所示:https://***.com/a/56754212/11033276。

.babelrc(无插件)


    "presets": [
        "@babel/preset-env",
        "@babel/preset-react", 
    ],

我仍然不确定是否还必须将useBuiltIns: entry 添加到@babel/preset-env,因为它似乎已经以这种方式工作了。 我是 web 开发的新手,所以如果有人可以提出优化建议,那就太好了!

最后,我卸载了一堆我试图解决这个问题的依赖项。

package.json

// …
  "devDependencies": 
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/preset-env": "^7.5.5",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.6",
    "css-loader": "^3.2.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "postcss-loader": "^3.0.0",
    "style-loader": "^0.23.1",
    "webpack": "^4.39.1",
    "webpack-cli": "^3.3.6",
    "webpack-dev-server": "^3.8.0",
    "webpack-merge": "^4.2.1"
  ,
// …

我通过重新安装 node_modules 仔细检查了一切仍然有效。

webpack.dev.js

// ...
                
                    test: /\.(js|jsx)$/,
                    exclude: /(node_modules\/(?!is-online)\/(?!public-ip)|bower_components)/,
                    loader: "babel-loader",
                    options: 
                        presets: ["@babel/env"],
                    
                ,
// …

【讨论】:

很高兴你解决了它!我认为您的正则表达式 /(node_modules\/(?!is-online)\/(?!public-ip)|bower_components)/ (test 1) 是错误的,您的意思是 /(node_modules\/(?!(is-online|public-ip))|bower_components)/ (test 2)

以上是关于Babel:无法让“@babel/plugin-transform-destructuring”插件工作的主要内容,如果未能解决你的问题,请参考以下文章

无法使用为 vue cli 3 设置添加的 babel-plugin-transform-object-rest-spread 传播对象

在 Babel 7 中包含一些 node_modules 目录

让 Nextjs 忽略 babel.config.js

MERN 应用程序中的 Babel 配置

如何让 React 与 Grunt 和 Babel 一起工作?

TypeError:无法读取未定义的属性“babel”