JSJavaScript · Lesson 12 of 14

Modules & npm

JavaScript modules let you split code across files and import only what you need. They also gave rise to npm, which has over 2 million packages, making it simultaneously the world's largest software repository and the world's largest potential supply-chain attack surface.

JavaScript
// ES Modules (use in browsers and Node.js with "type": "module" in package.json)

// math.js — named exports
export function add(a, b) { return a + b }
export function subtract(a, b) { return a - b }
export const PI = 3.14159

// Default export (one per module)
export default class Calculator {
  add(a, b) { return a + b }
}

// utils/strings.js
export const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1)
export const slugify = (s) => s.toLowerCase().replace(/\s+/g, "-")

// main.js — importing
import Calculator from "./math.js"           // default import
import { add, PI } from "./math.js"          // named imports
import { capitalize as cap } from "./utils/strings.js"  // rename on import
import * as MathUtils from "./math.js"       // namespace import

console.log(add(2, 3))         // 5
console.log(PI)                // 3.14159
console.log(MathUtils.PI)      // 3.14159
console.log(cap("hello"))      // Hello

// Dynamic import — load a module only when needed
async function loadHeavyModule() {
  const { heavyFunction } = await import("./heavy.js")
  return heavyFunction()
}
Bash
# npm basics
npm init -y          # create package.json
npm install lodash   # install a package (adds to dependencies)
npm install -D jest  # install as devDependency (testing tools etc.)
npm install          # install all dependencies from package.json
npm update           # update packages to latest allowed versions

# Run scripts defined in package.json
npm run test
npm run build
npm run dev

# package.json scripts section:
# {
#   "scripts": {
#     "start": "node index.js",
#     "dev":   "node --watch index.js",
#     "test":  "jest"
#   }
# }
JavaScript
// CommonJS (older Node.js style, .js files without "type": "module")
const fs = require('fs')
const path = require('path')
const { EventEmitter } = require('events')

module.exports = { myFunction }
module.exports.myValue = 42

// Using a popular npm package (lodash)
import _ from 'lodash'

const data = [1, 2, 2, 3, 3, 3, 4]
console.log(_.uniq(data))           // [1, 2, 3, 4]
console.log(_.chunk(data, 3))       // [[1, 2, 2], [3, 3, 3], [4]]
console.log(_.groupBy([6.1, 4.2, 6.3], Math.floor))  // { 4: [4.2], 6: [6.1, 6.3] }

const users = [
  { name: "Alice", age: 30 },
  { name: "Bob",   age: 25 },
  { name: "Carol", age: 35 },
]
console.log(_.sortBy(users, "age"))
console.log(_.minBy(users, "age"))  // { name: 'Bob', age: 25 }
console.log(_.maxBy(users, "age"))  // { name: 'Carol', age: 35 }

// Deep clone (no structuredClone needed for older envs)
const original = { a: { b: { c: 1 } } }
const clone = _.cloneDeep(original)
clone.a.b.c = 99
console.log(original.a.b.c)  // 1 (untouched)
◆ Note
Keep node_modules out of git — add it to .gitignore. The package-lock.json file should be committed; it records exact versions of every dependency so installs are reproducible across machines and CI.