Having trouble running Phantomjs + node on Heroku - node.js

I've successfully got Phantomjs to work on Heroku but now I'm hitting issues with the phantomjs-node interface for node.js (see https://github.com/sgentle/phantomjs-node).
When I'm attempting to initialize Phantom I'm seeing a 10-15 second delay and then:
> phantom stdout: ReferenceError: Can't find variable: socket
phantom stdout: phantomjs://webpage.evaluate():1
phantomjs://webpage.evaluate():1
phantomjs://webpage.evaluate():1
You can reproduce the problem with the following steps or by pulling down my test app at https://github.com/matellis/phantom-test
git init phantom-test
cd phantom-test
heroku apps:create
# create node app as per Heroku instructions here https://devcenter.heroku.com/articles/nodejs
# copy bin and lib folders from http://phantomjs.googlecode.com/files/phantomjs-1.6.1-linux-x86_64-dynamic.tar.bz2 into root of your new project
# if you don't do this step you'll get an error "phantom stderr: execvp(): No such file or directory"
git add .
git commit -m "init"
git push heroku
Test your app has come up, the third to last line will tell you the URL, it should read like:
http://fathomless-ravine-5563.herokuapp.com deployed to Heroku
If successful you should see Hello World! in your browser.
Now from the same folder as your Heroku application run:
heroku run node
At the node prompt try the following:
phantom = require('phantom');
x = phantom.create();
Wait 10-15 seconds and you should see the error. Nothing works from this point on.
This should output file foo.png:
x = phantom.create(function(ph){ph.createPage(function(page){ page.open('http://bbcnews.com', function(status){ page.render('foo.png', function(result) {ph.exit()}); }); }); });
To validate Phantomjs is working fine on Heroku, try the following using my test project:
>heroku run bash
Running `bash` attached to terminal... up, run.1
~ $ phantomjs test.js http://bbcnews.com foo.png
~ $ ls *.png
foo.png
I cannot reproduce any of these problems locally but there are other issues reported where folks may have hit this issue locally.
The problem seems to originate in shim.js line 1637:
s.on('request', function(req) {
var evil;
evil = "function(){socket.emit('message', " + (JSON.stringify(JSON.stringify(req))) + " + '\\n');}";
return controlPage.evaluate(evil);
});
I've tried variations of versions of node, phantom, etc. with no luck.
I've also tried a custom buildpack that sets the DYLD variable, see http://github.com/tecnh/heroku-buildpack-nodejs with no luck either.
Anyone who has got Phantom + Node playing together nicely on Heroku please let me know. There are several references to this on Stackoverflow but nobody is saying "I got it to work, here's how".

I've never used the phantomjs node module, but I do have an app running both node and phantomjs on Heroku.
You need to use custom buildpacks in order to get this to work. My .buildpacks file looks like
http://github.com/heroku/heroku-buildpack-nodejs.git
http://github.com/stomita/heroku-buildpack-phantomjs.git
You should then be able to run phantomjs scripts in a child process:
var script = app.get('root') + '/scripts/rasterize.js' //the phantomjs script to run
, bin = app.get('phantom') //normally this would just be the string "phantomjs"
, spawn = require('child_process').spawn;
// set up args to the phantom cli
// (run the phantomjs command in your terminal to see options/format)
var args = [];
// ...
var phntm = spawn(bin, args);
phntm.stdout.on('data', function (data) { /* do something */ });
phntm.stderr.on('data', function (data) { /* do something */ });
phntm.on('exit', function (code) { /* handle exit */ });

Heroku does not support WebSockets. With Socket.io it has a workaround. Not sure about dnode, which phantomjs-node uses.
I had a problem with WebSockets on Heroku too and I switched to Nodejitsu, which solved it for me.

Related

nodejs and express with heroku im getting R10

thanks for taking time to help me
im deploying a nodejs express js project
these are the steps that i have done:
1- change the port to: process.env.PORT
code:
const PORT = process.env.PORT || 9000;
app.listen(PORT , function() {
console.log('Application is listening on 9000');
});
2- create Procfile with: web: node server.js
3- make sure in package json the npm start command points to "node path/server.js"
the server works locally
4- important note: I am sending an AJAX request from my front end to the server to get data
I have read on you documentation that i should add 0.0.0.0
$.ajax({
url: "0.0.0.0/hotels",
cache: false,
type: 'GET',
success: function(result) {
bla bla ....
}
});
also i have tried to add the url of heroku the one i get after creating
thanks in advance
have a great day
did not solve it yet but i organized some helpful heroku commands
useful commands
git remote -v
git remote rm heroku
heroku create
git push heroku master
heroku ps:scale web=1
heroku open
heroku logs --tail
heroku run bash
Your code there looks fine (except 0.0.0.0 -- just use a relative path like /). I would ensure you've actually pushed the changes you have there. If you run heroku run bash, do you see your Procfile? When you run node server.js in that environment, does it run successfully?
I've seen Heroku customers get stuck on an issue like this, when the reality is that the code they have locally wasn't properly sent to Heroku.
Hello #jmccartie thank you for replying but it still does not work
could it be the static __dirname? im starting to question every part of the code :D
I changed the path and just to make sure i understood correctly
it used to be : "http://localhost:9000/data/hotels"
now is: "/data/hotels"
would you mind taking a look at my code?
just double check the parts i mentioned
https://github.com/hibaAkroush/herokuNode
i will name the files to make it easier for you
1- Procfile in the root
2- server in server/index.js line 24
3- the front end (where im sending an ajax get request) client/home.js line 6
4- packagejson line 10: "start": "node server/index.js"
thanks
ok i fixed it ...
wohoo!
not sure which thing i made fixed it
but what i did was:
1- I moved the server to the root and of course changed the code a bit so it would still work than i tested it locally to make sure
2- pushed on github
3- added ./ to procfile so it became
web: node ./index.js
instead of web: node index.js
thanks everyone !

How to install node.js and create project in Eclipse

The steps I've tried:
1.(OK) install node from official website: https://nodejs.org/en/download/
Result: I'm able to open cmd(in any location, type node then use commands like "console.log" and it prints my messages)
2.(Failure) install express using npm install -g express from cmd gives me an error(picture attached
3.(OK) I've succeed installing express using the following command npm install express (without -g)
4.(OK) Writing a simple Hello World program works. Javascript file:
var http = require('http');
// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);
// Put a friendly message on the terminal
console.log("Server running at http://127.0.0.1:8000/");
5.(Failure) However, I wanna run a bigger project, where besides one js file, I also have an index.html file. If I move both files to node installation directory, everything works. But I wanna be able to keep my projects somewhere else. If I try to run with node C:\Users\marius\Downloads\chat-example-master\indes.js I get the error: Cannot find module express. Thus it seems that when I installed express without "-g" I got it working only in node directory.(let me know if you have any doubt).
6.(Failure) When creating a Node.js project from Eclipse, I choose empty project, no template, then add a single and simple js file(the one with Hello World), right click on project name -> run as -> run Configuration -> Node Application -> New -> add my .js file -> Run. I get the following error:
Exception occurred executing command line.(steps from http://techprd.com/how-to-setup-node-js-project-in-eclipse/)
Cannot run program "node" (in directory "C:\Users\marius\workspace\FirstNodeProject"): CreateProcess error=2, The system cannot find the file specified
To recap: What I want is to be able to run node projects located anywhere with "node" in cmd and to create node.js and express project and run them from Eclipse.
Please let me know if you need more information.
Just to let others know if they come across this issue. I can run express apps from anywhere but in the root folder of every app I have to npm install express.
In Eclipse all you need to do is: Window->Preferences->Nodeclipse->uncheck "find .Node on PATH" and insert into Node.js path input your node.exe location (in my case: C:\Program Files\nodejs\node.exe)

How can I run grunt as a daemon?

I am running a packaged nodejs webserver that allows for reading of epub files (Readium-JS), and it is started with the grunt command.
However, if I run this on my VPS the server dies as soon as my terminal connection ends.
How can I run this task as a daemon?
I have looked at options like grunt-forever and grunt-daemon but the way the Gruntfile is written using load-grunt-config is messing with my mind and I can't piece together how to isolate the server code.
Here's the solution I found:
As was suggested above, using pm2
However, when I ran
pm2 start grunt
I got an error saying that the grunt module did not exist, which was weird.
So I ended up writing a script which worked:
-- start.js --
var pm2 = require('pm2');
pm2.connect(function() {
pm2.start({
script : '/usr/local/bin/grunt', // Script to be run
args: '--force',
}, function(err, apps) {
pm2.disconnect();
});
});
After running node start.js from the command line, everything sailed smoothly.

phantomjs cannot find module webpage in node's child process

I'm trying to run phantomjs in a node child process. Phantomjs complains it can not find module 'webpage'. Running the script from the cli works fine:
phantomjs script.js
I stripped the problem down to these two files:
main.js:
var script = require('./script');
var cp = require('child_process');
cp.exec('/usr/bin/phantomjs script.js');
script.js
var page = require('webpage').create();
page.open("http://www.google.com", function(status) {
console.log("opened google? ", status);
var title = page.evaluate(function(s) {
return s;
}, 'Hello');
console.log(title);
phantom.exit();
});
Running the following command fails:
node main.js
with error:
module.js:340
throw err;
^
Error: Cannot find module 'webpage'
I've tried to specify the working directory in cp.exec as an option without effect. Is there a way to set the node search path for modules in a global context so it can be found in a new node process? Or am I doing something else wrongly?
PhantomJS is not a node.js module and cannot be directly used from node. I think you understand this, because you try to invoke it via child_process.
The problem is the line var script = require('./script');. As I understand, it is the phantomjs script. Since node.js doesn't have a webpage module, but phantomjs does the require fails and everything with it. Simply remove the line. It doesn't seem like you use it anyway.

Using Heroku Scheduler with Node.js

There is literally no tutorial about using Heroku Scheduler with Node.js. Assume that I have a function called sayHello() and I would like to run it every 10 mins. How can I use it in controller. In ruby you write rake function_name() however no explanation made for Node. Can I write '/sayHello' or I should do extra configuration?
Create the file <project_root>/bin/say_hello:
#! /app/.heroku/node/bin/node
function sayHello() {
console.log('Hello');
}
sayHello();
process.exit();
Deploy to Heroku and test it with $ heroku run say_hello then add it to the scheduler with task name say_hello.
Explanation
Take say_hello.js as an example of a Node.js script that you would normally run using $ node say_hello.js.
Turn it into a script by
removing the .js ending
inserting the 'shebang' at the top: #! /app/bin/node [1][2]
moving it into the bin directory [3]
[1] Read about the shebang on Wikipedia.
[2] The node executable is installed in app/bin/node on Heroku. You can check it out by logging into bash on Heroku with $ heroku run bash then asking $ which node.
[3] Heroku requires scripts to be placed in the bin directory. See Defining Tasks in the Heroku Dev Center.
I agree that the Heroku documentation for scheduling tasks is not very clear for anything other than Ruby scripts. I managed to work it out after some trial and error.
A better approach is to define your schedule file called for example worker.js with following content:
function sayHello() {
console.log('Hello');
}
sayHello();
and then in the heroku schedule, you just write node worker like you define it in the Procfile and that's all!
Christophe's answer worked for me until I needed to pass a parameter to the script, at which point it failed. The issue is that node should not be specified in the task. Here is how exactly to get it working:
In your Procfile, define a process type for your script. See below for a typical Procfile with a web process and, for running "scheduled_job.js", a second process type imaginatively named "worker".
web: node app.js
worker: node scheduled_job.js
In the Heroku scheduler's Task column, just enter the name of the process type ("worker" in this example) with or without parameters. Don't enter 'node' before it. Heroku shows a dollar sign in front of it, so examples of a valid setup would be $ worker (run without arguments) or $ worker 123 abc (to execute scheduled_job.js with arguments "123" and "abc")
I am confused that nobody tried:
$ heroku run node yourScript.js
So put this in Heroku Scheduler
node yourScript.js
Worked for me.
PS: be sure to import everything your script needs.
Following steps work in my situation.
In the root folder add worker.js file.
In worker.js. Write an simple function, like above.
function sayHello() {
console.log('Hello');
}
sayHello();
Go to heroku Scheduler add-ons. Click 'add new job' and type 'worker' in the field. Then set time interval and click save.
Here are something should notice
After update works setting.If using above example, you can use heroku run node worker.js to check if it work. It should be show 'Hello' in your terminal.
I use express-babel starter for my node.js project.
Thnks so much for the previous answers here.
I found the following worked for me where feed.js is the script to run as a job on Heroku.:
<PROJECT_ROOT>/bin/feed.js
The contents of feed.js start with:
#!/usr/bin/env node
async function mediumFeed() {
await fetch('https://medium.com/feed/stokedinfluence')
And end with:
}
mediumFeed();
And on Heroku the job is defined as node bin/medium_feed.js:
To run the node js script locally feed.js you can use from the root of your project directory node bin/feed.js and to run via heroku you can use heroku run feed.js --app <APP_NAME_NOT_PIPELINE_NAME>. When using heroku command, this will run the job from the server where as running node bin/feed.js will run locally. Run locally to test and verify the code works, once deployed verify it works with the heroku run... command

Resources