Node.js Development

Understanding Modules and NPM in Node.js: A Comprehensive Guide

By the Domain India teamPublished 9 min read
Knowledge base article
Contents (8 sections)

Every Node.js project is built from modules: your own files, the modules built into Node, and packages from the npm registry. Knowing how modules load and how npm manages packages saves you from the most common "Cannot find module" and version-mismatch errors. This guide covers both module systems, the npm commands you use every day, and how to run a Node.js project on Domain India.

Key takeaways

Node.js has two module systems: CommonJS (require and module.exports) and ES modules (import and export), which are the standard for new code. Set "type": "module" in package.json to use ES modules. Manage packages with npm, commit package-lock.json, and use npm ci for clean, repeatable installs. Use Node.js 22 or 24; Node.js 20 reached end of life in April 2026.

1. What a module is

A module is a file whose variables and functions stay private unless you export them. Node.js has three kinds:

  • Your own modules: any .js, .mjs or .cjs file in your project, loaded with a relative path such as ./math.js.
  • Core modules: built into Node, such as fs, path, http and crypto. Load them with the node: prefix, for example node:fs, so nobody can confuse them with an npm package of the same name.
  • Packages: code from the npm registry, installed into node_modules and loaded by name, such as express.

2. CommonJS: require and module.exports

CommonJS is Node's original module system, and a great deal of existing code still uses it.

javascript
// math.cjs
function add(a, b) {
  return a + b;
}
module.exports = { add };
javascript
// app.cjs
const { add } = require('./math.cjs');
const fs = require('node:fs');

console.log(add(5, 3)); // 8

require loads a module synchronously the first time and caches it, so every later require of the same file returns the same object. Assign to module.exports (or add properties to exports), but never replace exports itself: exports = {...} silently exports nothing.

3. ES modules: import and export

ES modules (ESM) are the JavaScript standard, used in browsers and in modern Node.js. Turn them on for a whole project by adding "type": "module" to package.json, or name individual files .mjs.

javascript
// math.js
export const add = (a, b) => a + b;
export default function multiply(a, b) {
  return a * b;
}
javascript
// app.js
import multiply, { add } from './math.js';
import { readFile } from 'node:fs/promises';

const text = await readFile('notes.txt', 'utf8'); // top-level await works in ESM
console.log(add(5, 3), multiply(5, 3));

Three rules catch most people out:

  1. Write the file extension in relative imports: ./math.js, not ./math.
  2. __dirname and __filename don't exist in ES modules. Use import.meta.dirname and import.meta.filename in current Node versions.
  3. Load code lazily with import(), which returns a promise, for example const { default: sharp } = await import('sharp');. It works in both module systems.
QuestionCommonJSES modules
Syntaxrequire, module.exportsimport, export
Enable withDefault, or .cjs files"type": "module", or .mjs files
LoadingSynchronousAsynchronous; top-level await allowed
Use forExisting projects and older packagesAll new code

Mixing the two works in one direction easily: an ES module can import a CommonJS package. Recent Node versions can also require() an ES module, as long as it doesn't use top-level await.

4. npm and package.json

npm installs with Node.js. It downloads packages from the npm registry and records them in two files:

  • package.json lists your project's name, scripts and the version ranges of the packages it depends on. You edit it.
  • package-lock.json records the exact version of every package installed, including packages your packages depend on. npm writes it. Commit it to Git, so every machine installs exactly the same versions.

Never commit node_modules; add it to .gitignore and reinstall from the lock file instead.

5. The npm commands you use every day

bash
npm init -y                 # create package.json with defaults
npm install express         # add a dependency
npm install -D eslint       # add a devDependency (only needed while developing)
npm uninstall express       # remove a package
npm outdated                # list packages with newer versions
npm update                  # update within the ranges in package.json
npm ci                      # clean install exactly what package-lock.json says
npm ci --omit=dev           # the same, without devDependencies (for production)
npm run build               # run a script from package.json
npx create-vite@latest      # run a package's command without installing it globally

Use npm install while you develop and change dependencies. Use npm ci on servers and in CI: it deletes node_modules, installs exactly what the lock file says, and fails if the lock file and package.json disagree.

Scripts live in package.json:

json
{
  "type": "module",
  "scripts": {
    "start": "node server.js",
    "dev": "node --watch server.js",
    "test": "node --test"
  }
}

