CSCI 4513
Week 13, Lecture 23
From his throne Hlidskjalf, Odin can observe all nine realms and respond to any event, just as a Node.js server listens for requests from anywhere in the world.
The Tale:
High in Asgard stands Hlidskjalf, Odin's magnificent throne from which he surveys all the nine realms. From this elevated seat, nothing escapes his noticeβhe sees events in Midgard (the mortal world), conflicts in Jotunheim (land of giants), celebrations in Alfheim (realm of elves), and activities across all other realms simultaneously.
When mortals pray, when giants scheme, when events unfold anywhere in the cosmos, Odin perceives them from Hlidskjalf. He doesn't merely watchβhe listens, processes information, and can dispatch responses through his ravens Huginn (Thought) and Muninn (Memory), who carry messages and gather intelligence across the realms. This high seat serves as the ultimate server, constantly running, always listening, ready to process requests and send responses to any corner of the nine worlds.
// Hlidskjalf - The server that listens to all realms
const http = require('http');
const server = http.createServer((request, response) => {
// Like Odin processing requests from across the nine realms
console.log(`Request from: ${request.url}`);
// Dispatch response (like sending the ravens)
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('<h1>Response from Hlidskjalf</h1>');
});
// Start listening on port 3000 (establish the high seat)
server.listen(3000, () => {
console.log('Hlidskjalf established on port 3000...');
console.log('Now observing all realms for requests...');
});
The backend handles:
Data storage, business logic, authentication, server-side rendering, API requests
Client (Browser) Server (Node.js)
| |
| 1. HTTP Request |
| -------------------------> |
| (GET /users) |
| |
| 2. Process Request
| 3. Query Database
| 4. Prepare Response
| |
| 5. HTTP Response |
| <------------------------- |
| (JSON data) |
| |
Key Point: Node.js lets you use JavaScript for backend development!
// β Browser APIs - NOT available in Node
window.alert('Hello');
document.querySelector('#app');
localStorage.setItem('key', 'value');
fetch('https://api.example.com'); // Available but different
// β
Node.js APIs - NOT available in browser
const fs = require('fs');
const http = require('http');
const path = require('path');
process.env.NODE_ENV;
// β
Available in BOTH
console.log('Hello');
setTimeout(() => {}, 1000);
const data = JSON.parse('{"key": "value"}');
1. Download from: nodejs.org
2. Choose version:
3. Verify installation:
node --version
npm --version
// Method 1: REPL (Read-Eval-Print Loop)
// Just type 'node' in terminal
$ node
> console.log('Hello from Node!')
Hello from Node!
> 2 + 2
4
> .exit // or Ctrl+C twice
// Method 2: Run a file
// Create app.js, then run:
$ node app.js
// Method 3: Run with nodemon (auto-restart on changes)
$ npm install -g nodemon
$ nodemon app.js
// app.js
console.log('Hello from Node.js!');
const greeting = (name) => {
return `Welcome, ${name}!`;
};
console.log(greeting('Alice'));
console.log(greeting('Bob'));
// Run with: node app.js
Output:
Hello from Node.js!
Welcome, Alice!
Welcome, Bob!
// Built-in modules
const fs = require('fs');
const http = require('http');
const path = require('path');
// npm packages (install first with npm install)
const express = require('express');
const lodash = require('lodash');
// Your own modules
const myModule = require('./myModule');
const utils = require('./utils/helpers');
// Specific exports
const { readFile } = require('fs');
const { join } = require('path');
// math.js - Export functions
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const multiply = (a, b) => a * b;
module.exports = {
add,
subtract,
multiply
};
// app.js - Import and use
const math = require('./math');
console.log(math.add(5, 3)); // 8
console.log(math.multiply(4, 2)); // 8
Read and write files from your Node application
const fs = require('fs');
// Read file (synchronous - blocks execution)
const data = fs.readFileSync('input.txt', 'utf8');
console.log(data);
// Read file (asynchronous - doesn't block)
fs.readFile('input.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log(data);
});
// Modern: Promises version
const fsPromises = require('fs').promises;
const data = await fsPromises.readFile('input.txt', 'utf8');
const fs = require('fs');
// Write file (replaces existing content)
fs.writeFile('output.txt', 'Hello, World!', (err) => {
if (err) {
console.error('Error writing file:', err);
return;
}
console.log('File written successfully!');
});
// Append to file
fs.appendFile('log.txt', 'New log entry\n', (err) => {
if (err) throw err;
console.log('Log updated!');
});
// Synchronous version
fs.writeFileSync('output.txt', 'Hello, World!');
const fs = require('fs');
const path = require('path');
// Read directory contents
fs.readdir('./files', (err, files) => {
if (err) throw err;
console.log(files); // Array of filenames
});
// Create directory
fs.mkdir('./new-folder', (err) => {
if (err) throw err;
console.log('Directory created!');
});
// Check if file/directory exists
if (fs.existsSync('./my-file.txt')) {
console.log('File exists!');
}
const http = require('http');
// Create a server
const server = http.createServer((request, response) => {
// This function runs for every incoming request
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end('<h1>Hello from Node.js Server!</h1>');
});
// Start listening on port 3000
server.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
Visit http://localhost:3000 in your browser!
const http = require('http');
const server = http.createServer((req, res) => {
// Request object properties
console.log('Method:', req.method); // GET, POST, etc.
console.log('URL:', req.url); // /about, /users, etc.
console.log('Headers:', req.headers); // Request headers
// Response methods
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('<h1>Welcome</h1>');
res.write('<p>Path: ' + req.url + '</p>');
res.end();
});
server.listen(3000);
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
if (req.url === '/') {
res.end('<h1>Home Page</h1>');
} else if (req.url === '/about') {
res.end('<h1>About Page</h1>');
} else if (req.url === '/contact') {
res.end('<h1>Contact Page</h1>');
} else {
res.writeHead(404);
res.end('<h1>404 - Page Not Found</h1>');
}
});
server.listen(3000);
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer((req, res) => {
let filePath = './public' + req.url;
if (filePath === './public/') {
filePath = './public/index.html';
}
fs.readFile(filePath, (err, content) => {
if (err) {
res.writeHead(404);
res.end('<h1>404 - File Not Found</h1>');
} else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content);
}
});
});
server.listen(3000);
const path = require('path');
// Get file extension
const extname = path.extname(filePath);
// Set appropriate content type
let contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
case '.json':
contentType = 'application/json';
break;
case '.png':
contentType = 'image/png';
break;
}
res.writeHead(200, { 'Content-Type': contentType });
// app.js
const calculate = (a, b) => {
debugger; // Program pauses here when debugging
const result = a + b;
return result;
};
console.log(calculate(5, 3));
// Run with debugger:
// $ node inspect app.js
// Or in Chrome DevTools:
// $ node --inspect-brk app.js
// Then open chrome://inspect in Chrome
1. Set breakpoints: Click left of line numbers
2. Press F5 to start debugging
3. Use debug controls:
4. Inspect variables in the sidebar
process.env.env files for local developmentβ οΈ Never commit .env files to git! Add to .gitignore
// Access environment variables
const port = process.env.PORT || 3000;
const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;
console.log(`Server will run on port ${port}`);
// Set when running (Linux/Mac):
$ PORT=8080 node app.js
// Set when running (Windows):
$ set PORT=8080 && node app.js
// 1. Install dotenv
$ npm install dotenv
// 2. Create .env file
PORT=3000
DATABASE_URL=mongodb://localhost:27017/myapp
API_KEY=your_secret_api_key_here
// 3. Load in your app
require('dotenv').config();
const port = process.env.PORT;
const dbUrl = process.env.DATABASE_URL;
// 4. Add .env to .gitignore
echo ".env" >> .gitignore
Build a simple website with Node.js:
No frameworks! Pure Node.js only
basic-informational-site/
βββ index.js # Server file
βββ public/
β βββ index.html # Home page
β βββ about.html # About page
β βββ contact-me.html # Contact page
β βββ 404.html # 404 error page
β βββ styles.css # Stylesheet
βββ .gitignore
// index.js
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer((req, res) => {
// Your code here:
// 1. Determine which file to serve based on req.url
// 2. Read the file with fs.readFile()
// 3. Set appropriate headers
// 4. Send the file content or 404
});
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
π Next Class: Express.js - A better way to build servers
π Homework: Basic Informational Site Project
π― Coming Soon: Express framework will make this much easier!