Background
Sometimes, a full blown SPA is overkill for a simple node express js web project so we will setup a simple Express Js multi page app using Visual Studio 2017 community without the hassle cmd/powershell tools (but please tinker with it once you get comfortable, the true magic happens there). I assume you have a little ASP NET MVC/ ASP NET Core experience.
Dev Environment Requirements
A working dev machine, just be patient if it's sluggish, we have to start somewhere and make the most out of it.
Install/update to the latest version of Visual Studio 2017 Community Edition.
Download from https://visualstudio.microsoft.com/downloads/.
Run installer, then select Node.js development workload (you may not check others as shown below).
Now Let's Code
Create a new expressjs 4 project using template (under the hood, it used express generator).
This will create an Express boiler plate app. Files will be as shown below:
NPM
- are packages installed on this project, this reflects the contents of package.json file - Public - is a directory for our project’s static content, acts like wwwroot dir on ASP NET Core
- Routes - is a directory that contains our route definitions, if you have ASP NET Core background, it's like controllers with Route decorator attribute on top.
- Views - Self-explanatory. Unlike ASP NET Core views that uses razor, expressjs uses PUG by default as a view render engine which makes writing HTML simpler. (Just be careful with tabs and spaces, see external references below this article for detailed tuts).
- App.js - This is our app’s entry point. Think of this like ASP NET Core’s program.cs and Startup.cs.
- Package.json - This file is used to give information to npm that allows it to identify the project as well as handle the project's dependencies.
- README.md - Self-explanatory
Time to run this app. This will look like the image below, too plain, right? So, we will add bootstrap 4.
Add a new directory under public, set name to lib.
Right click on project to show a context dialogue. Click Add -> Client-Side Library...
Type in “Twitter-bootstrap” then click matching package listed on dropdown(version must be 4.X.X ). Select Choose specific files then select bootstrap.min and bootstrap.min.js
Set path to lib/twitter-bootstrap/ as shown below:
Once installed, our files will look like this:
Now, it is time to update our layout. Go to bootstrap example page. https://getbootstrap.com/docs/4.1/examples/starter-template/
Hit F12, using the browser element inspector, copy the page’s HTML markup.
Remember that express uses PUG by default? Which means we will have to convert what we have to PUG. Go to https://html-to-pug.com/. Paste the copied HTML, as shown below, this will convert our HTML to PUG.
We will make some modifications on the generated PUG, will point bootstrap references to our local setup and load route specific content. (For convenience, copy code below to Layout.pug.)
doctype html
head
meta(charset='utf-8')
meta(name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no')
meta(name='description' content='')
meta(name='author' content='')
title #{title}
// Bootstrap core CSS
link(href='lib/twitter-bootstrap/css/bootstrap.min.css' rel='stylesheet')
nav.navbar.navbar-expand-md.navbar-dark.bg-dark.fixed-top
a.navbar-brand(href='#') Navbar
button.navbar-toggler(type='button' data-toggle='collapse'
data-target='#navbarsExampleDefault' aria-controls='navbarsExampleDefault'
aria-expanded='false' aria-label='Toggle navigation')
span.navbar-toggler-icon
#navbarsExampleDefault.collapse.navbar-collapse
ul.navbar-nav.mr-auto
li.nav-item.active
a.nav-link(href='#')
| Home
span.sr-only (current)
li.nav-item
a.nav-link(href='#') Link
li.nav-item
a.nav-link.disabled(href='#') Disabled
li.nav-item.dropdown
a#dropdown01.nav-link.dropdown-toggle(href='https://example.com'
data-toggle='dropdown' aria-haspopup='true' aria-expanded='false') Dropdown
.dropdown-menu(aria-labelledby='dropdown01')
a.dropdown-item(href='#') Action
a.dropdown-item(href='#') Another action
a.dropdown-item(href='#') Something else here
form.form-inline.my-2.my-lg-0
input.form-control.mr-sm-2(type='text' placeholder='Search' aria-label='Search')
button.btn.btn-outline-success.my-2.my-sm-0(type='submit') Search
main.container(role='main')
br
br
br
//WILL LOAD ROUTE SPECIFIC CONTENT HERE
block content
//.container
// Bootstrap core JavaScript
script(src='https://code.jquery.com/jquery-3.3.1.slim.min.js'
integrity='sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo'
crossorigin='anonymous')
script(src='lib/twitter-bootstrap/js/bootstrap.min.js')
Rerun app, it will look like this:
Now that layout is setup, time to add a subscribe mailing list form. Copy this code to replace content of views/index.pug file:
extends layout
block content
//WILL ONLY SHOW ALERT BOX WHEN MESSAGE IS NOT EMPTY
if message !== ''
.alert.alert-primary(role='alert') #{message}
h3 Subscribe Now
.row
.col-md-12
form.form-inline(action='/subscribe' method='POST')
label.mr-sm-2(for='email') Email address:
input#email.form-control.mr-sm-2(type='email')
button.btn.btn-primary.mr-sm-2(type='submit') Submit
Let's add a route that will catch our post request.
And it's so simple, copy code below to replace contents of routes/index.js.
'use strict';
var express = require('express');
var router = express.Router();
router.get('/', function (req, res) {
res.render('index', { title: 'Subscribe',message:'' });
});
router.post('/subscribe', function (req, res) {
var resultMessage = 'thanks for the subs!';
res.render('index', { title: 'Subscribe', message: resultMessage });
});
module.exports = router;
Rerun it. Input email, then hit on submit, our page will then look like this:
Noticed we have todos on our code? I will cover them in my next tutorial. Stay tuned.
History