From 39a9e6dde39c9367d25e4f433a16e49d8692bc25 Mon Sep 17 00:00:00 2001 From: Nitin <150040530+nitin-is-me@users.noreply.github.com> Date: Wed, 11 Feb 2026 10:29:04 +0530 Subject: [PATCH] fix: add missing ESM/CJS tabs with their examples in Learn section --- .../event-loop-timers-and-nexttick.md | 86 ++++++++++++++++++- ...-asynchronous-programming-and-callbacks.md | 17 +++- .../overview-of-blocking-vs-non-blocking.md | 80 +++++++++++++++-- ...-read-environment-variables-from-nodejs.md | 18 +++- .../memory/understanding-and-tuning-memory.md | 8 ++ .../diagnostics/memory/using-gc-traces.md | 27 ++++++ .../diagnostics/memory/using-heap-snapshot.md | 9 +- .../writing-files-with-nodejs.md | 73 ++++++++++++++-- 8 files changed, 298 insertions(+), 20 deletions(-) diff --git a/apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md b/apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md index f8468941682fe..2f625ed7df7f9 100644 --- a/apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md +++ b/apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md @@ -110,7 +110,7 @@ For example, say you schedule a timeout to execute after a 100 ms threshold, then your script starts asynchronously reading a file which takes 95 ms: -```js +```cjs const fs = require('node:fs'); function someAsyncOperation(callback) { @@ -137,6 +137,33 @@ someAsyncOperation(() => { }); ``` +```mjs +import fs from 'node:fs'; + +function someAsyncOperation(callback) { + // Assume this takes 95ms to complete + fs.readFile('/path/to/file', callback); +} + +const timeoutScheduled = Date.now(); + +setTimeout(() => { + const delay = Date.now() - timeoutScheduled; + + console.log(`${delay}ms have passed since I was scheduled`); +}, 100); + +// do someAsyncOperation which takes 95 ms to complete +someAsyncOperation(() => { + const startCallback = Date.now(); + + // do something that will take 10ms... + while (Date.now() - startCallback < 10) { + // do nothing + } +}); +``` + When the event loop enters the **poll** phase, it has an empty queue (`fs.readFile()` has not completed), so it will wait for the number of ms remaining until the soonest timer's threshold is reached. While it is @@ -259,7 +286,7 @@ timeout However, if you move the two calls within an I/O cycle, the immediate callback is always executed first: -```js +```cjs // timeout_vs_immediate.js const fs = require('node:fs'); @@ -273,6 +300,20 @@ fs.readFile(__filename, () => { }); ``` +```mjs +// timeout_vs_immediate.js +import fs from 'node:fs'; + +fs.readFile(import.meta.filename, () => { + setTimeout(() => { + console.log('timeout'); + }, 0); + setImmediate(() => { + console.log('immediate'); + }); +}); +``` + ```bash $ node timeout_vs_immediate.js immediate @@ -453,7 +494,7 @@ allowing the connection event to be fired before the listening event. Another example is extending an `EventEmitter` and emitting an event from within the constructor: -```js +```cjs const EventEmitter = require('node:events'); class MyEmitter extends EventEmitter { @@ -469,13 +510,30 @@ myEmitter.on('event', () => { }); ``` +```mjs +import EventEmitter from 'node:events'; + +class MyEmitter extends EventEmitter { + constructor() { + super(); + this.emit('event'); + } +} + +const myEmitter = new MyEmitter(); +myEmitter.on('event', () => { + console.log('an event occurred!'); +}); +``` + You can't emit an event from the constructor immediately + because the script will not have processed to the point where the user assigns a callback to that event. So, within the constructor itself, you can use `process.nextTick()` to set a callback to emit the event after the constructor has finished, which provides the expected results: -```js +```cjs const EventEmitter = require('node:events'); class MyEmitter extends EventEmitter { @@ -495,5 +553,25 @@ myEmitter.on('event', () => { }); ``` +```mjs +import EventEmitter from 'node:events'; + +class MyEmitter extends EventEmitter { + constructor() { + super(); + + // use nextTick to emit the event once a handler is assigned + process.nextTick(() => { + this.emit('event'); + }); + } +} + +const myEmitter = new MyEmitter(); +myEmitter.on('event', () => { + console.log('an event occurred!'); +}); +``` + [libuv]: https://libuv.org/ [REPL]: https://nodejs.org/api/repl.html#repl_repl diff --git a/apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md b/apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md index 11b7bda915516..fc9c2755f1a48 100644 --- a/apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md +++ b/apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md @@ -96,7 +96,7 @@ How do you handle errors with callbacks? One very common strategy is to use what If there is no error, the object is `null`. If there is an error, it contains some description of the error and other information. -```js +```cjs const fs = require('node:fs'); fs.readFile('/file.json', (err, data) => { @@ -111,6 +111,21 @@ fs.readFile('/file.json', (err, data) => { }); ``` +```mjs +import fs from 'node:fs'; + +fs.readFile('/file.json', (err, data) => { + if (err) { + // handle error + console.log(err); + return; + } + + // no errors, process data + console.log(data); +}); +``` + ### The problem with callbacks Callbacks are great for simple cases! diff --git a/apps/site/pages/en/learn/asynchronous-work/overview-of-blocking-vs-non-blocking.md b/apps/site/pages/en/learn/asynchronous-work/overview-of-blocking-vs-non-blocking.md index e516cd6f8f3c8..deaaa24791d91 100644 --- a/apps/site/pages/en/learn/asynchronous-work/overview-of-blocking-vs-non-blocking.md +++ b/apps/site/pages/en/learn/asynchronous-work/overview-of-blocking-vs-non-blocking.md @@ -39,15 +39,21 @@ execute **asynchronously**. Using the File System module as an example, this is a **synchronous** file read: -```js +```cjs const fs = require('node:fs'); const data = fs.readFileSync('/file.md'); // blocks here until file is read ``` +```mjs +import fs from 'node:fs'; + +const data = fs.readFileSync('/file.md'); // blocks here until file is read +``` + And here is an equivalent **asynchronous** example: -```js +```cjs const fs = require('node:fs'); fs.readFile('/file.md', (err, data) => { @@ -57,6 +63,16 @@ fs.readFile('/file.md', (err, data) => { }); ``` +```mjs +import fs from 'node:fs'; + +fs.readFile('/file.md', (err, data) => { + if (err) { + throw err; + } +}); +``` + The first example appears simpler than the second but has the disadvantage of the second line **blocking** the execution of any additional JavaScript until the entire file is read. Note that in the synchronous version if an error is @@ -66,7 +82,7 @@ shown. Let's expand our example a little bit: -```js +```cjs const fs = require('node:fs'); const data = fs.readFileSync('/file.md'); // blocks here until file is read @@ -74,9 +90,17 @@ console.log(data); moreWork(); // will run after console.log ``` +```mjs +import fs from 'node:fs'; + +const data = fs.readFileSync('/file.md'); // blocks here until file is read +console.log(data); +moreWork(); // will run after console.log +``` + And here is a similar, but not equivalent asynchronous example: -```js +```cjs const fs = require('node:fs'); fs.readFile('/file.md', (err, data) => { @@ -89,6 +113,19 @@ fs.readFile('/file.md', (err, data) => { moreWork(); // will run before console.log ``` +```mjs +import fs from 'node:fs'; + +fs.readFile('/file.md', (err, data) => { + if (err) { + throw err; + } + + console.log(data); +}); +moreWork(); // will run before console.log +``` + In the first example above, `console.log` will be called before `moreWork()`. In the second example `fs.readFile()` is **non-blocking** so JavaScript execution can continue and `moreWork()` will be called first. The ability to run @@ -118,7 +155,7 @@ threads may be created to handle concurrent work. There are some patterns that should be avoided when dealing with I/O. Let's look at an example: -```js +```cjs const fs = require('node:fs'); fs.readFile('/file.md', (err, data) => { @@ -131,12 +168,25 @@ fs.readFile('/file.md', (err, data) => { fs.unlinkSync('/file.md'); ``` +```mjs +import fs from 'node:fs'; + +fs.readFile('/file.md', (err, data) => { + if (err) { + throw err; + } + + console.log(data); +}); +fs.unlinkSync('/file.md'); +``` + In the above example, `fs.unlinkSync()` is likely to be run before `fs.readFile()`, which would delete `file.md` before it is actually read. A better way to write this, which is completely **non-blocking** and guaranteed to execute in the correct order is: -```js +```cjs const fs = require('node:fs'); fs.readFile('/file.md', (readFileErr, data) => { @@ -154,6 +204,24 @@ fs.readFile('/file.md', (readFileErr, data) => { }); ``` +```mjs +import fs from 'node:fs'; + +fs.readFile('/file.md', (readFileErr, data) => { + if (readFileErr) { + throw readFileErr; + } + + console.log(data); + + fs.unlink('/file.md', unlinkErr => { + if (unlinkErr) { + throw unlinkErr; + } + }); +}); +``` + The above places a **non-blocking** call to `fs.unlink()` within the callback of `fs.readFile()` which guarantees the correct order of operations. diff --git a/apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md b/apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md index 9afb46f342ba1..89bda392e45d2 100644 --- a/apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md +++ b/apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md @@ -80,7 +80,7 @@ Because this method is invoked post-initialization, the setting of startup-relat PORT=1234 ``` -```js +```cjs const { loadEnvFile } = require('node:process'); // Loads environment variables from the default .env file @@ -89,9 +89,23 @@ loadEnvFile(); console.log(process.env.PORT); // Logs '1234' ``` +```mjs +import { loadEnvFile } from 'node:process'; + +// Loads environment variables from the default .env file +loadEnvFile(); + +console.log(process.env.PORT); // Logs '1234' +``` + You can also specify a custom path: -```js +```cjs const { loadEnvFile } = require('node:process'); loadEnvFile('./config/.env'); ``` + +```mjs +import { loadEnvFile } from 'node:process'; +loadEnvFile('./config/.env'); +``` diff --git a/apps/site/pages/en/learn/diagnostics/memory/understanding-and-tuning-memory.md b/apps/site/pages/en/learn/diagnostics/memory/understanding-and-tuning-memory.md index ae39c74851ef9..30ddfb6f3565e 100644 --- a/apps/site/pages/en/learn/diagnostics/memory/understanding-and-tuning-memory.md +++ b/apps/site/pages/en/learn/diagnostics/memory/understanding-and-tuning-memory.md @@ -36,6 +36,14 @@ const heapSizeInGB = heap_size_limit / (1024 * 1024 * 1024); console.log(`${heapSizeInGB} GB`); ``` +```mjs +import v8 from 'node:v8'; +const { heap_size_limit } = v8.getHeapStatistics(); +const heapSizeInGB = heap_size_limit / (1024 * 1024 * 1024); + +console.log(`${heapSizeInGB} GB`); +``` + This will output the maximum heap size in gigabytes, which is based on your system's available memory. ### The Stack diff --git a/apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md b/apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md index 19b1b66f97a8d..14b4c81155df3 100644 --- a/apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md +++ b/apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md @@ -359,6 +359,33 @@ obs.observe({ entryTypes: ['gc'] }); obs.disconnect(); ``` +```mjs +import { PerformanceObserver } from 'node:perf_hooks'; + +// Create a performance observer +const obs = new PerformanceObserver(list => { + const entry = list.getEntries()[0]; + /* + The entry is an instance of PerformanceEntry containing + metrics of a single garbage collection event. + For example: + PerformanceEntry { + name: 'gc', + entryType: 'gc', + startTime: 2820.567669, + duration: 1.315709, + kind: 1 + } + */ +}); + +// Subscribe to notifications of GCs +obs.observe({ entryTypes: ['gc'] }); + +// Stop subscription +obs.disconnect(); +``` + ### Examining a trace with performance hooks You can get GC statistics as [PerformanceEntry][] from the callback in diff --git a/apps/site/pages/en/learn/diagnostics/memory/using-heap-snapshot.md b/apps/site/pages/en/learn/diagnostics/memory/using-heap-snapshot.md index dbe951184d81d..a74732bab2796 100644 --- a/apps/site/pages/en/learn/diagnostics/memory/using-heap-snapshot.md +++ b/apps/site/pages/en/learn/diagnostics/memory/using-heap-snapshot.md @@ -73,8 +73,13 @@ For details, see the latest documentation of [heapsnapshot-signal flag][]. If you need a snapshot from a working process, like an application running on a server, you can implement getting it using: -```js -require('v8').writeHeapSnapshot(); +```cjs +require('node:v8').writeHeapSnapshot(); +``` + +```mjs +import { writeHeapSnapshot } from 'node:v8'; +writeHeapSnapshot(); ``` Check [`writeHeapSnapshot` docs][] for file name options. diff --git a/apps/site/pages/en/learn/manipulating-files/writing-files-with-nodejs.md b/apps/site/pages/en/learn/manipulating-files/writing-files-with-nodejs.md index ffd643eae6a75..7deac9680aef7 100644 --- a/apps/site/pages/en/learn/manipulating-files/writing-files-with-nodejs.md +++ b/apps/site/pages/en/learn/manipulating-files/writing-files-with-nodejs.md @@ -10,7 +10,7 @@ authors: flaviocopes, MylesBorins, fhemberger, LaRuaNa, ahmadawais, clean99, ovf The easiest way to write to files in Node.js is to use the `fs.writeFile()` API. -```js +```cjs const fs = require('node:fs'); const content = 'Some content!'; @@ -24,11 +24,25 @@ fs.writeFile('/Users/joe/test.txt', content, err => { }); ``` +```mjs +import fs from 'node:fs'; + +const content = 'Some content!'; + +fs.writeFile('/Users/joe/test.txt', content, err => { + if (err) { + console.error(err); + } else { + // file written successfully + } +}); +``` + ### Writing a file synchronously Alternatively, you can use the synchronous version `fs.writeFileSync()`: -```js +```cjs const fs = require('node:fs'); const content = 'Some content!'; @@ -41,9 +55,22 @@ try { } ``` +```mjs +import fs from 'node:fs'; + +const content = 'Some content!'; + +try { + fs.writeFileSync('/Users/joe/test.txt', content); + // file written successfully +} catch (err) { + console.error(err); +} +``` + You can also use the promise-based `fsPromises.writeFile()` method offered by the `fs/promises` module: -```js +```cjs const fs = require('node:fs/promises'); async function example() { @@ -58,6 +85,17 @@ async function example() { example(); ``` +```mjs +import fs from 'node:fs/promises'; + +try { + const content = 'Some content!'; + await fs.writeFile('/Users/joe/test.txt', content); +} catch (err) { + console.log(err); +} +``` + By default, this API will **replace the contents of the file** if it does already exist. **You can modify the default by specifying a flag:** @@ -85,7 +123,7 @@ Appending to files is handy when you don't want to overwrite a file with new con A handy method to append content to the end of a file is `fs.appendFile()` (and its `fs.appendFileSync()` counterpart): -```js +```cjs const fs = require('node:fs'); const content = 'Some content!'; @@ -99,11 +137,25 @@ fs.appendFile('file.log', content, err => { }); ``` +```mjs +import fs from 'node:fs'; + +const content = 'Some content!'; + +fs.appendFile('file.log', content, err => { + if (err) { + console.error(err); + } else { + // done! + } +}); +``` + #### Example with Promises Here is a `fsPromises.appendFile()` example: -```js +```cjs const fs = require('node:fs/promises'); async function example() { @@ -117,3 +169,14 @@ async function example() { example(); ``` + +```mjs +import fs from 'node:fs/promises'; + +try { + const content = 'Some content!'; + await fs.appendFile('/Users/joe/test.txt', content); +} catch (err) { + console.log(err); +} +```