node --watch restarts on file changes and node --test runs Node's built-in test runner, so small projects no longer need extra tools for either.

6. Versions and semantic versioning

npm packages use semantic versioning, MAJOR.MINOR.PATCH: a major release may break your code, a minor one adds features, and a patch fixes bugs.

Range in package.jsonAcceptsExample for 5.1.0
^5.1.0 (npm's default)Minor and patch updates5.1.1, 5.2.0, not 6.0.0
~5.1.0Patch updates only5.1.1, not 5.2.0
5.1.0Exactly this version5.1.0 only

Dependencies are needed to run your app; devDependencies only to build or test it. peerDependencies are for plugins that expect the host package to be installed, and npm installs them automatically.

7. Keep your dependencies safe

Compromised and malicious packages on the npm registry are a real risk; several popular packages were hijacked in 2025.

  • Run npm audit regularly, and npm audit fix for safe fixes. Read what npm audit fix --force would change before you run it, because it can install breaking major versions.
  • Install from the lock file with npm ci, so a new, unreviewed version never slips in during a deploy.
  • Add packages deliberately. Check the package's weekly downloads, maintainers and repository, and watch for look-alike names.
  • Turn on two-factor authentication on your npm account if you publish packages.
  • If node_modules seems corrupted, delete it and run npm ci. npm cache verify checks the cache; you rarely need to clear it.

8. Running a Node.js project on Domain India

Shared hosting (cPanel and DirectAdmin). The control panel's Node.js tool runs your app for you. On our cPanel servers it is Setup Node.js App, offering Node.js 20, 22 and 24; on DirectAdmin the Node.js selector offers versions 14 to 24 (measured 23 September 2026). Upload your code with package.json and package-lock.json but without node_modules, then click Run NPM Install and Start App. You don't need SSH for this. Build front-end or TypeScript projects on your own computer and upload the output, because large builds can run out of memory within your account's limits. The full steps are in Deploy a Node.js app on shared hosting.

Jailed SSH access is available on every shared hosting plan (cPanel, DirectAdmin, Webuzo). It is off by default; ask support to enable it for your account. You log in with an SSH key, and there is no root access, so install tools per project with npm and run them with npx rather than installing them globally. Tools available inside the jailed shell vary; ask support.

App Platform. For a production Node.js app, the App Platform detects your project from package.json, installs dependencies and runs your start script. Your app must listen on the PORT environment variable. Deploy from GitHub with Deploy Now, or with a deploy token from your CI. See Getting started with App Platform.

App Starter
₹100/mo + GST
  • 512 MB RAM per app
  • 1 vCPU
  • 5 GB NVMe SSD
  • PostgreSQL Database
See plan details

VPS. A VPS is self-managed with full root access, so you install the Node.js version you want and run your app with any process manager.

What is the difference between require and import in Node.js?

require belongs to CommonJS, Node's original module system, and loads modules synchronously. import belongs to ES modules, the JavaScript standard, which load asynchronously and allow top-level await. Use ES modules for new code by adding "type": "module" to package.json.

Why do I get "Cannot use import statement outside a module"?

Node is treating your file as CommonJS. Add "type": "module" to package.json, or rename the file to .mjs, or switch the file to require.

Should I commit package-lock.json?

Yes. It records the exact version of every installed package, so npm ci installs the same versions on every computer and server. Do not commit node_modules.

What is the difference between npm install and npm ci?

npm install adds or updates packages and can change package-lock.json. npm ci deletes node_modules and installs exactly what the lock file says, which makes it the right choice for servers and CI.

What does the caret (^) mean in package.json?

It allows minor and patch updates but not a new major version. For example, ^5.1.0 accepts 5.2.0 but not 6.0.0.

Can I run npm install on Domain India shared hosting?

Yes. On cPanel and DirectAdmin, the control panel's Node.js tool has a Run NPM Install button that installs your dependencies without SSH. Build large front-end projects on your own computer and upload the result.

Ready to run your Node.js app? Start on the App Platform, use cPanel hosting for a small app next to your website, or choose a VPS for full control.

Deploy your Node.js app

Push your code from GitHub or your CI, and the App Platform installs your packages, runs your start script and serves your app over HTTPS.

See App Platform plans

Was this article helpful?

Your answer helps us decide what to improve next.

Still need help? Open a support ticket and our team will reply.

Prefer an app? Add this site to your home screen.Get the app
Node.js Modules and npm: require, import, package.json