Frontend Development 14 min read

Understanding the ESModule Specification and Its Implementation in Node.js and Browsers

This article explains the ESModule standard, compares it with CommonJS and AMD, describes how Node.js and modern browsers implement ESModules, discusses compatibility challenges with third‑party dependencies, and reviews next‑generation tools such as Snowpack and Vite that leverage native module loading.

政采云技术
政采云技术
政采云技术
Understanding the ESModule Specification and Its Implementation in Node.js and Browsers

1 ESModule Specification

Introduction

Before ES6, the community created module loading solutions like CommonJS (for servers) and AMD (for browsers). ES6 introduced a native module system that satisfies most needs of both. With ESModule, browsers and Node.js can natively support a unified module format.

After ES6 defined ESModule, browsers began to support it natively, and Node.js added support as well.

// commonjs
const axios = require('axios')

// amd
require(['axios'], function (axios) {})

// esmodule
import axios from './node_modules/axios/axios.js'
Note: The latest ECMAScript proposal is approved; import maps can manage module import paths.

Server‑side Implementation

CommonJS

Node.js originally used its own built‑in Module system to implement CommonJS, which is not an official JavaScript standard and is unsupported by browsers.

ESModule

Node.js needed to adopt ESModule while preserving existing CommonJS packages, so the solution was to support both formats.

Compatibility Issues

Because CommonJS and ESModule have fundamental design conflicts, compatibility layers are complex.

Node.js >= v13 uses the .mjs extension for ESModules and the "type": "module" field in package.json to treat .js files as ESModules.

// esmA/index.mjs
export default null

// esmB/index.js
export default null

// esmB/package.json
{
    "type": "module"
}

Browser Implementation

Modern Browser Support

All major browsers (except IE) have implemented ESModule support within the last few years.

Example repository: https://github.com/mdn/js-examples/tree/master/modules/basic-modules

2 Third‑Party Dependency Dilemma

Node.js Module Resolution

Node.js resolves third‑party packages by name, automatically concatenating node_modules paths and reading the entry field in package.json .

const axios = require('axios') // => resolves to node_modules/axios
const axios = require('/User/xxxx/workspace/node_modules/axios') // => resolves package.json
const axios = require('/User/xxxx/workspace/node_modules/axios/axios.js') // => resolves entry file

Auto‑append full path to node_modules

Auto‑read entry field in package.json

Auto‑add file extensions or index paths

Webpack Module Resolution

Webpack bundles all dependencies into a single bundle.js . It mimics Node.js CommonJS handling so developers can use the same syntax in web apps.

However, Webpack’s internal CommonJS implementation differs from Node.js’s core implementation.

Browser Module Resolution

Browsers do not support native CommonJS loading; even with ESModule support, they cannot directly load CommonJS packages, prompting the need for new tooling.

3 Next‑Generation Web App Development Model

To avoid the incompatibility of CommonJS packages with browsers, tools convert CommonJS modules to ESModules.

CommonJS to ESModule Converters

JSPM (https://jspm.dev/@babel/core)

Skypack (http://cdn.skypack.dev/@babel/core)

ESM.sh (http://esm.sh/@babel/core)

These tools use bundlers like Rollup or esbuild to transform syntax and rewrite import paths.

const axios = require('axios')
module.exports = axios
// =>
import axios from '/esm/axios.js'
export default axios

In the browser, the transformed module can be loaded directly:

Using this approach can cause a “request explosion” when many third‑party modules are needed (e.g., an Ant Design component library may trigger ~2000 network requests).

Snowpack & Vite

These tools separate third‑party dependencies from source code, bundling dependencies once into a “dep chunk” while letting the browser handle native ESModule loading for source files, dramatically improving dev‑server startup time.

4 Adoption Challenges

Although the new model reduces tooling complexity and speeds up startup, ecosystem adoption is slow due to incomplete support, conversion gaps, and dynamic‑import issues.

Ecology Issues

Many features already available in Webpack lack official support in newer tools.

CommonJS‑to‑ESModule Conversion Problems

Conversion tools often fail to handle complex CommonJS patterns, dynamic exports, and legacy compatibility code (e.g., exports.__esModule ).

Dynamic Import vs. Static Analysis

CommonJS’s dynamic require makes static analysis difficult, whereas ESModule requires top‑level static exports.

// CommonJS dynamic example
init()
function init() { exports.a = 1 }
// ESModule static example
export const a = 1
// Error if export is inside a function
init()
function init() { export const a = 1 }

Named vs. Default Exports

CommonJS treats module.exports and exports as the same object, while ESModule distinguishes named and default exports.

// module.js (ESModule)
export const a = 1
export default { a: 2 }
// index.js
import { a } from './module.js' // 1
import aDefault from './module.js' // { a: 2 }
import * as all from './module.js' // { a: 1, default: { a: 2 } }

Proposed Solutions

The ByteDance Web Infra team is actively working on ESModule adoption, addressing the above challenges, and will share detailed solutions in future posts.

Follow the ByteDance Web Infra public account for updates.

JavaScriptFrontend Developmentbackend developmentNode.jsbrowserESModule
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.