Create a Node.js App Using the Express Application Generator Tool
1) Install Express dependencies, create the project directory, and run the generator
npm i -g express express-generator
mkdir express-project
cd express-project
express --view=hbs
Up above we installed the express libraries, created our project directory, navigated into our new directory, and then ran the express generator command. After doing so, run a cd
public
, /routes
, /views
, and /bin
directories. The generator basically created a nice MVC-structured application for us in one command.2) Intall project dependencies
npm install
Now that our application structure is in place, let’s install all of the libraries that are needed to run our application. Our generator command created a package.json
dependencies
section:"dependencies": { "cookie-parser": "~1.4.3", "debug": "~2.6.9", "express": "~4.16.0", "hbs": "~4.0.1", "http-errors": "~1.6.2", "morgan": "~1.9.0"}
3) Start your server and check out your new site!
Now that your application’s basic structure is in place, it’s time to do a preliminary run to see if it works. Go back to your terminal prompt, and execute npm start
. You should see the message node ./bin/www
display right after that, with no errors. Now open your browser, and enter the following in the url: localhost: 3000
. You should see the following load in your browser:
Wasn’t that easy? That is exactly why I love to use this tool. It creates all the basic elements that I need for any site, and I can customize the wazoo out of it because it doesn’t limit what I can change or add to it moving forward.
4) Add nodemon library
Nodemon is a utility that will monitor for any changes in your source and automatically restart your server. This means that we don’t have to run npm start
every time we make a server-side code change. We just need to run nodemon start
just one time, and it takes care of the rest. Install the library at your project root:
npm i -D nodemon
5) Clean up our routing structure and create related controllers.
See full code repository here.
Typical applications will separate the routing logic from the controller logic, and for good reason. As your application becomes more complex, you might find that a particular route has hundreds of lines of code in it. This makes it pretty difficult to see what is going on at a quick glance, makes testing difficult to implement, and can make it difficult to find code. Let’s clean up our starter code so that we don’t get detained by the MVC police! For this example, we are going to make a mock music app, which can process albums, genres, and artists.
Set up routes entry point, and create all controllers and routes files
Express (starting at version 4) comes with an express.Router
class, which enables us to create modular, mountable route handlers. In summary, we can make entire containers that respond to a particular route name (can you say “RESTful API” ?!).
First, we need to alter our application’s entry point, app.js
, to prep it for clean routing. Add a reference to our future routes index file at the top, and replace the current route references with our main routes index file:
const routes = require('./routes');
// Old codeapp.use('/', indexRouter);app.use('/users', usersRouter);
// New code, replace the above with thisapp.use('/', routes);
Next, let’s create our /controllers
directory, and all of our future router and controller files:
cd routes
touch albumsRouter.js artistsRouter.js genresRouter.js indexRouter.js
cd ..
mkdir controllers
cd controllers
touch albumsController.js artistsController.js genresController.js indexController.js
Replace the main router index.js file with our new modularized routing logic
Next, let’s replace the boilerplate code in /routes/index.js
with the following. This will set us up for modularized routes. Instead of responding to particular GET
or POST
requests, we set up each global, non-biased route response module with router.use()
:
One nice advantage to this approach is that changing a parent route reference only has to be done in one place. For instance, if I wanted to change the route reference genres
to categories
, I only have to do it in the above file. Otherwise, I would have to change every routegenres
reference in my application.
Create content for each new router file
Next, create our main index route file and all other music route files. Note that each route index reference /
has an implicit route attached to it, due to our index.js
setup. Each file is virtually identical, except for the references to the type of route:
Also, after you populate all of the route files, delete the original users.js
file that the generator created for us. We don’t need it anymore.
Create content for each new controller file
Finally, fill in the content for each of your new controller files. These files will contain functions that can be reused. By doing so, we create scalable functionality, which also makes it easy to set up testing (can you say “test-driven development”?!). Note that we are also using the newest ES syntax for object method definitions:
Your /routes
and /controllers
directories should now look like this:
/controllers albumsController.js artistsController.js genresController.js indexController.js
/routes albumsRouter.js artistsRouter.js genresRouter.js index.js indexRouter.js
Create our new music view handlebars template file
Now let’s create our new view file, which will be served for every music-related url route. Create a file and save it as music.hbs
under the /views
directory:
6) Integrate Sass for CSS compiling and add styles
Sass is an incredible CSS extension language which allows you to create CSS while using variables, logic, and other powerful features. In my opinion, I wouldn’t create any web project without it! The basic flow is this: create Sass files with a .scss
extension, which are then compiled into regular CSS files that are actually used by your application.
Install the node-sass library and create the scss directory in /public
npm i -D node-sass
cd public
mkdir scss
Add the compile execution instruction to package.json
"scripts": { "start": "node ./bin/www", "compile:sass": "node-sass public/scss/main.scss public/css/style.css -w" },
With this new instruction, you can run npm run compile:sass
in a terminal window separate from your main active server window. Any changes to your /scss
directory will immediately trigger another compile instruction and will create a new styles.css
file!
Add the sass starter files to the /scss directory
Add all of the below files to your new /scss
directory and populate their contents. I have included several Sass files to use for a good setup example, which all aggregate into our main file, main.scss
.
cd scsstouch main.scss _utils.scss _global.scss _link.scss _music.scss
In addition, note that our music template file contains BEM-style (block-element-modifier) CSS. This is my preferred method of scoping CSS, and I would recommend that you look into it if you have not used it before. Notice the nice nesting syntax that we use in _music.scss
, and our modifer syntax used in _link.scss
. This is a really nice Sass feature, because it makes clean and concise code where we only need to reference the parent class one time.
Update public directory names, css style link reference, and index.hbs
The Express generator uses some non-standard directory names. Let’s clean these up and also update our styles.css
link in the layout.hbs
file.
Inside of /public
, you’ll see the /javascripts
, /styles
, and /images
directories. Rename these to /js
, /css
, and /img
, respectfully. These reflect more common naming conventions. Next, update the layout.hbs
file style link reference for our directory rename change so that our styles still work:
<link rel='stylesheet' href='/css/style.css' />
Finally, add the anchor tag to our original index.hbs
file. It lets us navigate to our music page:
<a class="link" href="/albums">Go to music page</a>
7) Reload your app and jump for joy
Everything should now be in place for your app to function correctly. Run nodemon start
again if your server isn’t already running, and then load the index route ( localhost:3000
) in your browser and you should see the Express home view. Click the ‘Go to music page’ link and it should take you to your music view. Click around on the links and your description text should update appropriately to reflect the route/controller data that was returned. Pretty clean, right?
In Summary
Let’s recap everything that we did one more time for sanity’s sake:
- Loaded the express libraries
- Created our MVC skeleton app by running the Express generator
- Refactored the routes and controllers to make them more scalable and modular
- Added a handlebars view file for our main music page
- Integrated Sass with our project and added some example BEM styles
- Renamed some directories so that they more closely follow convention
- Celebrated!
I hope you enjoyed this tutorial and that you were able to learn some new things to help your future dev skills. Please leave a comment if you have anything else to add or if you have any questions etc. See the full GitHub repository here. Happy coding :)