ES Modules Logo ESModules.com
Contact Us

ES Modules Cheat Sheet

Quick reference for JavaScript ES Modules syntax

Updated: October 2025 | Print-friendly

Export Syntax

Named Exports

// Export declarations
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export class Calculator { }

// Export list
const name = 'John';
const age = 30;
export { name, age };

// Rename exports
export { name as fullName, age as years };

Default Export (one per file)

// Export default function
export default function() { }

// Export default class
export default class User { }

// Export default value
export default 42;

// Named then exported as default
function greet() { }
export { greet as default };

Re-exports (Barrel Pattern)

// Re-export all
export * from './utils.js';

// Re-export specific
export { add, subtract } from './math.js';

// Re-export with rename
export { default as User } from './user.js';
export { add as sum } from './math.js';

Import Syntax

Named Imports

// Import specific exports
import { PI, add } from './math.js';

// Import with rename
import { add as sum } from './math.js';

// Import multiple with rename
import { name as userName, age } from './user.js';

Default Import

// Import default (use any name)
import User from './user.js';
import myFunction from './utils.js';

Namespace Import

// Import all as object
import * as MathUtils from './math.js';
MathUtils.add(2, 3);
MathUtils.PI;

Mixed Imports

// Default + named
import React, { useState, useEffect } from 'react';

// Default + namespace
import _, { debounce } from 'lodash';

Side Effects Only

// Import for side effects (no bindings)
import './polyfills.js';
import './styles.css';

Dynamic Imports

// Returns a Promise
const module = await import('./module.js');

// Conditional loading
if (condition) {
  const { feature } = await import('./feature.js');
  feature();
}

// With error handling
try {
  const module = await import('./module.js');
} catch (err) {
  console.error('Failed to load module:', err);
}

// Dynamic path (use with caution)
const lang = 'en';
const translations = await import(`./i18n/${lang}.js`);

Module Specifiers

Relative Paths

import './file.js';      // Same dir
import '../file.js';     // Parent dir
import './sub/file.js';  // Subdirectory

Bare Specifiers

import 'react';          // Package
import 'lodash/debounce'; // Subpath
import '@org/package';    // Scoped

Absolute URLs

import 'https://cdn.com/lib.js';
import 'https://unpkg.com/lodash';

Data URLs

import 'data:text/javascript,...';
// Inline module

HTML Usage

Basic Module Script

<script type="module" src="/js/app.js"></script>

<!-- Inline module -->
<script type="module">
  import { init } from './app.js';
  init();
</script>

Module Preload

<link rel="modulepreload" href="/js/app.js">

Import Maps

<script type="importmap">
{
  "imports": {
    "react": "https://esm.sh/react@18",
    "lodash": "/js/lodash.js"
  }
}
</script>

Node.js package.json

{
  "type": "module",              // Enable ESM
  "main": "./dist/index.js",     // CJS entry
  "module": "./dist/index.mjs",  // ESM entry
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    },
    "./sub": "./dist/sub.js"
  }
}

Advanced Features

Top-Level Await

// At module top level
const data = await fetch('/api');
const config = await loadConfig();

export { data, config };

import.meta

// Module URL
console.log(import.meta.url);

// Relative URL
const img = new URL('./img.png',
  import.meta.url);

Import Assertions

// JSON modules
import data from './data.json'
  assert { type: 'json' };

// CSS modules (upcoming)
import styles from './styles.css'
  assert { type: 'css' };

Web Workers

// worker.js
import { heavy } from './utils.js';
self.onmessage = (e) => { };

// main.js
const worker = new Worker(
  './worker.js',
  { type: 'module' }
);

Quick Tips & Rules

✅ DO

  • Always use .js extension in imports
  • Use named exports for better tree-shaking
  • Place imports at the top of files
  • Use dynamic imports for code splitting
  • Enable "type": "module" in package.json
  • Serve modules with correct MIME type
  • Use HTTPS in production

❌ DON'T

  • Omit file extensions in Node.js
  • Mix ESM and CommonJS without care
  • Use file:// protocol (CORS issues)
  • Rely on automatic extension resolution
  • Create circular dependencies
  • Use require() in ESM
  • Modify imported bindings (read-only)

Common Errors & Solutions

❌ Failed to resolve module specifier

Missing or incorrect file extension

// Wrong
import { add } from './math';

// Correct
import { add } from './math.js';

❌ CORS policy blocked

Use a local dev server, not file:// protocol

// Use dev server
npx serve .
# or
python -m http.server

❌ Cannot use import outside a module

Add type="module" to script tag

<script type="module" src="app.js"></script>

❌ require is not defined

Use import instead of require in ESM

// Wrong in ESM
const fs = require('fs');

// Correct
import fs from 'fs';

Continue Learning