See Update Below
I have written a Node.js application with Express that works fine locally, but when I run the app on Heroku, it gives me the following error:
2013-01-19T21:55:42+00:00 app[web.1]: module.js:340
2013-01-19T21:55:42+00:00 app[web.1]: throw err;
2013-01-19T21:55:42+00:00 app[web.1]: ^
2013-01-19T21:55:42+00:00 app[web.1]: Error: Cannot find module './blog/blog'
2013-01-19T21:55:42+00:00 app[web.1]: at Function.Module._load (module.js:312:12)
2013-01-19T21:55:42+00:00 app[web.1]: at Module.require (module.js:362:17)
2013-01-19T21:55:42+00:00 app[web.1]: at Object.Module._extensions..js (module.js:467:10)
2013-01-19T21:55:42+00:00 app[web.1]: at require (module.js:378:17)
2013-01-19T21:55:42+00:00 app[web.1]: at Object.<anonymous> (/app/app.js:15:12)
2013-01-19T21:55:42+00:00 app[web.1]: at Function.Module._resolveFilename (module.js:338:15)
2013-01-19T21:55:42+00:00 app[web.1]: at Module.load (module.js:356:32)
2013-01-19T21:55:42+00:00 app[web.1]: at Module.runMain (module.js:492:10)
2013-01-19T21:55:42+00:00 app[web.1]: at Function.Module._load (module.js:280:25)
2013-01-19T21:55:42+00:00 app[web.1]: at Module._compile (module.js:449:26)
2013-01-19T21:55:43+00:00 heroku[web.1]: Process exited with status 1
2013-01-19T21:55:43+00:00 heroku[web.1]: State changed from starting to crashed
I don't understand why it doesn't work on Heroku, because the exact same code works perfectly locally. Maybe it has something to do with how I put the code on Heroku's server? Just in case, below is my filesystem, the code for my app.js
file, and my blog.js
module that I want app.js
to load:
filesystem:
app.js:
//requires and starts up app
var express = require('express');
var app = express();
//db setup
var mongoose = require('mongoose')
, dbURI = 'localhost/brads-projects';
//configures app for production, connects to MongoHQ databse rather than localhost
app.configure('production', function () {
dbURI = process.env.MONGOHQ_URL;
});
//requires the various project files
var blog = require('./blog/blog').blog;
//tries to connect to database.
mongoose.connect(dbURI);
//once connection to database is open, then rest of app runs
mongoose.connection.on('open', function () {
//runs the blog app
blog(app, express);
app.listen(process.env.PORT || 5000);
});
//in the event of a connection to database error, the app will not run
mongoose.connection.on('error', console.error.bind(console, 'connection error:'));
blog.js:
module.exports.blog = function(app, express) {
//models
var postmodel = require('./models/post').postmodel
, usermodel = require('./models/user').usermodel
, notificationmodel = require('./models/notification').notificationmodel
, commentmodel = require('./models/comment').commentmodel;
//controllers
var indexHandler = require('./controllers/index').index
, newpostHandler = require('./controllers/newpost').newpost
, postandidHandler = require('./controllers/postandid').postandid
, newPostHandler = require('./controllers/newpost').newpost
, searchHandler = require('./controllers/search').postsearch
, loginHandler = require('./controllers/login').login
, logoutHandler = require('./controllers/login').logout
, dashboardHandler = require('./controllers/dashboard').dashboard
, registerHandler = require('./controllers/register').register
, userSettingsHandler = require('./controllers/usersettings').usersettings
, editpostHandler = require('./controllers/editpost').editpost
, newCommentHandler = require('./controllers/newcomment').newcomment;
//misc requires
var MemStore = require('connect/lib/middleware/session/memory');
//configures app for general stuff needed such as bodyParser and static file directory
app.configure(function () {
app.use(express.bodyParser());
app.use(express.static(__dirname + '/static'));
app.use(express.cookieParser('lockirlornie123'));
app.use(express.session({store: MemStore( {
reapInterval: 60000 * 10
})}));
});
//requires a user session for access
function requiresLogin(request, response, next) {
if (request.session.user) {
next();
} else {
response.redirect('/blog/login');
}
};
//requires user session and admin for access
function requiresLoginAndAdmin(request, response, next) {
if (request.session.user && request.session.user.role === 'admin') {
next();
} else {
if (request.session.user) {
response.redirect('/blog');
} else {
response.redirect('/blog/login');
}
}
};
console.log("loaded");
var PostModel = new postmodel();
var Post = PostModel.setupPostSchema();
var UserModel = new usermodel();
var User = UserModel.setupUserSchema();
var NotificationModel = new notificationmodel();
var Notification = NotificationModel.setupNotificationSchema();
NotificationModel.clickNotificationHandler(app, Notification);
var CommentModel = new commentmodel();
var Comment = CommentModel.setupCommentSchema();
app.set('views', __dirname + '/views');
app.set('view engine','jade');
/*
var newuser = new User({email: "[email protected]", password: UserModel.createHashPass("Brad1234"), role: 'admin', activated: true});
newuser.save(function (err) {
if (err) {
console.log("error saving!");
} else {
console.log("successfully created!");
}
});
*/
//get request for the home page that displays the 10 most recent posts
indexHandler(app, Post, PostModel, NotificationModel.getNotifications, Notification);
//get request for the unique page for every post
postandidHandler(app, Post, NotificationModel.getNotifications, Notification, CommentModel.getComments, Comment);
//post request for the submit url that creates a new post and puts it into the database
//if a get request is sent to the sumbit page, it redirects users away from the /submit url in order to keep them away and not cause errors.
newPostHandler(app, Post, requiresLogin, PostModel, NotificationModel.getNotifications, Notification);
//post request to create a new comment
newCommentHandler(app, Comment, requiresLogin, CommentModel, NotificationModel.getNotifications, Notification, NotificationModel.createNotification, Post);
//get request for search page that both displays search results and allows users to create new search queries
searchHandler(app, Post, NotificationModel.getNotifications, Notification);
//login page get request and post request
loginHandler(app, UserModel.authenticate, User);
//logout page that redirects back to home
logoutHandler(app);
//dashboard page for managing posts by user
//and if user is an admin, adding and deleting users
dashboardHandler(app, User, Post, requiresLoginAndAdmin, NotificationModel.getNotifications, Notification, Comment);
//a page for users to register for posting priveleges
registerHandler(app, User, UserModel, NotificationModel.createNotification, Notification);
//a page for user settings
userSettingsHandler(app, User, UserModel, requiresLogin);
//a page to edit posts
editpostHandler(app, Post, requiresLogin, NotificationModel.getNotifications, Notification);
};
UPDATE:
Thanks to the suggestions below, I have run heroku run bash
to find out what files are actually there, and when I do the following, I find out some intriguing information, namely that the file I am trying to import isn't actually there:
~ $ cd ./blog
~/blog $ ls
~/blog $ cd ..
~ $ cd ./addressbook
~/addressbook $ ls
~/addressbook $ cd ..
~ $ cd ./views
~/views $ ls
addressbook blog index
~/views $ cd ./blog
~/views/blog $ ls
dashboard.jade index.jade layout.jade newpost.jade register.jade
editpost.jade index_error.jade login.jade postandid.jade search.jade
Looks like something I am doing is not uploading those files in app/blog and app/addressbook. Interesting and a good piece of info. Thanks for the suggestions...
Heroku uses the lockfiles, either the package-lock. json or yarn. lock , to install the expected dependency tree, so be sure to check those files into git to ensure the same dependency versions across environments. If you are using npm, Heroku will use npm ci to set up the build environment.
Your link should be like https://test-name.herokuapp.com/ Even if the deployment is successful, but you have not defined a html as to how the webpage should look like, then you get 'Method not allowed', meaning, "https://your-app-name.herokuapp.com/" will have "Method not allowed".
Run the npm install command in your local app directory to install the dependencies that you declared in your package. json file. Start your app locally using the heroku local command, which is installed as part of the Heroku CLI. Your app should now be running on http://localhost:5000/.
Based on the information you have provided this might be the answer. In the mac terminal (i'm assuming from the screenshot you are running OSX) run this command from the folder in which the blog.js file is located.
file blog.js -I
This should tell you that the file has a mime type of 'text/plain', if it comes back with a mime type of 'text/x-c' then it looks like the file was originally created on Linux - this is your problem.
To solve this issue simply:
The new file should now have the mime type of 'text/plain'. Push the changes to Heroku and test.
If this was not the issue my next step would be to run:
heroku run bash
And see if the file exists in the location your app is expecting to find it on Heroku. If you still have issue post back the results of these investigations.
Let me know!
Reference: Mac developer Library: 'file' command
Strange behaviour; Try debugging using:
console.log( __dirname );
Make sure that the following path is correct (points to your blog.js file):
console.log( __dirname + '/blog/blog.js' );
Then try to explicitly pass it to require
: (might vary depending on what __dirname
returns..)
var blog = require( __dirname + '/blog/blog' ).blog;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With