Node.js Fundamentals and Environment Setup
45 minNode.js is a JavaScript runtime built on Chrome's V8 engine that enables server-side JavaScript development.
Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient for data-intensive applications.
The Node.js ecosystem includes npm (Node Package Manager) for package management and a vast library of open-source packages.
Setting up a proper development environment includes Node.js installation, version management with nvm, and IDE configuration.
Node.js's single-threaded event loop handles asynchronous operations efficiently, allowing it to handle many concurrent connections without the overhead of thread management.
Understanding Node.js's module system (CommonJS and ES modules) is fundamental to organizing and sharing code in Node.js applications.
Key Concepts
- Node.js enables JavaScript to run on the server using V8 engine.
- Event-driven, non-blocking I/O model enables high concurrency.
- npm is the package manager for the Node.js ecosystem.
- Node.js uses an event loop for asynchronous operations.
- CommonJS and ES modules are the two module systems in Node.js.
Learning Objectives
Master
- Setting up Node.js development environment
- Understanding Node.js's event-driven architecture
- Using npm for package management
- Working with Node.js core modules (fs, http, path)
Develop
- Server-side JavaScript thinking
- Understanding asynchronous programming
- Node.js ecosystem awareness
Tips
- Use nvm (Node Version Manager) to manage multiple Node.js versions.
- Always initialize projects with npm init to create package.json.
- Use .gitignore to exclude node_modules from version control.
- Set up nodemon for automatic server restarts during development.
Common Pitfalls
- Blocking the event loop with synchronous operations.
- Not handling errors in asynchronous operations properly.
- Installing packages globally when local installation would suffice.
- Forgetting to add node_modules to .gitignore.
Summary
- Node.js enables server-side JavaScript development.
- Event-driven, non-blocking I/O enables high performance.
- npm manages packages and dependencies.
- Understanding the event loop is crucial for Node.js development.
Exercise
Create a basic Node.js project structure with proper package.json configuration and demonstrate basic Node.js concepts.
// package.json
{
"name": "nodejs-fundamentals",
"version": "1.0.0",
"description": "Learning Node.js fundamentals",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest"
},
"keywords": ["nodejs", "javascript", "backend"],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^3.0.1",
"jest": "^29.6.2"
}
}
// index.js - Basic Node.js concepts demonstration
const http = require('http');
const fs = require('fs').promises;
const path = require('path');
class NodeJSFundamentals {
constructor() {
this.server = null;
this.port = process.env.PORT || 3000;
}
// Demonstrate event-driven programming
createEventEmitter() {
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.on('userAction', (action, timestamp) => {
console.log(`User performed: ${action} at ${timestamp}`);
});
myEmitter.on('error', (error) => {
console.error('Error occurred:', error.message);
});
// Emit events
myEmitter.emit('userAction', 'login', new Date().toISOString());
myEmitter.emit('userAction', 'logout', new Date().toISOString());
return myEmitter;
}
// Demonstrate async/await with file operations
async demonstrateAsyncOperations() {
try {
console.log('=== Async Operations Demo ===');
// Create a temporary file
const tempContent = 'Hello from Node.js!';
const tempFile = path.join(__dirname, 'temp.txt');
await fs.writeFile(tempFile, tempContent, 'utf8');
console.log('File created successfully');
// Read the file
const readContent = await fs.readFile(tempFile, 'utf8');
console.log('File content:', readContent);
// Delete the file
await fs.unlink(tempFile);
console.log('File deleted successfully');
} catch (error) {
console.error('Error in async operations:', error.message);
}
}
// Demonstrate streams
demonstrateStreams() {
console.log('\n=== Streams Demo ===');
const { Readable, Writable, Transform } = require('stream');
// Create a readable stream
const readable = new Readable({
read() {}
});
// Create a transform stream
const transform = new Transform({
transform(chunk, encoding, callback) {
const transformed = chunk.toString().toUpperCase();
callback(null, transformed);
}
});
// Create a writable stream
const writable = new Writable({
write(chunk, encoding, callback) {
console.log('Received:', chunk.toString());
callback();
}
});
// Pipe the streams together
readable.pipe(transform).pipe(writable);
// Push data to readable stream
readable.push('hello world');
readable.push('node.js is awesome');
readable.push(null); // End the stream
}
// Demonstrate Buffer operations
demonstrateBuffers() {
console.log('\n=== Buffer Demo ===');
// Create buffers
const buffer1 = Buffer.from('Hello');
const buffer2 = Buffer.from(' World');
// Concatenate buffers
const combined = Buffer.concat([buffer1, buffer2]);
console.log('Combined buffer:', combined.toString());
// Buffer to JSON
const bufferInfo = {
length: combined.length,
content: combined.toString(),
hex: combined.toString('hex'),
base64: combined.toString('base64')
};
console.log('Buffer information:', bufferInfo);
}
// Create a basic HTTP server
createServer() {
this.server = http.createServer((req, res) => {
const { method, url } = req;
console.log(`${method} ${url}`);
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (method === 'OPTIONS') {
res.writeHead(200);
res.end();
return;
}
// Handle different routes
if (method === 'GET' && url === '/') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
message: 'Welcome to Node.js Fundamentals!',
timestamp: new Date().toISOString(),
features: ['Event-driven', 'Non-blocking I/O', 'Streams', 'Buffers']
}));
} else if (method === 'GET' && url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
status: 'healthy',
uptime: process.uptime(),
memory: process.memoryUsage()
}));
} else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Not Found' }));
}
});
this.server.listen(this.port, () => {
console.log(`š Server running at http://localhost:${this.port}`);
console.log('Available endpoints:');
console.log(' GET / - Welcome message');
console.log(' GET /health - Health check');
});
return this.server;
}
// Demonstrate process management
demonstrateProcessManagement() {
console.log('\n=== Process Management Demo ===');
console.log('Process ID:', process.pid);
console.log('Node.js version:', process.version);
console.log('Platform:', process.platform);
console.log('Architecture:', process.arch);
console.log('Current working directory:', process.cwd());
console.log('Environment variables:', Object.keys(process.env).length);
// Handle process signals
process.on('SIGINT', () => {
console.log('\nš Received SIGINT, shutting down gracefully...');
if (this.server) {
this.server.close(() => {
console.log('Server closed');
process.exit(0);
});
} else {
process.exit(0);
}
});
process.on('SIGTERM', () => {
console.log('\nš Received SIGTERM, shutting down gracefully...');
if (this.server) {
this.server.close(() => {
console.log('Server closed');
process.exit(0);
});
} else {
process.exit(0);
}
});
}
async run() {
console.log('šÆ Node.js Fundamentals Demonstration\n');
// Run all demonstrations
this.createEventEmitter();
await this.demonstrateAsyncOperations();
this.demonstrateStreams();
this.demonstrateBuffers();
this.createServer();
this.demonstrateProcessManagement();
console.log('\nā
All demonstrations completed!');
console.log('Press Ctrl+C to stop the server');
}
}
// Run the demonstration
if (require.main === module) {
const demo = new NodeJSFundamentals();
demo.run().catch(console.error);
}
module.exports = NodeJSFundamentals;
Exercise Tips
- Use 'npm init -y' for quick project setup.
- Install nodemon as a dev dependency for auto-restart.
- Test your setup by running 'node index.js'.
- Explore Node.js core modules in the official documentation.