Starting Express.js Using app.js or 'npm start'? - node.js

I've recently installed Node.js on a local server and when I create a 'server.js' file (adding a server using the .createServer() method), it loads fine.
However after installing Express.js, the default files are as follows:
/bin
/node_modules
/public
/routes
/views
app.js
package.json
After following some documentation, I am instructed to go to Terminal and enter the following command:
node app.js
To which nothing happens, the command line refreshes to the next line in less than a second, and opening a browser after visiting the proper IP and port, to no avail.
Below is the code inside of the app.js file:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
I understand that the actual 'express' module that is being required in the beginning of the file is where the magic happens, however, when I run the command line:
node app.js
Nothing happens. However, if I call the following line:
npm start
Everything appears to be okay. I would like to follow the documentation as is, any reason why the app.js wouldn't be working?
Thank you.
UPDATE: My question was too similar to another one already posted, so I must clarify exactly how they were different. In the other question, a person was questioning a code number they received while running the Supervisor command on the default 'app.js' file.
While similar in nature, this question should remain, as those who are confused by using my same approach will focus on the identity of the actual 'app.js' file by using 'node app.js' without having full knowledge of the Supervisor utility.
Regards.

Thank you all for your great responses, as they really allowed me to understand what is actually going on with the app.js file and where it receives it's functionality. Thank you to both Matthew Bakaitis and Bjarni Leifsson for their great input.
The only reason why I am going to go ahead and answer my own question is because while the nature of the app.js file was explained, exactly how to replicate calling the 'node app.js' command from the command line as to replicate a Node.js book that I was following wasn't implicitly addressed.
After searching google with the specific phrase "app.js in previous express.js versions", I happened upon a great article by Jilles Soeters entitled "Understanding the Express app.js":
http://jilles.me/getting-the-express-app-js/
Below is the excerpt of the solution that worked for me:
The file I'm covering is app.js, the main configuration file for your
Express app. When I first opened app.js it confused me. I will save
you the trouble of doing research and just cover them here.
Before you do anything add the following to your app.js
app.listen(3000);
You need that in order to be able to actual open your app in the
browser. Go to 127.0.0.1:3000 after you've started your app (using
node app.js)
After doing this, I was able to run the command
node app.js
I was able to run this command from the root directory of the Express install and proceed with my Node.js book with no additional problems.

