24. Intro to the Node.js Environment
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:
node -vRun a script:
node 01_hello_node.js2. process β arguments and environment variables
console.log(process.argv); // ['node path', 'script path', ...extra args]
console.log(process.env.HOME);node 02_process.js apple 53. fs β the file system
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.
| Aspect | CommonJS | ESM |
|---|---|---|
| File extension | `.js` (default) | `.mjs` or `"type":"module"` |
| Export | `module.exports = ...` | `export` |
| Import | `require('./x')` | `import` |
| Loading | Synchronous | Asynchronous |
// 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
| File | What it covers |
|---|---|
| 01_hello_node.js | First node run |
| 02_process.js | argv / env |
| 03_fs_basic.js | Reading and writing files |
| 04_commonjs_esm.mjs | Comparing the two module systems |
src/01_hello_node.js
/**
* 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
/**
* 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
/**
* 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
/**
* 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
- Using browser APIs (`window`, `document`) in Node.
- Calling `require` inside ESM (or `import` inside CommonJS).
- Forgetting `./` on a relative path.
- Losing track of the working directory and not finding files created by `fs.writeFileSync`.
- 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
/**
* 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
/**
* 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_μ λ¬Έ/)
All lecture materials and example code are openly available on GitHub.
View on GitHub β