JavaScript Core/
Lesson

Before ES modulesWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json., organizing JavaScript meant dumping everything into the global scopeWhat is scope?The area of your code where a variable is accessible; variables declared inside a function or block are invisible outside it. and hoping nothing collided. All variables shared one namespace, script load order mattered, and debugging name clashes felt like detective work. ES modules give JavaScript a proper moduleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. system where every file has its own scope and explicit connections to other files.

Why modules matter

Think of modules as separate rooms in a house. Each room has its own furniture (variables), its own purpose (functionality), and doors (exports/imports) that connect them. Without modules, everything sits in one giant room where the kitchen table blocks the bedroom door.

<!-- The old way - order matters, everything is global -->
<script src="utils.js"></script>
<script src="api.js"></script>
<script src="app.js"></script>

If utils.js and api.js both define a config variable, the last one loaded wins silently. Modules eliminate this entire category of bugs.

AI pitfall
AI tools frequently mix CommonJS (require() / module.exports) and ES module (import / export) syntax in the same file. This will not work, a file is either one system or the other. If you see const x = require('./file') next to export function y(), the AI has blended two incompatible module systems. Pick one and be consistent across your project. AI also generates wrong import paths, always verify the path matches your actual file structure.
02

Exporting code

The export keyword makes values available to other files. There are two flavors.

Named exports

Named exports let you share multiple values from a single file. Consumers must use the exact name (or rename with as).

// math.js
export const PI = 3.14159;
export const E = 2.71828;

export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

You can also group exports at the bottom of the file:

// math.js (alternative style)
const PI = 3.14159;
function add(a, b) { return a + b; }

export { PI, add };

Default exports

Each moduleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. can have exactly one default exportWhat is default export?A module's single primary export, imported without curly braces and with any local name the caller chooses.. This is typically the "main thing" the module provides.

// UserService.js
export default class UserService {
  constructor(apiUrl) {
    this.apiUrl = apiUrl;
  }

  async getUser(id) {
    const response = await fetch(`${this.apiUrl}/users/${id}`);
    return response.json();
  }
}
03

Importing code

The import syntax changes depending on what you are importing.

// Named imports - curly braces required
import { PI, add } from './math.js';

// Default import - no braces
import UserService from './UserService.js';

// Namespace import - everything as one object
import * as MathUtils from './math.js';

// Combined - default + named together
import UserService, { validateUser } from './UserService.js';
Import styleSyntaxWhen to use
Namedimport { x } from './file.js'Importing specific values
Defaultimport x from './file.js'Importing the main export
Namespaceimport * as X from './file.js'Importing everything as an object
Renameimport { x as y } from './file.js'Avoiding name collisions
04

ModuleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. scopeWhat is scope?The area of your code where a variable is accessible; variables declared inside a function or block are invisible outside it. and strict mode

Modules automatically run in strict mode. Each module has its own top-level scope, variables declared at the top level are not global.

// utils.js
const secret = 'module-private';
// Not available to other files unless exported

export function useSecret() {
  return secret;
}
05

Real-world patterns

Barrel exports

An index.js file that re-exports from multiple modules in one place:

// components/index.js
export { Button } from './Button.js';
export { Card } from './Card.js';
export { Input } from './Input.js';

// Consumer imports from one location
import { Button, Card, Input } from './components/index.js';

Dynamic imports

Load modules on demand for code splittingWhat is code splitting?Breaking your application into smaller JavaScript chunks that load on demand so users only download the code needed for the page they're viewing.:

async function showChart() {
  const { Chart } = await import('./chartLibrary.js');
  new Chart(data).render();
}

Dynamic imports return a PromiseWhat is promise?An object that represents a value you don't have yet but will get in the future, letting your code keep running while it waits. and are great for loading heavy code only when the user actually needs it.

ModuleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. paths

Always include the file extension in imports. Relative paths start with ./ or ../. Build tools may support aliases like @/.

import { helper } from './utils.js';       // Same directory
import { config } from '../config.js';      // Parent directory
import { theme } from '@/styles/theme.js';  // Alias (build tool)
06

CommonJSWhat is commonjs?Node.js's original module format using require() and module.exports - distinct from and predating the ES module import/export syntax. vs ES modulesWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json.

You will encounter both systems. Knowing the difference prevents confusion when AI tools mix them up.

FeatureCommonJS (require)ES Modules (import)
Syntaxconst x = require('./file')import x from './file.js'
Exportmodule.exports = xexport default x
LoadingSynchronousAsynchronous
EnvironmentNode.js (default)Browsers + Node.js
Tree shakingNoYes (unused code removed)
07

Quick reference

SyntaxWhat it doesExample
export const xNamed exportexport const PI = 3.14
export default xDefault exportexport default class App {}
import { x }Import namedimport { PI } from './math.js'
import xImport defaultimport App from './App.js'
import * as XImport namespaceimport * as utils from './utils.js'
import { x as y }Rename importimport { PI as pi } from './math.js'
export { x } fromRe-exportexport { Button } from './Button.js'