# Introduction to ES Modules

> Learn how ES Modules let JavaScript files export and import values in browsers and Node.js, using default exports, named exports, and module specifiers.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2018-06-13 | Updated: 2026-07-18 | Topics: [JavaScript](https://flaviocopes.com/tags/js/) | Canonical: https://flaviocopes.com/es-modules/

ES Modules are the standard JavaScript module system. They let one file export values and another file import them.

Modern browsers and Node.js support ES Modules. The same `import` and `export` syntax works in both environments, although each environment resolves package names differently.

The [MDN modules guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) is the best complete reference for browser modules.

## Export a value

Create a file named `uppercase.js`:

```js
export default function uppercase(string) {
  return string.toUpperCase()
}
```

This module has one **default export**.

Import it from another module:

```js
import uppercase from './uppercase.js'

console.log(uppercase('hello')) //'HELLO'
```

You can choose the local name of a default import.

## Named exports

A module can export several named values:

```js
const first = 1
const second = 2

export { first, second }
```

Import the values by name:

```js
import { first, second } from './numbers.js'
```

You can rename an import:

```js
import { second as two } from './numbers.js'
```

Or import all named exports into a module namespace object:

```js
import * as numbers from './numbers.js'

console.log(numbers.first)
```

The `import * from './numbers.js'` syntax is not valid. A namespace import always needs a local name after `as`.

The [MDN `import` reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) lists every supported import form.

## Use modules in the browser

Load the entry module with `type="module"`:

```html
<script type="module" src="index.js"></script>
```

Module scripts use strict mode automatically and are deferred by default. Their dependencies are fetched before the module runs.

In browser code, relative module specifiers need `./` or `../`:

```js
import { first } from './numbers.js'
```

Root-relative and full URL imports also work:

```js
import { first } from '/modules/numbers.js'
import { first } from 'https://cdn.example.org/numbers.js'
```

A bare name such as this does not identify a browser URL on its own:

```js
import packageName from 'package-name'
```

Browsers can resolve bare names when you provide an [import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type/importmap). Bundlers and other runtimes also have their own package resolution rules.

Browser modules use CORS. Serve your files through a local web server while developing instead of opening the page with a `file://` URL.

## Use ES Modules in Node.js

Node treats `.mjs` files as ES Modules.

You can also add `"type": "module"` to `package.json` so Node treats `.js` files in that package as ES Modules:

```json
{
  "type": "module"
}
```

Use `.cjs` for a CommonJS file inside a module package.

Node can also detect module syntax in some ambiguous `.js` files, but an explicit `"type"` field is clearer and avoids extra parsing work. The [Node.js package documentation](https://nodejs.org/api/packages.html#determining-module-system) explains the complete rules.
