I am an AMQP/RabbitMQ newbie, and relative Node.js newbie. Can I use the amqplib NPM library client-side?
I'd like to be able to push messages direct to RabbitMQ from my Angular app. I have used Browserify to modularise a lot of my client-side code. I am now starting to experiment with RabbitMQ and would like to push messages direct from the browser to cloud-based queues over the amqp protocol.
I have installed amqplib via NPM and written/pasted the following module:
var amqp = require('amqplib/callback_api');
var push = function(){
console.log('This is the CORE queue.pusher push function being triggered');
var connString = 'amqp://username:pwd@blabla.rmq.cloudamqp.com/username';
amqp.connect(connString, function(err, conn) {
if (err){
console.log("core queue.pusher push error %s", err);
}else {
conn.createChannel(function (err, ch) {
var q = 'FatController';
var msg = 'Hello World!';
ch.assertQueue(q, {durable: false});
// Note: on Node 6 Buffer.from(msg) should be used
ch.sendToQueue(q, new Buffer(msg));
console.log(" [x] Sent %s", msg);
});
setTimeout(function () {
conn.close();
process.exit(0)
}, 500);
}
});
};
module.exports = {push:push};
When I try running this I get the following error:
bundle.js:32074 TypeError: QS.unescape is not a function
at openFrames (bundle.js:9551)
at connect (bundle.js:9629)
at Object.connect (bundle.js:7959)
at Object.push (bundle.js:7652)
at controller.pushQueueEntry (bundle.js:7805)
at fn (eval at compile (bundle.js:32907), <anonymous>:4:184)
at callback (bundle.js:44543)
at Scope.$eval (bundle.js:35710)
at Scope.$apply (bundle.js:35810)
at HTMLInputElement.<anonymous> (bundle.js:44548)
at defaultHandlerWrapper (bundle.js:21283)
at HTMLInputElement.eventHandler (bundle.js:21271)
Am I barking up the wrong tree here? Will amqplib only run in a 'proper' node environment?
As a secondary question, what is the best way to determine whether a particular NPM package will run in the browser environment? It seems to me that some NPM packages will run in the browser, and some won't - what is the best way to be confident about this?
Will amqplib only run in a 'proper' node environment?
Yes, I'm afraid so.
As a secondary question, what is the best way to determine whether a particular NPM package will run in the browser environment? It seems to me that some NPM packages will run in the browser, and some won't - what is the best way to be confident about this?
It's not always clear if a package can run in a browser or not, so you have to apply some heuristics:
fs
, net
, cluster
, http
, https
, tls
, dns
, os
, tty
or dgram
? Most likely server-side.Packages that can be used client-side typically say so in their documentation, so if it isn't specifically mentioned, there's a good chance that it's only server-side.
I hadn't used Browserify in a while, so I had to check, but it looks like it doesn't warn you if the code you pass it depends on server-side modules. It will create a bundle that at some point will just fail with an error, much like what you're running in to.
Webpack, another commonly used bundler, has a concept of deployment targets. By default, it will target browsers, and when you try to bundle a project that depends on server-side modules like the ones I mentioned above, you will get an error:
$ webpack -p bundle.js
Hash: 767ace79fc17abef93e8
Version: webpack 2.6.1
Time: 3983ms
Asset Size Chunks Chunk Names
bundle.js 308 kB 0 [emitted] [big] main
[0] <SNIP>
ERROR in ./~/amqplib/lib/connect.js
Module not found: Error: Can't resolve 'net' in '/private/tmp/node_modules/amqplib/lib'
@ ./~/amqplib/lib/connect.js 152:11-25
@ ./~/amqplib/channel_api.js
@ ./test.js
ERROR in ./~/amqplib/lib/connect.js
Module not found: Error: Can't resolve 'tls' in '/private/tmp/node_modules/amqplib/lib'
@ ./~/amqplib/lib/connect.js 155:11-25
@ ./~/amqplib/channel_api.js
@ ./test.js
As you can see, my test file uses amqplib
, which depends on net
and tls
, which are both not available in the browser environment. So if you're unsure about whether or not a package can be used in a browser, Webpack provides you with a safety net.