Node.js app works locally but heroku says missing module - node.js

I made a simple chat application using Node.JS and Socket.IO, everything works fine locally, but when I push it to heroku it gives me an application error, when I check the logs, this is the error:
Error: Cannot find module 'indexof'
at Function.Module._resolveFilename <module.js:338:15>
at Function.Module._load <module.js:280:25>
at Module.require <module.js:364:17>
at require <module.js:380:17>
at Object.<anonymous> </app/node_modules/socket.io/node_modules/socket.io-parser/node_modules/emitter/index.js:6:13>
at Module._compile <module.js:456:26>
at Object.Module._extensions..js <module.js:474:10>
at Module.load <module.js:356:32>
at Functin.Module._load <module.js:312:12>
at Module.require <module.js:364:17>
So I figured out that indexof is a module that Socket.IO uses, and it is in my node_modules folder, but for some reason either it's not being pushed to heroku or it's just not being recognized. I reinstalled my modules 5-6 times and recreated the app but it's still giving me the same error. My package.json file has 3 dependencies: Express, Socket.IO and Jade

Alright so after 2 hours I figured the problem out, multiple folders named "emitter" that contained the indexof module also had a gitignore file that made git ignore the module, no idea why that was even there, but deleting them fixed the problem

In my case I had to add a few modules to dependencies, as they were only under devdependecies and were not built on production

I had the same problem , please read it carefully
These are solutions to socket.io related problems
I hope i will work
Ports in your (index.js or server.js) & (index.html and your client.js) port must be different. (refer below code)
=============your index.js file ======================
(port here is 8000)
const express = require("express")
var app = express();
const http = require('http')
var server = http.createServer(app);
const port = process.env.PORT || 8000
server.listen(port,()=>
{
console.log("Listening at port => "+port)
});
var io = require('socket.io')(server, {
cors: {
origin: '*',
}
});
const cors = require("cors")
app.use(cors())
=============your client.js file ======================
port here is 8080
const socket = io.connect('https://localhost:8080/')
=============your index.html file ======================
port here is 8080
<script defer src="https://localhost:8080/socket.io/socket.io.js">
</script>
Remember your "server.js or index.js" port should be different from "client.js" port (Rememeber this is important)
(index.html and your client.js) port must be same
You should always use 'http' while working with socket.io (refer above code)
U may not included cors as it allows u to have more resourses , without cors heroku prevent some dependencies to not install in heroku (refer above code)
Try replacing "io" to "io.connect"
const socket = io.connect('https://localhost:8080/')
Must write tag at the end in the HTML
U may forget to add this code which is must in "socket.io"
It is required in your html file
delete "node_modules" and "package-lock.json"
and write "npm i" in cmd
This should be in package.json 's scripts
"start":"node index.js",
I am not talking about nodemon , use simple node over here
May be version is creating a problem , u can avoid it by copying all "devDependencies" to "dependencies" in "package.json" and put "*" in version like this
"dependencies": {
"cors": "*",
"express": "*",
"nodemon": "*",
"socket.io": "*"
},
"devDependencies": {}

Related

Basic express setup: not sending anything to local port

I created a frontend app and now trying to incorporate backend into it.
ON the same frontend app i added an index.js file in the root directory, and installed express and required it in index.js file.
Very basic setup as below:
const express = require('express')
const cors = require('cors')
const port = process.env.PORT || 3001
const app = express()
app.get('/', (req, res) => {
res.send({
greetings: 'hi'
})
})
app.listen(port, () => {console.log(`Server on port ${port}`)})
Server is successfully on port 3001 as per my terminal, however, on localhost:3001 I'm not seeing any json response I set up in app.get.
It says Cannot GET / instead. When i inspected in devtool(Network) it says 404.
This seems a very straightforward setup, but what could've gone wrong here?
i just figured why. I installed nodemon but my “start” script is “node index.js”. Should’ve used “nodemon index.js”
Working now with nodemon index.ks
Your code is fine, There are no errors, I tested it and it works as expected.
However few things to note, Keep Backend in Seperate folder/dirctory unless required.
Coming back to your question, There are many possiblity such as some modules are not installed properly
try running following command
//this will install if any library is currupt or not installed properly
npm i
if it doesn't work then try clearing cache
Also keep in mind, In nodeJS dev server does not automatically refresh changes, you need to restart server to see changes or you can use dev dependancy called Nodemon (this will auto restart server on saving changes)

How do I deploy a static React "app" to Heroku?

