Node_crash_course

https://www.youtube.com/watch?v=2LUdnb-mls0&t=293s

To check the version of node:

node --version

Basic Hello World Example

Server.js:

const http = require("http");

const HOSTNAME = process.env.HOSTNAME || "localhost";
const PORT = process.env.PORT || 3000;

//then we create the server
const server = http.createServer((request, response) => {
    response.statusCode = 200;
    response.setHeader("Content-Type", "text/plain");
    response.end("Hello World");
})

//then we start the server
server.listen(PORT, HOSTNAME, () => (
    console.log(`Server is running at http://${HOSTNAME}:${PORT}/`)
));

http is one of the available modules in node.js. Process is a global object, and within it we have our environmental variable.

Then we create the http server.

To run the code, we open up our terminal and run:

node server

Screenshot_77

Screenshot_78

Screenshot_79

You just created your first webserver.

Stop the process in the terminal with Control + C.

Global Properties

We have access to other things other than process in the global object.

We also have:

global.__filename global.__dirname

Screenshot_80

This will help when we need to read and write files on the server.

File System Module

Reading files

Create an hi.txt file and put:

Hello World

Now we're going to read it.

const { log } = require('console');
const fs = require('fs');

fs.readFile("hi.txt", (err, data) => {
    if (err) {
        console.error(err)
        return
    }
    console.log(data);
});

Screenshot_81

Notice that we're getting a data buffer not the actual text.

To get the text, we can add data.tostring().

Screenshot_82

Or we specify the encoding type.

Screenshot_83

Now let's add a console log outside our function.

Screenshot_84

Do you notice that we got "Log from outside" before hello world?

This demonstrates the asynchronous nature of node. It takes node a split second to read the file, so it just process the second log first.

Each node module also has a synchronous version.

Screenshot_85

Instead of importing the entire fs module, we can also do destructuring.

Screenshot_86

Writing to Files

const { log } = require('console');
const { writeFile, writeFileSync } = require('fs');

const newContent = 'This is some new text'

writeFile('hi.txt', newContent, (err) => {
    if (err) {
        console.error(err);
        return
    }
    console.log('Content Written');
});

Screenshot_87

Screenshot_88

Notice that the content was entirely replaced.

That's the default behaviour of writeFile.

We can change this behaviour by adding a flag.

Screenshot_89

Screenshot_90

We can also use the synchronous version.

Screenshot_91

Screenshot_92

Instead of using flag to append new text, we can use the appendFile option.

Screenshot_93

Screenshot_94

Renaming and Deleting Files

const { log } = require('console');
const { rename } = require('fs');



rename('hi.txt', 'hello.txt', (err) => {
    if (err) {
        console.error(err);
        return
    }
    console.log('File Renamed');
})

Screenshot_95

Screenshot_96

Deleting

const { log } = require('console');
const { unlink } = require('fs');



unlink('hello.txt', (err) => {
    if (err) {
        console.error(err);
        return
    }
    console.log('File Deleted');
})

Screenshot_97

Importing and exporting modules.

server.js:

const addNums = require("./addNums");

const sum = addNums(2, 2)
console.log(sum);

addNums.js:

function addNums(a, b) {
    return a + b;
}

module.exports = addNums;

When you run it:

Screenshot_98

We can also use ES6 syntax.

Screenshot_99

Screenshot_100

Go get our package json:

npm init -y

This gave us a package.json then we added a new line: type: module

Screenshot_101

Basic HTML Content

Now let's use the http module to create an actual webserver.

const http = require('http');

http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain')
    res.write('Hello World');
    res.end();
}).listen(3000, () => console.log('Server running'));

Screenshot_102

Screenshot_103

Screenshot_104

We can refactor the code:

const http = require('http');

const PORT = process.env.PORT || 3000

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain')
    res.write('Hello World');
    res.write('Hello World again');
    res.end("The end");
})

server.listen(PORT, () => console.log(`Server is listening on port ${PORT}`));

Screenshot_105

Screenshot_106

This doesn't look great.

So let's look at sending some HTML.

We just change our content type to text/html, then get rid of res.write.

Then we have to restart our server.

const http = require('http');

const PORT = process.env.PORT || 3000

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html')
    res.end("<h1>Hello World</h1>");
})

