Create a basic Express server
A disclaimer: I wrote this a long time ago, when I was just learning server-side JavaScript. I think it's still a decent guide to creating a full-featured Express server, but keep in mind that there's probably better, more up-to-date guidance out there, like this guide from DigitalOcean.
Whenever I spool up a new Express application, I tend to forget the steps I take. I'm writing them down here for my benefit, but the hope is that you will come across this in the future sometime and it'll benefit you too.
Generating your files
As much as it would be nice, it's non-standard to have a single enormous app.js
and package.json
and let that be the end of it. You'll never collaborate with anyone with that attitude. There needs to be some structure.
Luckily, Express comes with a tool just for that: the express-generator
package. It creates a very basic framework of files to save you the half-hour or so of configuration needed to get everything in the right place, and it encourages modularization within a standard. You'll find more information about it here.
express-generator
gets installed globally (so you can use it anywhere) and then run with an express
command. You can specify options for customizing the HTML and CSS engines you want to use, which is handy.
$ npm install -g express-generator
... the general npm install rigamarole
$ express --view=pug myapp
create : myapp
create : myapp/package.json
create : myapp/app.js
create : myapp/public
create : myapp/public/javascripts
create : myapp/public/images
create : myapp/routes
create : myapp/routes/index.js
create : myapp/routes/users.js
create : myapp/public/stylesheets
create : myapp/public/stylesheets/style.css
create : myapp/views
create : myapp/views/index.pug
create : myapp/views/layout.pug
create : myapp/views/error.pug
create : myapp/bin
create : myapp/bin/www
$ npm install
... more rigamarole
Make sure to include that
—view=pug
part, or else you’ll wind up with thejade
templating engine, which is exactly the same aspug
, except for that Node will hammer you with warnings thatjade
has been renamed topug
. Go figure.Another short side note about your fundamental structure here:
app.js
is where the app's configuration goes;package.json
is, wellpackage.json
;public
is where you assets (stylesheets, images, javascripts) go;routes
contains your routing (and the functions that get run on those routes); andviews
, predictably, contains thepug
templates that get rendered by the functions within your routes.bin
is where thewww
file sits, but I don't like it and I'm going to change that in the next paragraph.
This is a purely personal choice, but I don't like having my app's configuration at the top level in app.js
while the logic that actually starts the app's server sits in some other folder. So I prefer to grab everything in /bin/www
and put it into a start.js
file that sits at the top level.
Of course that means that you have to go into your package.json
and change the start script. Don't bother with the standard node
command; if you haven't already, go npm install -g nodemon
, which does the same as node
except for it accepts hot reloading, so you don't have to stop and restart your server every time to make a change to your files.
Then go into your package.json
and fix that "start"
script:
/package.json
...
"scripts": {
"start": "nodemon start.js"
},
...
And just like that, you're all set. Time to get the server started up.
$ npm start
Whoo boy look at you go.
A couple of explanations of things I didn’t know
You might notice once I navigated to ‘localhost:3000’ that you'll also see a list of requests being console.log
ed, along with some metadata.
Check out this extra-snazzy terminal, courtesy of Hyper
These come from the morgan
logger package in your app.js
file. Specifically the app.use(logger(‘dev’));
line. Morgan comes with a few predefined formats which determine what gets outputted on request, or you can fiddle with the options yourself. I haven’t dug too deep into the docs, but like I said (wrote?), this more as a reference for myself. So heads up, that’s what that is.
Another thing you'll notice in the app.js
file is copious use of the app.use()
function. This basically sets up some middleware for whatever route is specified in the first argument (defaulted to ’/‘
, which means every route). The second argument is the callback that gets run. Simple enough.