Title was: How do I fix "Cannot use import statement outside a module" error on Heroku without causing a "Must use import to load ES Module" error?
This was before I understood that I was trying to deploy a "static" React "app" and Heroku was running index.js as if it was server code.
I had setup Procfile to contain:
web: node ./src/index.js
Then I saw this error:
...
2020-03-29T02:34:01.000000+00:00 app[api]: Build succeeded
2020-03-29T02:34:02.637867+00:00 heroku[web.1]: State changed from starting to crashed
2020-03-29T02:34:02.622526+00:00 heroku[web.1]: Process exited with status 1
2020-03-29T02:34:02.583667+00:00 app[web.1]: /app/src/index.js:1
2020-03-29T02:34:02.583689+00:00 app[web.1]: import React from 'react';
2020-03-29T02:34:02.583690+00:00 app[web.1]: ^^^^^^
2020-03-29T02:34:02.583690+00:00 app[web.1]:
2020-03-29T02:34:02.583691+00:00 app[web.1]: SyntaxError: Cannot use import statement outside a module
2020-03-29T02:34:02.583691+00:00 app[web.1]: at wrapSafe (internal/modules/cjs/loader.js:1072:16)
...
I tried to fix it by adding this to package.json:
"type": "module",
And then I got this error:
...
2020-03-29T03:05:01.000000+00:00 app[api]: Build succeeded
2020-03-29T03:05:06.293573+00:00 heroku[web.1]: Starting process with command `node ./src/index.js`
2020-03-29T03:05:08.744086+00:00 heroku[web.1]: State changed from starting to crashed
2020-03-29T03:05:08.724957+00:00 heroku[web.1]: Process exited with status 1
2020-03-29T03:05:08.650103+00:00 app[web.1]: internal/modules/cjs/loader.js:1174
2020-03-29T03:05:08.650125+00:00 app[web.1]: throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
2020-03-29T03:05:08.650126+00:00 app[web.1]: ^
2020-03-29T03:05:08.650126+00:00 app[web.1]:
2020-03-29T03:05:08.650126+00:00 app[web.1]: Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /app/src/index.js
2020-03-29T03:05:08.650127+00:00 app[web.1]: at Object.Module._extensions..js (internal/modules/cjs/loader.js:1174:13)
2020-03-29T03:05:08.650127+00:00 app[web.1]: at Module.load (internal/modules/cjs/loader.js:1002:32)
...
I should've noted that my React "app" is a front-end only that uses a GraphQL API I've already deployed elsewhere. In other words, there is no "server.js that serves [my] react app". (HMR's comment led me to that realization. I guess the correct terminology would be to call this a "static app".)
This code in server.js only slightly adapted from Tin Nguyen's answer works:
const http = require('http');
const path = require('path');
const express = require('express');
let wss;
let server;
const app = express();
app.use(express.static(path.join(__dirname, './build')));
server = new http.createServer(app);
server.on('error', err => console.log('Server error:', err));
server.listen(process.env.PORT);
...with this Procfile:
web: node ./server.js
The only change is the path to the build directory, which I tweaked after snooping around with heroku run bash.
My site isn't working properly, but I think that is the result of my build not being correct. Perhaps that can be solved with a buildpack. But that belongs in a different question. (And I might not bother figuring it out since I plan to take Tin Nguyen's advice and try hosting on GitHub.)
Update: The problem wasn't with my build, but with client-side routing (as described on https://create-react-app.dev/docs/deployment/). This code (from that page) fixes it (in server.js):
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(process.env.PORT);
The link in HMR's comment helped me reach this understanding, but Dave Ceddia writes that his article covers how to keep a React app and API server together. Is there any documentation on how to deploy a front-end on Heroku (or elsewhere) with an API server already deployed elsewhere?
(I found this answer where Paras recommends Netlify.)
If I am reading it right you have a static website and you want it to be hosted on Heroku.
Static websites can be served on Netlify and also GitHub pages. They don't require a web server. You can still host it on Heroku by wrapping a web server around it that is then serving your static files.
const http = require('http');
const path = require('path');
const express = require('express');
let wss;
let server;
const app = express();
app.use(express.static(path.join(__dirname, './../build')));
server = new http.createServer(app);
server.on('error', err => console.log('Server error:', err));
server.listen(process.env.PORT);
How do you know if you have a static website?
You should have generated build files somewhere in your project. You can navigate to the folder and open index.html. The website should work even though you don't have node or npm running. That folder is in my example ./../build.
Personally I would recommend you host static websites on GitHub over Heroku. Heroku is "free" but with a lot of limitations. The dyno hours are limited, websites need to spin up after not being in use for a long time, etc.
try changing your command:
node ./src/index.js
to:
node --experimental-modules ./src/index.js
Try for both with and without fix of package.json with
"type": "module"
Actually, this comes from using ES6 import inside the NodeJS environment. there is two way, using require instead of import in the server-side JavaScript files:
import something from 'something';
↓↓↓
const something = require('something');
Or use babel node on the server environment to run the project:
node ./src/index.js
↓↓↓
babel-node [options] [ -e script | ./src/index.js ] [arguments]
A complete example could be like below:
npx babel-node --presets es2015 -- ./src/index.js
By reading your errors, I guess the second way is better for your case. but at first please remove your solution, I mean the "type": "module",.