server.listen(PORT, () => console.log(`Server is listening on port ${PORT}`));

Screenshot_107

Screenshot_108

Webserver HTML Files

Now we want to send an HTML file and access that file.

So we use fs to access it.


index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
        font-size: 5rem;
        background-color: darkslateblue;
        color: white;
      }
    </style>
    <title>Node.js Crash Course</title>
  </head>
  <body>
    <h1>Home</h1>
  </body>
</html>

Screenshot_109

Screenshot_110

Web Server Basic Routing

If we do http://localhost:3000/about

We'll still get the same file.

Let's build a route to certain URL.

Now if we add this code to our server and refresh the browser, you will get:

Screenshot_111

Screenshot_112

Screenshot_114

Screenshot_113

We can now add this to the server code:

let path = './';
    switch(req.url) {
        case '/':
            path += 'index.html';
            break;
        case '/about':
            path += 'about.html';
            break;
        default:
            path += '404.html';
            break; 
    }

server.js:

const http = require('http');
const fs = require('fs');

const PORT = process.env.PORT || 3000

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html');

    let path = './';
    switch(req.url) {
        case '/':
            path += 'index.html';
            break;
        case '/about':
            path += 'about.html';
            break;
        default:
            path += '404.html';
            break; 
    }

    fs.readFile(path, (err, data) => {
        if (err) {
            console.error(err);
            res.end();
        } else {
            res.write(data); // or res.end(data);
            res.end();
        }
    });
})

server.listen(PORT, () => console.log(`Server is listening on port ${PORT}`));

about.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
        font-size: 5rem;
        background-color: darkslateblue;
        color: white;
      }
    </style>
    <title>Node.js Crash Course</title>
  </head>
  <body>
    <h1>About</h1>
  </body>
</html>

404.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
        font-size: 5rem;
        background-color: darkslateblue;
        color: white;
      }
    </style>
    <title>Node.js Crash Course</title>
  </head>
  <body>
    <h1>404</h1>
  </body>
</html>

Now run the server with node server

Then add the status codes:

const http = require('http');
const fs = require('fs');

const PORT = process.env.PORT || 3000

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html');

    let path = './';
    switch(req.url) {
        case '/':
            path += 'index.html';
            res.statusCode = 200;
            break;
        case '/about':
            path += 'about.html';
            res.statusCode = 200;
            break;
        default:
            path += '404.html';
            res.statusCode = 404;
            break; 
    }

    fs.readFile(path, (err, data) => {
        if (err) {
            console.error(err);
            res.end();
        } else {
            res.write(data); // or res.end(data);
            res.end();
        }
    });
})

server.listen(PORT, () => console.log(`Server is listening on port ${PORT}`));

Web Server Redirects

We can redirect them back to homepage instead of 404.

So the default will be:

default:
            res.setHeader('Location', '/')
            res.statusCode = 301;
            break;

Now when you run the server, any random URl will take you back to the home page.

NPM - Node Package manager

npm init

This creates a package.json

Nodemon

with Nodemon, we don't need to restart our server every time we make changes.

npm i -g nodemon

This will install nodemon globally on our computer.

npm i -D nodemon

This will install nodemon as a dev dependency on our project.

Now look in your package.json.

You will see your node_modules folder now.

Now create a gitignore file to hide your node_modules file

Screenshot_117

If we were to download this from github, we will get a node modules folder.

So i can reinstall the dependencies with

npm i

Now we can edit the scripts in the package.json:

"dev": "nodemon server"
"start": "node server"

Now we can start using nodemon with:

npm run dev

Screenshot_118

Now let's change the default back to 404.

default:
            path += '404.html';
            res.statusCode = 404;
            break;

Save and see that nodemon works.

Deploying to Heroku

We need to first upload to github.

Screenshot_119

Then we need to initialize directory.

Screenshot_120

Then make a commit.

Screenshot_121

Then we'll click the cloud icon below.

Then we'll go to heroku.

Create a new app

Screenshot_122

Create app

Screenshot_123

Choose github

Screenshot_124

Connect to github

Screenshot_125

Connect to Github repo

Screenshot_126

Enable automatic deploy

Screenshot_127

Deployed!!

Screenshot_128