Getting started with Express
If you haven't already set up your Node sample project, you can quickly do so by following these instructions
The http module that we used in a previous activity can be difficult to work with when building web applications. There is a module/package named Express that we can install that is built on top of the http module, which makes it easier to build various types of web applications. There are other packages available for building web applications, but Express is by far the most popular.
To install the Express package/module, run this command from the project folder:
npm install express
Remember that whenever you install a module with NPM, the package.json should be updated to document the 'dependencies' for the project.
Now let's use Express to create a web application. Create a file named app.js in the project folder (NOT in the 'samples' folder) and put this code in it:
// IMPORTS
const express = require('express');
const app = express();
// MIDDLEWARE
// We'll add 'middleware' code here soon
// ROUTES
app.get('/', (req, res) => {
res.send('<h1>Hello World from Express!</h1>');
});
app.get('/some-route', (req, res) => {
res.send('<h1>This is some route</h1>');
});
// START THE SERVER
const port = 8080; // We'll run the server on port 8080
const server = app.listen(port, () => {
console.log("Waiting for requests on port %s", port);
});
We'll discuss the code in a minute, but first run the application by entering this command in the terminal:
node app.js
Now open a browser tab and navigate to :
http://localhost:8080
You should see a web page that says 'Hello World from Express!'.
Now try visiting this URL in the browser:
http://localhost:8080/some-route
You should see a page that says 'This is some route'.
Note that the terminal is in use right now, because it's running your web application (the web server application is continously 'listening' for requests from browsers). To stop the server and free up the terminal, press ctrl + c.
Now let's go over the code in app.js.
- First we import the Express module, which happens to be a function.
- Then we invoke the function, which returns an object that represents our web application (which is why the variable name is 'app').
- We'll discuss 'middleware' soon, but in this part of the file we could add features/functionality to our app known as middleware.
- Next we define a 'route' which is a path (relative to localhost:8080). The first route is for the website's home page. The second route will be executed when a request is made for localhost:8080/some-route. In the browser it would appear that you are viewing an index.html located in the some-route folder, but this is not the case. We'll talk more about routes in a bit.
- After the routes are defined, we choose a port for the application to listen for requests. In this case we chose port 8080 (if we haven't already discussed ports, please ask me about them in class). Or you can learn more now by visiting this page.
- The last few lines of code call the listen() method of our application object. The first parameter is the port that the application should use to listen for requests. The second parameter is a callback that will get triggered when the app successfully starts.
Notice that when we define the routes, we call the get() method of the application object. We pass in two parameters. The first parameter is the path (relative to localhost:8080) that will invoke the callback (which is the second parameter). As you saw, when we made a request to localhost:8080/some-route, the callback for that route was invoked and the response sent to the browser was an H1 element that said 'This is some route'. When the app receives a request that matches a route, it will execute the callback function that was defined for the route. Further, Express will pass two parameters into the callback function. The first parameter is an object that represents the incoming request (req) and the second is an object that represents the response that will be sent to the browser (res). Notice that inside the body of the callback, we invoked the write() method of the response object. We used this to write content into the body of the response that is sent to the browser.
For more information on HTTP requests and responses, checkout this article. Understanding HTTP is an important skill for web developers. And will dig deep into it later in the program. But for now you can get by without knowing all the ins and outs of HTTP.
We'll be working with routes in Express a lot more in the future.
Static Pages and Files
Routes are a powerful tool for building web applications. But we can also use Express to build a traditional website that is made up of 'static' html pages. This approach is very similar to the website that you created in the Web Programming class.
Create a folder named public (put it in the project folder).
Inside the public folder, add a file named static-page.html and put this code inside of it:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Static Page</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<h1>This is a static page</h1>
</body>
</html>
Now we'll configure the server to use the 'public' folder as a static one (it's common to use a 'public' folder for your static files, which is very similar to the 'public_html' folder that you are familiar with).
Add this code to app.js (you can put it underneath the comment that says MIDDLEWARE):
// set the 'public' folder as the location for our static files:
app.use(express.static('public'));
The use() method of an Express object allows you to add 'middleware' to your application. Middleware allows you to add functionality to your app. Don't worry too much about this line of code, just know that it designates your 'public' folder as one that will serve 'static' files for your website.
Now stop and restart the server by pressing ctrl + c in the terminal, and then entering node app.js. When you make updates to app.js, you must restart the server in order for the changes to take affect.
Then open this URL in the browser:
http://localhost:8080/static-page.html
You should see the 'static' page in the browser.
The public folder will contain the 'static' files for our website. Static web pages are ones that that don't change. When a request comes in for a static file, the server will simply send the file, as is, to the browser. This is very different from how routes work (we'll talk more about routes in the next section).
Now we'll put other files into the public folder, such as images, .js, and .css files.
Create these folders inside the public folder:
- images
- js
- css
Then put an image in the images folder (any .jpg or .png file will do).
In the js folder, add a file named main.js and put this code in it:
console.log("This is main.js...");
In the css folder, add a file named main.css and put this code in it:
h1{ color: midnightblue; }
Now update static-page.html to look like this (note that you'll have to use the proper name for your image file):
<!DOCTYPE html>
<html lang="en">
<head>
<title>Static Page</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Link to our style sheet -->
<link rel="stylesheet" type="text/css" href="/css/main.css">
<!-- Link to our .js file -->
<script src="/js/main.js"></script>
</head>
<body>
<h1>This is a static page</h1>
<img src="/images/eagle.png"><!---------USE YOUR OWN IMAGE HERE-->
</body>
</html>
Now reload the page in the browser (http://localhost:8080/static-page.html), and note the following:
- Your image should appear on the page.
- The H1 element should be blue (because we linked the page to the stylesheet)
- If you check the console log, you should see that the JavaScript code in main.js has executed.
Note that the links to the static files start with a forward slash. These paths are known as doc root relative links. When we added the middleware code to app.js, we designated the public folder as the root folder for our static files. This means that any link path that begins with a forward slash will start in the public folder and follow the rest of the steps in path from there.
Dynamic Pages (Routes)
In contrast to static files, our website may also include dynamic 'pages'. These are actually routes that allow us to run some code on the server before sending the response to the browser. I put 'pages' in quotes because, although they appear to be pages when viewed from the browser, they are really routes that we define in our app.
Here's an example, add this code to the ROUTES section of app.js:
app.get("/dynamic-page.html", (req, res) => {
const currentTime = new Date();
res.send(`<h1>The current time is ${currentTime.toString()}</h1>`);
});
Stop the server (ctrl + c) and then start it again (by entering node app.js in the terminal). Then visit this page in the browser:
http://localhost:8080/dynamic-page.html
If you refresh the page in the browser you'll see that responds with different content every time, which is why we call it a dynamic page. Dynamic pages (routes) allow you to run code on the server before sending a response to the browser.
In this simple example, the server is simply computing the current time and sending it in the response. But you could do much more complicated and useful things by running code on the server. For example, you run code on the server that connects to a database and embeds the results of a SQL query in the response before sending it to the client
It takes a bit of a mental shift once you start working with dynamic websites. You might think that for every URL on the site, there is a page (.html file) that goes with it. But this is not the case for dynamice sites, as you can see from the previous example, there is no file named dynamic-page.html in the project. But we did define a route for the url /dynamic-page.html.