Cannot get correct static files after refreshing except index page

When I refresh page on index route (/) and login page (/login), it works fine.
However, my website gets error as I refresh on other routes, for example /user/123456.
Because no matter what the request is, the browser always gets HTML file.
Thus, both of the content in main.css and main.js are HTML, and the browser error.
I have already read the README of create-react-app.
Whether I use serve package ($serve -s build -p 80) or express, it will produce the strange bug.
Following is my server code:
//server.js
const express = require('express');
const path = require('path');
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
const PORT = process.env.PORT || 80;
app.listen(PORT, () => {
console.log(`Production Express server running at localhost:${PORT}`);
});
Edit: I have figured out where caused the problem.
I created a new project, and compared it to mine. The path of static files in the new project is absolute, but in my project is relative.
As a result, I delete "homepage": "." in the package.json.
//package.json
{ ....
dependencies:{....},
....,
- "homepage": "."
}
Everything works as expected now. How am I careless...
I have figured out where caused the problem.
I created a new project, and compared it to mine. The path of static files in the new project is absolute, but in my project is relative.
As a result, I delete "homepage": "." in the package.json.
//package.json
{ ....
dependencies:{....},
....,
- "homepage": "."
}
Everything works as expected now. How am I careless...
If your route /user/** is defined after app.get('/*', ... it might not match because /* gets all the requests and returns you index.html.
Try without the * or declare the other routes before.
First, I thought you misunderstood the server part. In your case, you use serve as your server. This is a static server provided by [serve]. If you want to use your own server.js, you should run node server.js or node server.
I also did the same things with you and have no this issue. The followings are what I did:
create-react-app my-app
npm run build
sudo serve -s build -p 80 (sudo for port under 1024)
And I got the results:
/user/321
I guessed you might forget to build the script. You can try the followings:
remove build/ folder
run npm run build again
Advise: If you want to focus on front-end, you can just use [serve]. It will be easy for you to focus on what you need.

How do I make Openshift to use Express 4, instead of its installed Express 3?

I developed my Nodejs Express app locally using Express 4 and it works as expected on my computer. I then git the whole app up to Openshift. When I try to run it Openshift returns"503 Service Unavailable". If I ssh into my base Node cartridge and do "express -V" it returns version 3.2.5. I get the same version 3.2.5 if I go into my app folder at app-root/repo and run "express -V".
So clearly my Express 4 which was included in the git upload in my app's node_modules is not being used. What is the solution to use Express 4 as required by my app?
Ideas are- remove Openshift's version of Express 3, force Openshift to use my Express 4 in my app area, upgrade Openshift's Express 3 to Express 4. I cannot figure out how to do any of those and I have researched this.
Here's how to troubleshoot:
ssh into your cartridge
cd into the app-root/repo directory
run grep version ./node_modules/express/package.json
you should see a version based on your package.json dependency
verify your package.json has a scripts section containing a start command that just runs your app with something like node ./server.js (server.js being whatever file you coded your main app start script in). You don't need the express command line program to launch an express server. It's for setting up new project boilerplate and other ancillary tasks.
To see the version of express running within your app, you can add this code to your server.js (or equivalent) file: console.log(require("express/package").version);
Look at this project to know how to integrate openshift with express4
Its a simple example .
https://github.com/master-atul/openshift-express4
try this
rhc ssh
cd app-root/repo
npm start
also edit the ./bin/www
var port = normalizePort(process.env.OPENSHIFT_NODEJS_PORT || '8080');
var ip = process.env.OPENSHIFT_NODEJS_IP;
if (typeof ip === "undefined") {
// Log errors on OpenShift but continue w/ 127.0.0.1 - this
// allows us to run/test the app locally.
console.warn('No OPENSHIFT_NODEJS_IP var, using 127.0.0.1');
ip = "127.0.0.1";
};
//app.set('ip', port);
app.set('port', port);
var server = http.createServer(app);
server.listen(port, ip);
server.on('error', onError);
server.on('listening', onListening);
you can follow step:
copy all content bin/www and replace all content in file server.js:
Change some content at server.js:
from
`var port = normalizePort(process.env.PORT || '3000');`
to
var port = normalizePort(process.env.OPENSHIFT_NODEJS_PORT || '3000');
Add line:
var ip = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';
from
server.listen(port);
to
server.listen(port, ip);
Add more to package.json
from
"scripts": {
"start": "node bin/www"
},
to
"scripts": {
"start": "node server.js"
},
Add line:
"main": "server.js",
Use npm install --save module-name for npm install
create file .gitignore with content:
node_modules
on local run node server.js to start server with address localhost:3000
upload to openshift:
git add .
git commit -m "First update new server version"
git push
Browser: domain-appname.rhcloud.com

How to deploy a reveal.js app to heroku?

I am trying to deploy a reveal.js application to Heroku. Reveal.js runs on node via grunt connect command. The app also requires ruby for compiling assets on-the-fly. Locally, I can run the app by using grunt serve.
Initially, because of compass being a dependency of grunt watch, Heroku only detected the Gemfile and assumed I was running a ruby app. I used the nodejs custom buildpack to force Heroku to see it as a nodejs app.
Procfile contains
web: grunt serve
Log shows
2013-06-17T13:51:56.187012+00:00 heroku[router]: at=error code=H14 desc="No web processes running"
heroku ps shows nothing either. I can run "heroku run grunt serve" successfully, and I have modified the default Gruntfile.js that comes with reveal to accept process.env i.e.
connect: {
server: {
options: {
port: process.env.PORT || 8000,
base: '.'
}
}
}
As a last attempt, I tried using the Heroku-nodejs-grunt build pack (https://github.com/mbuchetics/heroku-buildpack-nodejs-grunt) which will run a grunt task on deploy to compile assets. Still no luck, heroku logs --tail still shows no process running. Exploring with heroku run reveals that grunt is available, and the grunt serve command successfully executes.
When starting to use the new grunt build pack I got an error with the above Gruntfile.js saying "process" is undefined. I switched the port to 0.
The port on which the webserver will respond. The task will fail if
the specified port is already in use. You can use the special values 0
or '?' to use a system-assigned port.
Didn't work, tried "?", didn't work (still no web process and heroku restart doesn't do anything)
I can't figure out how to get Heroku to use grunt serve as my main web server process!
I was able to make it work using nodejs and expressJs.
By following the heroku "getting started with nodejs", I was able to get a working webapp with expressjs and by declaring this in the web.js:
var express = require("express");
var app = express();
app.use(express.logger());
app.use("/", express.static(__dirname));
var port = process.env.PORT || 5000;
app.listen(port, function() {
console.log("Listening on " + port);
});
With this you serve everything from / statically.
You have the sources here: https://github.com/MichaelBitard/revealjs_heroku and a working example here: http://murmuring-cove-4212.herokuapp.com/
Your problem was that by default grunt serve binds to localhost. For it to work you will need to do a couple of small changes to reveal.js:
First add grunt-cli as a devDependency:
diff --git a/package.json b/package.json
index 10489bb..4c58442 100644
--- a/package.json
+++ b/package.json
## -36,6 +36,7 ##
"grunt-contrib-connect": "~0.8.0",
"grunt-autoprefixer": "~1.0.1",
"grunt-zip": "~0.7.0",
+ "grunt-cli": "~0.1.13",
"grunt": "~0.4.0",
"node-sass": "~0.9.3"
},
Then add a hostname parameter to grunt that will be used to bind to 0.0.0.0 instead of localhost.
diff --git a/Gruntfile.js b/Gruntfile.js
index 3e67b9f..b2bfc47 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
## -1,5 +1,6 ##
/* global module:false */
module.exports = function(grunt) {
+ var hostname = grunt.option('hostname') || 'localhost';
var port = grunt.option('port') || 8000;
// Project configuration
grunt.initConfig({
## -94,6 +95,7 ## module.exports = function(grunt) {
connect: {
server: {
options: {
+ hostname: hostname,
port: port,
base: '.',
livereload: true,
Now you can create a Procfile with the following contents to deploy to Heroku:
web: npm install && node_modules/.bin/grunt serve --hostname 0.0.0.0 --port $PORT
I have created a PR for the needed changes to reveal.js.
Currently with express v~4.13.3 express.logger() is deprecated and is not included with the express package. To solve this I had to import the dependency morgan.
My web.js file ended up being the following:
var express = require('express');
var morgan = require('morgan');
var app = express();
var port = process.env.PORT || 5000;
app.use(morgan('combined'));
app.use('/', express.static(__dirname));
app.listen(port, function() {
console.log('Server started on ' + port);
});
As well, I needed to update my package.json to include the morgan lib. My dependencies in the file works with:
...
"dependencies": {
"express": "~4.13.3",
"morgan": "~1.7.0",
"grunt-cli": "~0.1.13",
"mustache": "~2.2.1",
"socket.io": "~1.3.7"
},
...

Resources