My url is ws://127.0.0.1:8083/mqtt. No problem in browser, but not in electron, and I don't see any error messages.

When I open the Developer Tool Console, I use it like this and can also connect
const mqtt = require('mqtt')
mqtt.connect('ws://127.0.0.1:8083/mqtt', opts)

If you can help me, I will be very grateful!
everything is perfectly normal in the browser but Electron.
I can connect to WebSocket broker when I downgrade to v1.14.1 but can not subscribe to any topic and don't see any error messages. if I change to v2 or v3 also cannot connect to WebSocket broker.
Using:
I think I stumbled on this too, I believe it's the way the package is designed, it utilizes different modules for browser/node contexts: https://github.com/mqttjs/MQTT.js/blob/66e295ada333eb47e0881c22c2ef6e65e852a72c/package.json#L60-L65
While this entry alone seems to pose no threat, the underlying library rewrites a whole module: https://github.com/maxogden/websocket-stream/blob/feeb372ff530621d6df85cb85d4bee03b879c54d/package.json#L46
And the default export mode is actually for node: https://github.com/mqttjs/MQTT.js/blob/66e295ada333eb47e0881c22c2ef6e65e852a72c/package.json#L22
Try setting a event listener for "close", because in my case, the connection got always interrupted and reconnected and no errors got reported, but the "close" handler fired.
As for the fix, I believe you are using require('mqtt') from Electron's Renderer context, same as I did. This library does not want to work that way and has various unexpected issues, I don't know exactly why.
I managed to fix the issue for now by specifically importing from mqtt/dist/mqtt.js, which is a pre-built browser-friendly module.
Some research inputs
browser package.json field, is an instruction for bundlers/transpilers, not standard JS resolution algorithms: https://github.com/defunctzombie/package-browser-field-specbrowser resolution in Renderer context.browser part of the package, one should use a bundler/transpiler that supports it.electron-renderer target, but then there might be another catch. electron-renderer target, I think, again tampers with resolution algorithms... knowing that Electron Renderer itself isn't a strict browser environment, they skip the browser field for resolution.electron-renderer uses NodeTargetPlugin for CommonJS modules (which MQTT.js is), will ignore the pacakge.json's browser rule.websocket-stream library causing issues.browser field: https://parceljs.org/module_resolution.html#package.json-%60browser%60-fieldwebsocket-stream library, currently, uses browser field only for transpilation purposes../mqtt.js to ./lib/connect/index.js doesn't help a bit when the package is published (it should point to compiled target ./dist/mqtt.js) because Parcel, seeing that the target module is a ES5 module, probably does not even try to transpile anything and therefore skips out of all the browser resolution steps and enters node mode of this package.The fix
I think the involved packages should use the browser field properly, to point to bundled modules for usage in browser.
And that involves reworking the bundling process, probably utilizing actual webpack/browserify configs, instead of relying on browser field.
@YoDaMa I have never published packages to npm, but if you help me on that part (with a pre-release from a PR), I could open up the PR with an attempt to fix the issue.
@joltmode I think you are right. I solved this problem temporarily with this method.
webpack.config.js
pluginOptions: {
electronBuilder: {
// Prevent bundling of certain imported packages and instead retrieve these external dependencies at runtime.
// In order to connect to websocket.
externals: ['mqtt'],
}
}
connect.ts
const isWS: boolean = this.connectUrl.startsWith('ws') || this.connectUrl.startsWith('wss')
let mqtt = null
if (isWS) {
mqtt = require('mqtt/dist/mqtt')
} else {
mqtt = require('mqtt')
}
For anyone else that runs into this issue. I ended up working around this with the help of @tomsseisums comments, but instead of importing mqtt/dist/mqtt.js directly at the call site (i.e. import mqtt from 'mqtt/dist/mqtt.js';) I created a webpack alias as part of my electron renderer build:
resolve: {
alias: {
mqtt: resolve(__dirname, '../../node_modules/mqtt/dist/mqtt.js'),
},
},
By using an alias the same code can function in both node as electron-renderer.
Most helpful comment
I think I stumbled on this too, I believe it's the way the package is designed, it utilizes different modules for browser/node contexts: https://github.com/mqttjs/MQTT.js/blob/66e295ada333eb47e0881c22c2ef6e65e852a72c/package.json#L60-L65
While this entry alone seems to pose no threat, the underlying library rewrites a whole module: https://github.com/maxogden/websocket-stream/blob/feeb372ff530621d6df85cb85d4bee03b879c54d/package.json#L46
And the default export mode is actually for node: https://github.com/mqttjs/MQTT.js/blob/66e295ada333eb47e0881c22c2ef6e65e852a72c/package.json#L22
Try setting a event listener for "close", because in my case, the connection got always interrupted and reconnected and no errors got reported, but the "close" handler fired.
As for the fix, I believe you are using
require('mqtt')from Electron's Renderer context, same as I did. This library does not want to work that way and has various unexpected issues, I don't know exactly why.I managed to fix the issue for now by specifically importing from
mqtt/dist/mqtt.js, which is a pre-built browser-friendly module.Some research inputs
browserpackage.json field, is an instruction for bundlers/transpilers, not standard JS resolution algorithms: https://github.com/defunctzombie/package-browser-field-specbrowserresolution in Renderer context.browserpart of the package, one should use a bundler/transpiler that supports it.electron-renderertarget, but then there might be another catch.electron-renderertarget, I think, again tampers with resolution algorithms... knowing that Electron Renderer itself isn't a strict browser environment, they skip thebrowserfield for resolution.electron-rendereruses NodeTargetPlugin for CommonJS modules (whichMQTT.jsis), will ignore the pacakge.json'sbrowserrule.websocket-streamlibrary causing issues.browserfield: https://parceljs.org/module_resolution.html#package.json-%60browser%60-fieldwebsocket-streamlibrary, currently, usesbrowserfield only for transpilation purposes../mqtt.jsto./lib/connect/index.jsdoesn't help a bit when the package is published (it should point to compiled target./dist/mqtt.js) because Parcel, seeing that the target module is a ES5 module, probably does not even try to transpile anything and therefore skips out of all thebrowserresolution steps and enters node mode of this package.The fix
I think the involved packages should use the
browserfield properly, to point to bundled modules for usage in browser.And that involves reworking the bundling process, probably utilizing actual webpack/browserify configs, instead of relying on
browserfield.@YoDaMa I have never published packages to npm, but if you help me on that part (with a pre-release from a PR), I could open up the PR with an attempt to fix the issue.