Can I use amqplib in the browser? - angularjs

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:
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.

Related

when I just import different livery, I have seeing same errors (React)

I tried webdriverio, puppeteer, playwright, bowser
and I could see same results with problems using React
I just did
$ yarn add webdriverio (or other)
and next
import { remote } from 'webdriverio';or const playwright = require('playwright');
I did only that...
then I did $ yarn start
next is same or close
I saw this long err log..
it is same that log text means
Module not found: Error: Can't resolve 'os'
all log are 'can't resolve 'something'. (something : os, fs, http, https, tty .....)
I tried webpack config for fallback. the log recommended
but however I added new fallback, err still there
I also tried config's browser option. it false too
first, I thought it just Puppeteer problem(because I used that first)
so I tried alternative things and this is result all same
my node version 16.19.0 (I have coworkers, I can't change the version)
why I meet this same problems?

Phoenix: Error when refer to exq_ui dependency via git

I use exq and exq_ui for background job processing and monitoring in my Phoenix application.
At first, I refer to exq_ui in mix.exs's deps like this:
{:exq_ui, "~> 0.11.0", only: [:dev, :qa, :stg, :prod]}
And it works fine.
But then I discover 2 bugs in the UI:
When I click on the tab Busy, it blows up on the server side, and shows nothing in the tab Busy in UI.
In the tab Scheduled, when a job is passed args as a list of map, it is showed as [Object object] in the column Args, instead of the real content of the args.
I fix those bugs here in this PR to the main official repo:
https://github.com/akira/exq_ui/pull/89/files
But I cannot expect it will be merged anytime soon, so I change my dependency in mix.exs like this:
{:exq_ui, "~> 0.11.0",
git: "https://github.com/chauhonglinh/exq_ui.git",
branch: "feature/fix_busy_tab_in_exq_ui",
only: [:dev, :qa, :stg, :prod]}
Now the trouble happens.
The mix deps.get, mix deps.compile and iex -S mix phx.server all run successfully.
But then when I browse to http://localhost:4040, the UI doesn't show up, and in the javascript console, there are errors:
Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:4040/assets/vendor.css".
exq_ui:20
Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:4040/assets/exqui.css".
vendor.js:1 Uncaught SyntaxError: Unexpected token <
exqui.js:1 Uncaught SyntaxError: Unexpected token <
Question: Why did this error not happen with ordinary deps config, but it happened with deps config referred to a git repo?
How can I fix it?
I think React and Angular also have similar errors in certain situations, but it seems that nobody has a good fix for them, just some anecdotes here and there.
I figured out what the problem was. But I don't see any good solution for it yet if my PR is not merged (short of copying the whole exq_ui package and create a new one)
Here is the problem.
Referring to package like this points to binary distribution on hex.pm, hence it has all the emberjs and js modules prepackaged and babelified correctly:
{:exq_ui, "~> 0.11.0", only: [:dev, :qa, :stg, :prod]}
However, the referring to package in github points to source from github, so it has only source:
{:exq_ui, "~> 0.11.0",
git: "https://github.com/chauhonglinh/exq_ui.git",
branch: "feature/fix_busy_tab_in_exq_ui",
only: [:dev, :qa, :stg, :prod]}
Solution for dev environment:
In order for it to work in dev environment, from within my Phoenix repo, I need to run the following commands:
cd deps/exq_ui/priv/ember
npm install
bower install
node_modules/ember-cli/bin/ember build --environment=production
Then the web UI at http://localhost:4040 will work properly.
Remaining Question: When I refer to exq_ui from a git repo, I still don't see how I can make a binary distributed version for exq_ui when I want to release my Phoenix app.

TypeError: fs.readFileSync is not a function

My project require to use filesystem module in ReactJS. The project was created with create-react-app. In one of the component js file, I need to load lines in a textfile from a directory.
var fs = require('fs');
var readline = require('readline');
var stream = fs.readFileSync( C:/data/localmap.txt" ).toString().split("\n");
.......
There isn't error in the terminal, but the browser shows error as shown below:
TypeError: fs.readFileSync is not a function
Different from the issue raised here, I have used require statement as the comments suggested. I have been looking around online for resources but seems like it is not a widely faced problem.
fs is a Node.js module. You cannot run Node.js directly in the browser.
Unless you are running your own Chromium instance with Node integration enabled, (such as Electron) you will not be able to use Node.js modules.

Running Travis-CI using MochaJS, Supertest w/ Babel, Browserify, and Gulp

I've followed some tutorials and web casts on code school, mainly those on Node, ES2015, Angular, and Express. I've started a little project of my own and I've implemented all of the above. I'm also trying to get automated builds and testing working using Travis-CI and Mocha/Supertests for test driven development. The problem though is if I run npm test I get this error from Mocha
1) Uncaught error outside test suite:
Uncaught Error: listen EADDRINUSE :::3000
at Object.exports._errnoException (util.js:870:11)
at exports._exceptionWithHostPort (util.js:893:20)
at Server._listen2 (net.js:1236:14)
at listen (net.js:1272:10)
at Server.listen (net.js:1368:5)
at EventEmitter.listen (node_modules/express/lib/application.js:617:24)
at Object.<anonymous> (server/app.js:34:5)
at require (internal/module.js:12:17)
at Object.<anonymous> (test.js:6:11)
at require (internal/module.js:12:17)
at Array.forEach (native)
at node.js:962:3
I just noticed that I was missing module.exports = app at the end of my main app.js that might have helped but the tests still fail.
Here is a link to the latest push on GitHub.
Here is the failing build on Travis-CI.
Changing my server/app.js to listen if using
if (!module.parent) {
app.listen(port, () => {
console.log("Listening on port " + port);
});
}
Resolved my issue regarding testing not working on my local machine. The reason behind doing this can be found here.
Also adding
services:
- mongodb
like #ocean said worked, which reasoning can be referenced here.
The error you're currently getting on Travis CI is because NPM is trying to start your app with node server/app.js (as specified in line 9 of your package.json), but your app requires MongoDB to be running (as specified on line 13 of your app.js).
NPM has to start your app before it can run the tests.
MongoDB is available as a service on Travis CI. Have a look at the Travis CI Database Setup docs and see how you go.
Ok then, well the error is that this Express app is trying to use a network port on your machine which is already being used by something else (maybe another Node / Express app, as they often use 3000).
Try changing the var port declaration near the bottom of server/app.js to be something other than 3000.

Requiring unknown module "crypto" in react-native environment

I'm writing a simple Twitter app using react-native. Using twit module to get twitter feeds and stream. Below is the code, it works fine node. However, when included into my react-native app, seeing error "Requiring unknown module "crypto"". Dependency seems to be myapp->twit->oauth->crypto (thats part of node v0.12.2). Any suggestions to get this working inside react-native environment?
var Twit = require('twit')
var T = new Twit({
consumer_key:''
, consumer_secret:''
, access_token:''
, access_token_secret:''
})
var filtered_tweets=[];
var error;
var isSuccess=false;
function getTweets(searchString){
T.get('search/tweets',{q:searchString, count:100}, getResponse);
}
function getResponse(err,data,response){
if(err) {
handleGetErr(err);
}
handleGetData(data.statuses);
}
function handleGetErr(err){
enter code here
error = err;
}
function handleGetData(data){
data.map(function(tweet){
var twit={
twit:tweet.id,
created_at:tweet.created_at,
text:tweet.text,
retweet_count:tweet.retweet_count,
favorite_count:tweet.favorite_count
};
filtered_tweets.push(twit);
});
console.log(filtered_tweets);
isSuccess=true;
}
getTweets("#sahaswaranamam");
module.exports = getTweets;
![attached][2]
The crypto module is a built-in Node module; React Native runs JS on JavaScriptCore (when on the device or simulator) and on Chrome itself (when using Chrome debugging), so modules that depend on built-in Node.js modules won't work. See the JavaScript Runtime section of the React Native docs for more info.
I'm not sure how hard it would be to integrate into a React Native app, but browser module bundlers like Browserify often have browser versions of core Node.js modules, like this one for crypto.
If you are using rn-nodeify as #emmby suggests, then you can use react-native-crypto. Instructions from the README:
Install
npm i --save react-native-crypto
# install peer deps
npm i --save react-native-randombytes
react-native link react-native-randombytes
# install latest rn-nodeify
npm i --save-dev mvayngrib/rn-nodeify
# install node core shims and recursively hack package.json files
# in ./node_modules to add/update the "browser"/"react-native"
# field with relevant mappings
./node_modules/.bin/rn-nodeify --hack --install
rn-nodeify will create a shim.js in the project root directory
// index.ios.js or index.android.js
// make sure you use `import` and not require!
import './shim.js'
// ...the rest of your code
But rn-nodeify also states:
If you're looking for a saner approach, check out ReactNativify. I haven't tested it myself, but I think philikon will be happy to help
With ReactNativify you create a rn-cli.config.js and then in a transformer.js you let Babel transform bundle dependencies using babel-plugin-rewrite-require:
// The following plugin will rewrite imports. Reimplementations of node
// libraries such as `assert`, `buffer`, etc. will be picked up
// automatically by the React Native packager. All other built-in node
// libraries get rewritten to their browserify counterpart.
[require('babel-plugin-rewrite-require'), {
aliases: {
crypto: 'crypto-browserify',
// ...
},
throwForNonStringLiteral: true,
}]
(Note: You can also do this in without these 2 js files directly in .babelrc)
(Note2: Though ReactNativify is the cleaner way, it is still giving me issues wiring up crypto.getRandomValues for production-use in RN. See this question)
You can use the rn-nodeify module to get crypto on react-native.
Add rn-nodeify to your devDependencies in package.json:
"devDependencies": {
"rn-nodeify": "^6.0.1"
}
Add the following to the scripts section of the same file:
"scripts": {
…
"postinstall": "node_modules/.bin/rn-nodeify --install crypto --hack"
}
Be aware that rn-nodeify will modify your package.json.
More information available here: https://www.npmjs.com/package/rn-nodeify
React Native packager uses Babel under the hood. This means that you can use babel-plugin-rewrite-require Babel plugin to rewrite all require('crypto') calls to require('crypto-browserify'), assuming that the latter is installed in your node_modules.
As of January 2016, you can use .babelrc file to define optional configuration, so this becomes really easy. First, install the dependencies:
npm install --save crypto-browserify
npm install --save-dev babel-plugin-rewrite-require
Then add plugins config to your .babelrc file:
{
"presets": ["react-native"],
"plugins": [
["babel-plugin-rewrite-require", {
"aliases": {
"crypto": "crypto-browserify"
}
}]
]
}
Restart the packager and that should be it.
This is the same approach that ReactNativify uses, except that here we use .babelrc instead of defining custom transformer. When ReactNativify was written, it was not supported, so they had to go with more complex solution. See this file from ReactNativify for almost complete list of node polyfills.
I was having the same issue when implementing the Twilio package in my React Native app, and having React Native break over the crypto dependency.
As a work around I ended up creating a separate, stand alone Node/Express app to act as my server and take care of the Twilio logic I had. That way I removed all Twilio logic from my React Native app and moved it to Node. I then just called my Express route in React Native using fetch, which triggered the functionality I wanted to happen with Twilio. If you're unfamiliar with fetch here's a good starting point -
Making AJAX calls with Fetch in React Native
In addition, here's my question on the crypto dependency breaking my app:
twilio-react-native-unable-to-resolve-module-crypto
As far I can see amazon-cognito-identity-js uses crypto-js 3.3.0 without any additional magic... If that version of the package works then perhaps try that.
After having tried a bunch of these solutions and never really having been satisfied with any of them (some didn't even work), I managed to stumble upon react-native-quick-crypto, which honestly worked much more effortlessly than trying to lift the existing crypto library to the front-end

Resources