As a program grows, you cannot keep everything in one file. A module is simply a file whose code you can use from other files. Node.js supports the same module system as modern browsers, called ES modules, with import and export. In this lesson you will split code into files, start a proper project with package.json, install your first package and add scripts.
Turn on ES modules
Node can read two module styles. The older one, CommonJS, uses require. The newer one, ES modules, uses import. Most new code and most documentation now use import, so this course does too. To tell Node that your project uses it, create a package.json file. The easiest way is to let npm do it. Run this inside taskapi.
npm init -y
npm pkg set type=module
npm init -y creates package.json with default answers. npm pkg set type=module adds one line, "type": "module", which makes every .js file in the project an ES module. Without that line, using import gives an error such as *Cannot use import statement outside a module*.
Export and import
Create math.js. It shares three things: a named function, a named constant, and a default export.
export function add(a, b) { return a + b; }
export const TAX = 0.18;
export default function price(net) { return Math.round(net * (1 + TAX)); }
A file can have many named exports but only one default export. Now create app.js and use them.
import price, { add, TAX } from './math.js';
import os from 'node:os';
console.log(add(2, 3), TAX, price(100));
console.log(typeof os.cpus().length);
node app.js
5 0.18 118
number
Three rules to remember. First, named imports go inside curly braces and must match the exported names. A default import has no braces, and you choose any name for it. Second, for your own files you must write the file extension, ./math.js, and not just ./math. Browsers and bundlers sometimes let you skip it, but Node does not. Third, paths for your own files start with ./ or ../. A name with no dot, such as express, means a package from node_modules.
Built-in modules and the node: prefix
Node ships with many modules that need no installation, such as node:fs for files, node:path for file paths, node:os for facts about the computer, node:http for servers, node:crypto for security tools and node:test for tests. Write the node: prefix when you import them, as in import os from 'node:os'. It shows the reader, and Node, that this is built in and not a package from the internet.
npm and packages
Most real projects use packages that other people wrote and shared on the npm registry, a huge public library. To add one, use npm install. Try it with the package we will use later.
npm install express
Three things happen. A folder named node_modules appears with the package and everything it needs. package.json gets a dependencies section that lists express with a version. And a file named package-lock.json records the exact versions installed, so every computer gets the same result.
- `node_modules` can be huge. Never edit it by hand and never commit it to git. Add
node_modulesto.gitignore. - `package.json` lists what your project needs. Commit it.
- `package-lock.json` locks exact versions. Commit it too.
- To rebuild
node_moduleson another computer, runnpm installand npm reads the two files.
Some packages are needed only while you develop, such as test or formatting tools. Install those with npm install --save-dev name, and npm lists them under devDependencies. On a server, npm install --omit=dev skips them.
Version numbers
A version such as 5.3.0 has three parts: major, minor and patch. A patch is a bug fix. A minor adds features without breaking old code. A major may break old code. In package.json you will see something like ^5.1.0. The caret means npm may install newer minor and patch versions, but not a new major one. That protects you from surprise breaking changes while still receiving fixes.
npm scripts
The scripts section of package.json holds short names for commands. Add these three. We will create the files they use in later lessons, so do not run them yet.
"scripts": {
"start": "node --env-file=.env server.js",
"dev": "node --watch --env-file=.env server.js",
"test": "node --test"
}
Run npm start or npm test directly. Other names need run, for example npm run dev. The flag --watch restarts the program every time you save a file, so you do not need a separate tool. The flag --env-file=.env loads settings from a file named .env. You will meet it in lesson 11.
Safety with packages
A package is code from strangers, and it runs with your permissions. Choose well-known packages with many users and recent updates. Read the name carefully, because fake packages with names that look like popular ones exist. Run npm audit now and then to see reported problems in what you have installed, and keep dependencies updated.
Your task
- Run
npm init -yandnpm pkg set type=moduleintaskapi. - Create
math.jsandapp.jsas shown and runnode app.js. - Change
TAXto0.05, run again, and check that the price of 100 changes. - Run
npm install express, then look atpackage.jsonand the new files. - Create
.gitignorecontaining the linenode_modules.
How to check it worked
node app.jsprints5 0.18 118and thennumber.package.jsonshows"type": "module"and adependenciessection withexpress.- Deleting
node_modulesand runningnpm installbrings it back.