Can I use amqplib in the browser?

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:[email protected]/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?

Answer

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:

  • Does a package require setting up “plain” TCP connections (meaning connections that aren’t used for the usual web-based protocols like HTTP(S) or WebSockets)? If so, it’s probably a server-side package.
  • Does a package require reading arbitrary files? If so, again, probably server-side.
  • Does a package provide, or depend on, native Node.js addons? If so, it’s a server-side package.
  • As an extension of these: does it use 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.

Leave a Reply

Your email address will not be published. Required fields are marked *