← Back to JavaScript series
🟒
Node intro
Advanced Β· Prerequisite: 23_Modules_ESM

24. Intro to the Node.js Environment

Node is a JS runtime that runs outside the browser. It powers servers, CLIs, and build tooling.

Node.jsCommonJSESMfile system
Duration
⏱ ~1.5 hours
Level
πŸ“Š Intermediate
Prerequisite
🎯 Lecture 23
OUTCOME
Node is a JS runtime that runs outside the browser. It powers servers, CLIs, and build tooling.

What you'll learn

  • 1Run a JS file with Node.
  • 2Use `process.argv` and `process.env`.
  • 3Read and write files with the `fs` module.
  • 4Tell CommonJS and ESM module systems apart.

Overview

Node is a JS runtime that runs outside the browser. It powers servers, CLIs, and build tooling.

Core Concepts

1. What is Node?

Node is a JS runtime that runs outside the browser. It powers servers, CLIs, and build tooling.

Check it's installed:

bash
node -v

Run a script:

bash
node 01_hello_node.js

2. process β€” arguments and environment variables

javascript
console.log(process.argv);   // ['node path', 'script path', ...extra args]
console.log(process.env.HOME);
bash
node 02_process.js apple 5

3. fs β€” the file system

javascript
import { readFileSync, writeFileSync } from 'node:fs';

writeFileSync('hello.txt', 'Hi from Node');
const text = readFileSync('hello.txt', 'utf-8');
console.log(text);

There are also async versions (`readFile` and the `promises` API).

4. CommonJS vs ESM

Node supports both module systems side by side.

AspectCommonJSESM
File extension`.js` (default)`.mjs` or `"type":"module"`
Export`module.exports = ...``export`
Import`require('./x')``import`
LoadingSynchronousAsynchronous
javascript
// CommonJS (legacy.cjs)
module.exports = { hi: () => 'hi' };
const { hi } = require('./legacy');

// ESM (modern.mjs)
export const hi = () => 'hi';
import { hi } from './modern.mjs';

New code should use ESM.

Examples

FileWhat it covers
01_hello_node.jsFirst node run
02_process.jsargv / env
03_fs_basic.jsReading and writing files
04_commonjs_esm.mjsComparing the two module systems

src/01_hello_node.js

javascript
/**
 * Your first node run
 * Run: node 01_hello_node.js
 */
console.log('Hello, Node!');
console.log('Node version:', process.version);
console.log('Platform:', process.platform);

src/02_process.js

javascript
/**
 * process.argv and process.env
 * Example: node 02_process.js apple 5
 */
const [, , fruit, countStr] = process.argv;
const count = Number(countStr ?? 1);

console.log(`args: ${fruit} Γ— ${count}`);
console.log('full argv:', process.argv);
console.log('HOME env var:', process.env.HOME ?? process.env.USERPROFILE);

src/03_fs_basic.js

javascript
/**
 * Read and write a text file with fs
 */
const { writeFileSync, readFileSync, existsSync } = require('node:fs');

const path = 'hello.txt';
writeFileSync(path, 'Hi from Node\nSecond line');

if (existsSync(path)) {
  const text = readFileSync(path, 'utf-8');
  console.log('file contents:');
  console.log(text);
}

src/04_commonjs_esm.mjs

mjs
/**
 * ESM style β€” .mjs extension
 * Comments compare CommonJS and ESM
 */
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';

// In CommonJS, __filename and __dirname are provided automatically,
// but in ESM you have to build them yourself.
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

console.log('this file:', __filename);
console.log('this directory:', __dirname);

// CommonJS:
//   const { readFileSync } = require('node:fs');
//   module.exports = { ... };
//
// ESM:
//   import { readFileSync } from 'node:fs';
//   export { ... };

export const hello = () => 'hello from ESM';
console.log(hello());

Common Mistakes

  1. Using browser APIs (`window`, `document`) in Node.
  2. Calling `require` inside ESM (or `import` inside CommonJS).
  3. Forgetting `./` on a relative path.
  4. Losing track of the working directory and not finding files created by `fs.writeFileSync`.
  5. Hard-coding environment values directly in your code.

FAQ

Q1. Which Node version should I use?

The latest LTS (even-numbered major). **Q2. What about .env files?** A. Node 20+ has `--env-file`; older versions use the `dotenv` package. **Q3. What's the working directory?** A. `process.cwd()`. It's usually where you ran the command.

Practice

Build a small tool that uses command-line arguments plus the filesystem.

homework/README.md

## Homework 1 (CommonJS) β€” Take two numbers from the command line and print their sum. `node homework_01.js 3 5` β†’ `sum: 8`

## Homework 2 (ESM) β€” Append the given string to `note.txt` as a new line. `node homework_02.mjs "today's note"` β€” then check the file contents.

homework/answer/homework_01.js

javascript
/**
 * Homework 1: add two CLI arguments (CommonJS)
 * Run: node homework_01.js 3 5
 */
const [, , aStr, bStr] = process.argv;
const a = Number(aStr);
const b = Number(bStr);

if (Number.isNaN(a) || Number.isNaN(b)) {
  console.error('Please pass two numbers.');
  process.exit(1);
}

console.log(`sum: ${a + b}`);

homework/answer/homework_02.mjs

mjs
/**
 * Homework 2: append a note to note.txt (ESM)
 * Run: node homework_02.mjs "today's note"
 */
import { appendFileSync, readFileSync, existsSync } from 'node:fs';

const text = process.argv[2];
if (!text) {
  console.error('Please pass the text to append.');
  process.exit(1);
}

const path = 'note.txt';
appendFileSync(path, text + '\n');

console.log('--- current note.txt ---');
console.log(existsSync(path) ? readFileSync(path, 'utf-8') : '(empty)');

Next Lecture

[25_Intro_to_npm](../25_npm_μž…λ¬Έ/)

Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub β†—