Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
Node 18.11+ has built-in hot-reload (node --watch) and Node 20.6+ has built-in .env file loading (--env-file). You no longer need nodemon, dotenv, or a custom dev script. This collapses the 2026 dev loop to one command. Knowing what's in modern Node (and what's NOT — TS still needs a transpiler/loader, but that's coming) keeps you out of the npm-package treadmill.
A good development server loop dramatically shortens the feedback cycle: you save a file and the server restarts before your browser tab has finished switching. Node 22 ships --watch mode natively, and tsx adds TypeScript transpilation on top with no build step — meaning your TypeScript source runs directly without a separate compile pass. Combining --env-file (Node 20.6+) with watch mode gives you a zero-dependency dev server that picks up environment variable changes and file changes alike, eliminating the dotenv boilerplate that cluttered earlier Node.js projects.
.env and a small server.js that prints process.env.PORT. Run with node --env-file=.env. No dotenv package needed.--watch and edit the file while it's running. Note the auto-restart.--watch-path=src to limit which files trigger restart. Useful when node_modules changes shouldn't restart."dev": "node --watch --env-file=.env src/server.js" to package.json scripts. Now pnpm dev is your loop.Use these three in order. Each builds on the one before.
In one paragraph, explain what `--watch` and `--env-file` collapsed in the JS ecosystem (which packages we no longer need).
How does `node --watch` actually work — fs.watch under the hood, what it watches, when it restarts vs reloads in-process?
When does `node --watch` lose to nodemon, and when does it lose to a real bundler with HMR (esbuild, vite-node)? Pick a 2026 default for a backend project.
# .env
PORT=3000
DATABASE_URL=postgres://localhost/myapp
# src/server.js
const port = process.env.PORT || 8080;
console.log("server up on", port, "DB:", process.env.DATABASE_URL);
# old way (nodemon + dotenv):
# npm install --save-dev nodemon dotenv
# require("dotenv").config(); ...
# new way (Node 20.6+ builtin):
$ node --watch --env-file=.env src/server.js
[restarting due to changes...]
server up on 3000 DB: postgres://localhost/myapp
# multiple env files:
$ node --watch --env-file=.env --env-file=.env.local src/server.js
# scripts in package.json:
"scripts": {
"dev": "node --watch --env-file=.env src/server.js"
}node main.js