Vue2项目安装Mqtt 4.3.7遇解析错误,降级后无限加载求助
问题
在Vue2项目中通过npm安装mqtt 4.3.7时,持续抛出以下错误:
error in ./node_modules/mqtt/lib/client.js Module parse failed: Unexpected token (118:38) You may need an appropriate loader to handle this file type. | if (alias) { | packet.topic = '' | packet.properties = { ...(packet.properties), topicAlias: alias } | debug('applyTopicAlias :: auto assign(use) topic: %s - alias: %d', topic, alias) | } else { @ ./node_modules/mqtt/lib/connect/index.js 3:19-39
已确认./node_modules/mqtt/lib/client.js中无不可打印Unicode字符,尝试降级到mqtt 2.18.9、4.2.2和4.3.0版本后,项目进入无限加载循环。推测是webpack配置问题,不清楚如何添加合适的loader或是否有其他解决办法。
项目配置文件
package.json
{ "name": "mobile-attendant", "version": "1.3.0", "scripts": { "dev": "webpack-dev-server --host localhost --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "build": "node build/build.js", "copy-fonts": "cpy node_modules/framework7-icons/fonts/*.* src/fonts && cpy node_modules/material-design-icons/iconfont/*.{eot,ttf,woff,woff2} src/fonts", "postinstall": "npm run copy-fonts" }, "files": [ "dist/**/*" ], "dependencies": { "axios": "0.18.0", "framework7": "2.3.1", "framework7-icons": "0.8.9", "framework7-vue": "2.3.0", "material-design-icons": "3.0.1", "mqtt": "^4.3.7", "simple-keyboard": "2.29.47", "vue": "2.5.21", "vue-i18n": "8.21.1", "vue-resource": "1.5.1", "webpack-war-plugin": "1.0.0-beta.3" }, "devDependencies": { "autoprefixer": "8.0.0", "babel-core": "6.26.3", "babel-helper-vue-jsx-merge-props": "2.0.3", "babel-loader": "7.1.5", "babel-plugin-syntax-jsx": "6.18.0", "babel-plugin-transform-runtime": "6.23.0", "babel-plugin-transform-vue-jsx": "3.7.0", "babel-preset-env": "1.7.0", "babel-preset-stage-2": "6.24.1", "chalk": "2.4.2", "copy-webpack-plugin": "4.6.0", "cpy-cli": "1.0.1", "css-loader": "0.28.11", "extract-text-webpack-plugin": "3.0.2", "file-loader": "1.1.11", "friendly-errors-webpack-plugin": "1.7.0", "html-webpack-plugin": "2.30.1", "moment": "2.24.0", "node-notifier": "5.3.0", "node-sass": "4.11.0", "optimize-css-assets-webpack-plugin": "3.2.0", "ora": "1.4.0", "portfinder": "1.0.20", "postcss-import": "11.1.0", "postcss-loader": "2.1.6", "postcss-url": "7.3.2", "rimraf": "2.6.3", "sass-loader": "7.1.0", "semver": "5.6.0", "shelljs": "0.7.8", "style-loader": "0.21.0", "uglifyjs-webpack-plugin": "1.3.0", "url-loader": "0.5.9", "vue-loader": "13.7.3", "vue-style-loader": "3.1.2", "vue-template-compiler": "2.5.21", "webpack": "3.12.0", "webpack-bundle-analyzer": "2.13.1", "webpack-dev-server": "2.11.3", "webpack-merge": "4.2.1" }, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" }, "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] }
webpack.config.dev.js
const webpack = require('webpack'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin') const path = require('path'); function resolvePath(dir) { return path.join(__dirname, '..', dir); } module.exports = { mode: 'development', entry: [ './src/app.js' ], output: { path: resolvePath('www'), filename: 'app.js', publicPath: '' }, resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolvePath('src'), } }, devServer: { hot: true, open: true, compress: true, contentBase: '/www/', watchOptions: { poll: true } }, module: { rules: [ { test: /\.js$/, use: 'babel-loader', include: [ resolvePath('src'), resolvePath('node_modules/framework7'), resolvePath('node_modules/framework7-vue'), resolvePath('node_modules/template7'), resolvePath('node_modules/dom7'), resolvePath('node_modules/ssr-window'), ], }, { test: /\.vue$/, use: 'vue-loader', }, { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', ], }, { test: /\.styl(us)?$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'stylus-loader', ], }, { test: /\.less$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader', ], }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: 'images/[name].[hash:7].[ext]' } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: 'media/[name].[hash:7].[ext]' } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: 'fonts/[name].[hash:7].[ext]' } } ] }, plugins: [ new webpack.DefinePlugin({ 'process.env': JSON.stringify('development'), }), new webpack.HotModuleReplacementPlugin(), new webpack.NamedModulesPlugin(), new VueLoaderPlugin(), new HtmlWebpackPlugin({ filename: './index.html', template: './src/index.html', inject: true, }), new MiniCssExtractPlugin({ filename: 'app.css' }), new CopyWebpackPlugin([{ from: resolvePath('static'), to: resolvePath('www/static'), }]), ] }
解决方案
错误核心是mqtt 4.x使用了ES6扩展运算符(...),但当前webpack配置未让babel-loader处理mqtt模块,导致语法无法解析。以下是三种解决方法:
方法1:修改webpack配置,让babel转译mqtt
找到webpack配置中处理.js文件的规则,将node_modules/mqtt添加到include数组:
{ test: /\.js$/, use: 'babel-loader', include: [ resolvePath('src'), resolvePath('node_modules/framework7'), resolvePath('node_modules/framework7-vue'), resolvePath('node_modules/template7'), resolvePath('node_modules/dom7'), resolvePath('node_modules/ssr-window'), resolvePath('node_modules/mqtt'), // 新增该行 resolvePath('node_modules/mqtt-packet'), // 可选:若mqtt依赖的mqtt-packet也有语法问题,同样添加 ], },
修改后重新运行npm run dev即可。
方法2:直接使用mqtt预编译版本
mqtt提供了转译好的浏览器版本,无需修改webpack:
- 卸载当前mqtt:
npm uninstall mqtt - 重新安装同版本:
npm install mqtt@4.3.7 - 在项目中引入预编译文件:
import mqtt from 'mqtt/dist/mqtt.min.js'
方法3:升级babel和webpack(可选)
若项目允许,可升级babel到7.x、webpack到4.x及以上,新版本默认支持更多ES6语法,兼容性更好,但需调整相关配置,适合有重构空间的项目。
内容的提问来源于stack exchange,提问作者Alfonso R.
相关产品推荐
相关产品推荐

