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.js
的exclude
规则如下:
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 目录