This is a common problem that is caused when tutorials don't clearly explain what express is doing when it generates an app. You're trying to learn the new tech, but the tutorial is actively working against you. :(
The answer:
When you use the generator, package.json is configured so that npm start calls ./bin/www.
That file includes app.js and after the include, calls app.listen.
app.js doesn't call app.listen which is why if you call it directly, it exits with no code or info. You've got to call ./bin/www or you have to modify app.js...which then defeats some of the reasons you'd use a generator.
A related question here on the site saw a similar problem when trying to use supervisor to keep an app running but kept getting an exit 0 result.

How I understand this, and I have just started to use node.
There is a bin folder with www in it. There all the magic happens. So when you do node app.js it gets executed but the logic to the everything is in bin/www
So if you look into package.json you see this init :
"scripts": {
"start": "node ./bin/www"
},
So giving that, you see to execute the script you use the start method and it is linked to ./bin/www
If you take a look in that file you will find out that the whole logic of the server to start up is in there.
So if you change start to something else, like TurnOn and would do npm TurnOn, it will execute ./bin/www and the whole project for you.
The structor of the project is all linked together, and app.js is not enough to start the server.
Hope this helps.

When using Express the Express instance will create the server for you. Typically your app/index/server.js file will begin with these lines:
const express = require('express');
const app = express();
These lines require Express and then instantiate an instance of Express within the app variable. Express then uses var server = http.createServer(app); to start a server for you. All you need to do is to make sure your app listens to that server (as you wrote). However, the port for the connection may vary so it is not advisable to hard-code it. Instead it should be retrieved from the app variable as such:
app.listen(app.get('port'), function(){
//Something to do when the server starts.
});
Additionally, after creating your own app.js file make sure to change your package.json file to start the app via app.js instead of the Express module. By default your package.json might look like this:
"scripts": {
"start": "node ./bin/www"
},
But after you created your own app/index/server.js file you want node to start running that file on startup instead:
"scripts": {
"start": "node app.js"
}
You can then start your app by writing npm start from the project directory.

Related

express app is not sending index.html file to client

So my express app has a small Node server setup so it can serve up the index.html file when the home route '/' is hit. This is a requirement of using the App Services from Azure, there has to be this server.js file to tell the server how to serve up the client, and i had a previous implementation of this working, however i wanted to change my file structure. previously i had, the client React app in a folder client and the server.js in a folder server along with all of the conrtollers and routes. i've since moved the server API to its own application as there are other apps that depend on it. and i moved the client up one directory into the main directory. Everything was working fine till the other day when all of the sudden when you hit the home route / it will not serve up the index.html file. if you hit any other route it works, if you even hit a button linking back to the homepage, it works, but it wont serve up the app from the / and i cannot for the life of me figure out why, on my development server there are no errors in the console. and im most definitely targeting the correct directory and place for the index. but its like the server isnt reading the route to serve up.
if (process.env.NODE_ENV === 'production') {
console.log('running');
app.use(express.static(path.resolve(path.join(__dirname, 'build'))));
// no matter what route is hit, send the index.html file
app.get('*', (req, res) => {
res.sendFile(path.resolve(path.join(__dirname, 'build', 'index.html')));
});
} else {
app.get('/', (req, res) => {
res.send('API is running...');
});
}
So here im saying if the NODE_ENV is in production make the build folder static, and then whatever route is hit. (Note: i also tried this app.get with other route formats such as /* or / all have the same issues. however in my previous iteration when the client and server where deployed in the same location, /* is what i used.) The .env varialbes are setup correctly, as when the server is ran, itll console log running.. but even if i put a console log inside of the app.get() its like its never hit unless i access the route from something else first.
for example, if i place a console log inside of app.get that states hit whenever the route is hit, hitting / directly does nothing, but if i go to /login itll serve up the correct html on the client and console log hit in the terminal...
If you are having server files inside the client react app, then we are basically accessing file which are not inside our server file. So, we can serve static files using the following code:
const express = require("express");
const app = express(); // create express app
const path = require('path');
app.use(express.static(path.join(__dirname, "..", "build")));
app.use(express.static("build"));
app.listen(5000, () => {
console.log("server started on port 5000");
});
Now in your packages.json of the client react app change the name of start tag under scripts tag to start-client. Then add this following tag to the scripts tag:
"start":"npm run build && (cd server && npm start)",
Basically, this will build the react app and start the server.
It should look like this :
Also in the packages.json of your server add the following tag under script tag
"start":"node server.js"
So when you run the following command npm start it should look like this :

How to properly set Angular for production in NodeJS Express Server?

I have been working for hours on figuring out how to deploy my Angular 6 project on NodeJS Express server,
First, in development i use ng serve which refer to localhost:4200 (default) and another one is Node Express for API (interacting with DB) on localhost:3000. In production i want the Angular build to be served from that Node Express server too.
So what i did was:
Setting up <base href="/"> on index.html on Angular Project
Run ng build --prod it went 100% smooth, no errors.
Copy all files from dist/myprojectname on Angular to Node Express server directory under views/.
In index.js i add following lines app.use(express.static(path.join(__dirname, '/views/')));
it got error something like this
Refused to apply style from 'http://localhost:3001/styles.a64e6aa0f6090e05d2190.css/' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
3localhost/:16 GET http://localhost:3001/runtime.16a329deb1d564eef6599.js/ net::ERR_ABORTED 404 (Not Found)
If i use app.use('/*', express.static(path.join(__dirname, '/views/')));
it will give following error:
Uncaught SyntaxError: Unexpected token <
This seems similar to this issue, are you sure that your css files are NOT starting with comments?
From the linked question's answer:
The issue i think it was with a CSS library starting with comments.
While on dev, i do not minify files and i don't remove comments, this
meant that the stylesheet started with some comments, causing it to be
seen as something different from css.
Hope this helps you this worked perfectly fine for me. The important part of the code is below. My angular application is in ROOT_FOLDER/dist/index.html . You can set the compile/output path in angular.json (variable is outputPath). My express.js file and package.json file is just under the root folder.
const bodyParser = require('body-parser');
const DIST_FOLDER = join(process.cwd(), 'dist');
const STARTING_SERVER_MSG = 'Running server on port %s';
const VIEW_ENGINE_STR = 'view engine';
const HTML_STR = 'html';
const VIEWS_STR = 'views';
const BROWSER_STR = 'browser';
private routes() {
// This part might be useless STRAT_LINK later
this.app.set(VIEW_ENGINE_STR, HTML_STR);
this.app.set(VIEWS_STR, join(DIST_FOLDER));
this.app.use(express.static(join(DIST_FOLDER)));
this.app.use(bodyParser.json());
this.app.use(bodyParser.urlencoded({extended: false}));
// this.app.use('/env', envRouter);
// get router
this.app.use(function (req, res, next) {
res.sendFile(join(DIST_FOLDER, 'index.html'), {req});
});
}

Visual Studio Code - Node.js - Cannot find name '__dirname'

Just to preface I'm not a professional coder, but nonetheless I got roped into building a website for my boss after he found out I took "Web Design" in high school 10 years ago. Back then static sites were fine, and heck CSS was just starting to show it's potential, but I digress.
I'm working on a Node.js project on Visual Studio Code right now and have a weird exception. The code works fine, but I guess it's just curiosity at this point. Anyway, here's my code.
app.js
var express = require('express'),
app = express(),
bodyParser = require('body-parser'),
multer = require('multer'),
controller = require('./controllers');
//Sets the view engine to jade.
app.set('views', __dirname + '/frontend');
app.set('view engine', 'jade');
//sets up the development enviroment
if (app.get('env') === 'development') {
app.locals.pretty = true;
app.use(express.static(__dirname + '/build/public'))
var build = require(__dirname + '/build.js');
app.use('css/*', function(req, res, next){
build.style();
next();
});
}
//Sets up the public directory to serve static files - This will be depricated quite soon...
//app.use(express.static(__dirname + '/public'));
//Initalizes site-wide local variables
//app.set('title', 'Halvorson Homes');
//Sets up body-parser to be able to read RESTful requests
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(multer({dest: 'tmp'}).fields());
//Load Controllers
app.use( '/' , controller);
//makes the app listen on port 3000
app.listen(3000, function() {
console.log('Listening on port 3000...');
})
My folder structure is pretty much as follows
controllers
index.js
designs.js
models
designs.js
frontend
common
layout.jade
header.jade
footer.jade
client.js
style.less
index
index.jade
client.js
style.less
designs
index.jade
client.js
style.less
build
tmp
srv
app.js
build.js
package.json
According to VS Code's built in debugger there's exceptions on lines 8, 14, and 15. They're the only places I used __dirname in the entire project. This is an annoying to me, as I am too much of a perfectionist. Is it Node, VS Code, or something else?
The warning you are getting is from the eslint extension. While it may be valid in Node.JS, it's warning you about __dirname because it's not valid in all JavaScript environments such as in browsers.
To suppress the warning you will want to create an .eslintrc file in your project's root directly and indicate that the code will be running in node like so:
{
"env": {
"node": true
}
}
You can see the .eslint file used to configure eslint for the actual vscode codebase here https://github.com/microsoft/vscode/blob/main/.eslintrc.json
Late to the party, but just had the same issue. The fix for me was to add the node types so VSCode recognises them:
Go to the Terminal view, then enter the following:
npm install #types/node --save-dev
Then hit Cmd + Shift + P (for Mac at least) to bring up the VSCode command search dialogue, then select Reload Window.
When it reappears, that error and any other related to Node.JS stuff not being recognised should be gone.
Alternatively to creating a separate .eslintrc file, you can also add it to the package.json file.
The docs state:
To specify environments in a configuration file, use the env key and specify which environments you want to enable by setting each to true. For example, the following enables the browser and Node.js environments
{
"name": "mypackage",
"version": "0.0.1",
"eslintConfig": {
"env": {
"browser": true,
"node": true
}
}
}

Node starts my server, so does gulp, but gulp doesn't find any paths

I am sure this is something small, but I am unable to figure it out. Node, nodemon and gulp use app.js to start my server so I am not sure why one way works while gulp does not. If I start my server using:
nodemon app.js or
node app.js it starts fine and when I use the path localhost:1337 in the browser it does what it is supposed to do.
When I use the command:
gulp
it says that it started the server but when I navigate to localhost:1337 it does not display anything other than "Cannot GET /" and none of my sources are showing in the inspector. I still get the message that "the port is listening" as indicated in my app.js console.log. My gulpfile is as follows:
var gulp = require('gulp');
var nodemon = require('gulp-nodemon');
gulp.task('nodemon', function(){
nodemon({
script: './app/app.js'
})
});
gulp.task('watch', function(){
gulp.watch('*.js', ['nodemon']);
});
gulp.task('default', ['nodemon']);
my app.js file is:
express = require('express');
var app = express();
app.use(express.static('../views'));
app.use(express.static('../bower_components/angular'));
app.use(express.static('./directives'));
app.listen(1337);
console.log("The port is listening");
The 'Cannot GET /' being displayed when you go to localhost:1337 is Express's generic message when a request is made against a route that is undefined. A route needs to be defined for the pages that you want to serve. You need to add a Route to handle the request to the root of your app at http://localhost:1337/.
app.get('/', function(req, res) {
// return back a message
res.send('Welcome!');
});
Place the above snippet above app.listen() and the message "Welcome!" will be displayed.
To serve a view in an html file you need to add a view engine so Express knows how to render the file. Additionally, the views property needs to be configured so Express knows where to render your views from. The example below uses ejs to just handle plain html files and not worry about a template engine like jade.
app.use('views', path.join(__dirname + '/views'));
app.engine('html', require('ejs').renderFile);
app.use('view engine', 'html');
Now we can use the render function on the res object to send our index.html file:
app.get('/', function(req, res) {
res.render('index');
});
This a guide from ExpressJS on how to implement routing in Express.

Express.js App on Phusion Passenger - did not write a startup response in time

I am trying to run an express.js app on a server running Phusion Paggenger (apache) and am seeing the error "An error occurred while starting the web application: it did not write a startup response in time." after the request times out. I've read through https://github.com/phusion/passenger/wiki/Debugging-application-startup-problems but this seems a bit obscure. My express app is as bare-bones as possible so I'm wondering if anyone knows if there may be a component specific to express that might cause this. I have been able to run a plain node.js app with the same setup on the server.
If you used the express-generator command to set up your project, you might see if pointing your Virtual Host configuration file's PassengerStartupFile line to bin/www instead of app.js does the trick instead of explicitly calling app.listen in the app.js file. Phusion Passenger's documentation does not address this specific convention adopted by ExpressJS. You can read some about this bin/www startup convention on Express's Moving to 4.x guide. Seemed to work for me.
It seems that you need to explicitly call app.listen within app.js. Specifically, I do this only when in production:
if (app.get('env') === 'production') {
app.listen(3000);
}
at the end of app.js
If you are getting here from google. This is now documented with Passenger: https://www.phusionpassenger.com/library/indepth/nodejs/reverse_port_binding.html
A working example of a simple express app is below:
if (typeof(PhusionPassenger) != 'undefined') {
PhusionPassenger.configure({ autoInstall: false });
}
var express = require('express');
var app = express();
app.get('/', function(req, res){
var body = 'Hello World';
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Length', body.length);
res.end(body);
});
if (typeof(PhusionPassenger) != 'undefined') {
app.listen('passenger');
} else {
app.listen(3000);
}

Resources