如何解决Webpack/Babel解析空catch {}块的问题?
catch {}块的ssh2包 问题描述
使用Webpack 2和Babel 7构建项目时,引入ssh2 0.8.9及以上版本(尤其是1.0.0+),因包内代码使用了空catch {}语法,导致Webpack解析失败,抛出语法错误。
报错信息
[0] Module parse failed: C:\Users\PROJECT\node_modules\ssh2\lib\server.js Unexpected token (490:16)
[0] You may need an appropriate loader to handle this file type.
[0] | try {
[0] | socket.end();
[0] | } catch {} << it's complaining about this section.
[0] | },
相关配置文件
.babelrc
{ "presets": ["@babel/preset-env", "@babel/preset-react"], "plugins": ["add-module-exports"], "env": { "production": { "presets": ["react-optimize"], "plugins": [ "babel-plugin-transform-remove-console", "babel-plugin-transform-remove-debugger", "babel-plugin-dev-expression", "add-module-exports" ] }, "development": { "plugins": ["transform-exponentiation-operator"] }, "test": { "plugins": [ [ "webpack-loaders", { "config": "webpack.config.node.js", "verbose": false } ], [ "babel-plugin-module-alias", { "src": "test/electron/mockElectron", "expose": "electron" } ] ] } } }
Webpack开发配置(webpack.config.dev.js)
/* eslint max-len: 0 */ import webpack from 'webpack'; import baseConfig from './webpack.config.base'; const config = { ...baseConfig, devtool: 'cheap-module-eval-source-map', entry: [ 'webpack-hot-middleware/client?path=http://localhost:3000/__webpack_hmr', '@babel/polyfill', './app/index' ], output: { ...baseConfig.output, publicPath: 'http://localhost:3000/dist/' }, module: { ...baseConfig.module, loaders: [ ...baseConfig.module.loaders, { test: /\.global\.css$/, loaders: [ 'style-loader', 'css-loader?sourceMap' ] }, { test: /^((?!\.global).)*\.css$/, loaders: [ 'style-loader', 'css-loader?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]' ] } ] }, plugins: [ ...baseConfig.plugins, new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin(), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('development') }) ], target: 'electron-renderer' }; export default config;
Webpack基础配置(webpack.config.base.js)
import path from 'path'; import WebpackNotifierPlugin from 'webpack-notifier'; export default { module: { loaders: [{ test: /\.jsx?$/, loaders: ['babel-loader'], exclude: /node_modules/ }, { test: /\.json$/, loader: 'json-loader' }, { test: /\.cjs?$/, loaders: ['babel-loader'] } ] }, output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js', libraryTarget: 'commonjs2' }, resolve: { extensions: ['.js', '.jsx', '.json', '.cjs'], mainFields: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main'] }, plugins: [ new WebpackNotifierPlugin({excludeWarnings: true}) ], externals: [ ] };
依赖版本
{ "@babel/core": "^7.9.0", "@babel/plugin-transform-exponentiation-operator": "7.18.6", "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", "@babel/polyfill": "^7.12.1", "@babel/preset-env": "^7.19.0", "@babel/preset-react": "^7.18.6", "@babel/preset-stage-0": "^7.8.3", "@babel/register": "^7.18.9", "@babel/parser": "^7.19.0", "@babel/eslint-parser": "^7.18.9", "@babel/eslint-plugin": "7.18.10", "babel-loader": "8.0.0", "babel-plugin-add-module-exports": "1.0.4", "babel-plugin-dev-expression": "0.2.1", "babel-plugin-module-alias": "1.6.0", "babel-plugin-transform-react-inline-elements": "7.0.0-beta.3", "babel-plugin-transform-remove-console": "^6.9.4", "babel-plugin-transform-remove-debugger": "^6.9.4", "babel-plugin-webpack-loaders": "0.9.0", "babel-preset-react-hmre": "^1.1.1", "babel-preset-react-optimize": "1.0.*", "babel-core": "7.0.0-bridge.0", "babel-eslint": "~10.1.0", "webpack": "2.7.0", "webpack-dev-middleware": "2.0.6", "webpack-hot-middleware": "2.25.2" }
解决办法
空catch {}是ES2019的可选catch绑定语法,Webpack 2的默认解析器不支持该语法,且当前Babel未启用对应插件,同时默认排除了node_modules下的包转译,导致ssh2的未转译代码无法被解析。
方案1:启用Babel可选catch绑定插件并让ssh2经过转译
更新.babelrc配置
已安装@babel/plugin-proposal-optional-catch-binding,需在各个环境的plugins数组中添加该插件:{ "presets": ["@babel/preset-env", "@babel/preset-react"], "plugins": [ "add-module-exports", "@babel/plugin-proposal-optional-catch-binding" ], "env": { "production": { "presets": ["react-optimize"], "plugins": [ "babel-plugin-transform-remove-console", "babel-plugin-transform-remove-debugger", "babel-plugin-dev-expression", "add-module-exports", "@babel/plugin-proposal-optional-catch-binding" ] }, "development": { "plugins": [ "transform-exponentiation-operator", "@babel/plugin-proposal-optional-catch-binding" ] }, "test": { "plugins": [ ["webpack-loaders", {"config": "webpack.config.node.js", "verbose": false}], ["babel-plugin-module-alias", {"src": "test/electron/mockElectron", "expose": "electron"}], "@babel/plugin-proposal-optional-catch-binding" ] } } }修改Webpack基础配置
默认Webpack排除了node_modules的转译,需修改规则让ssh2包经过Babel处理:
修改webpack.config.base.js中的js加载规则,将exclude: /node_modules/替换为:exclude: /node_modules(?!\/ssh2)/或者使用
include明确指定需要转译的目录:include: [ path.join(__dirname, 'app'), path.join(__dirname, 'node_modules/ssh2') ]同时,为
.cjs规则也添加相同的include或修改exclude,确保ssh2的cjs文件也被转译。
方案2:降级ssh2版本
如果暂时不想修改配置,可以将ssh2降级到0.8.9版本,该版本未使用可选catch绑定语法,可直接被当前环境解析。
内容的提问来源于stack exchange,提问作者Getek99

