Suggest an editImprove this articleRefine the answer for “JavaScript modules: import/export”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`export` sends an entity out of a module, `import` pulls it into another file, and the difference between `export default` and a named `export` is about count and names: there is one default per file and it is imported without braces under any name, while there can be any number of named exports and they are imported inside `{}` under exactly their own names.** Both forms are static: the links between modules are known before the code runs, which is what makes tree shaking and bundler checks possible, and a module is loaded and cached once. ```javascript // math.js export const PI = 3.14; // named export export default function add(a, b) { // default export return a + b; } // app.js import sum, { PI } from './math.js'; // default without braces, named inside braces console.log(sum(1, 2), PI); // 3 3.14 ``` **Key point:** named exports are many and their names are fixed, the default one is single and its name is up to the importer.Shown above the full answer for quick recall.Answer (EN)Image**`export` sends a variable, function or class out of a module, and `import` pulls an exported entity into another file.** Together they form the built-in module system that arrived with ES6 (2015) and lets you split code into module files and share values, functions, classes and so on between them. ## Theory ### TL;DR - `export` sends an entity outward, `import` loads it into another module. - A file may have any number of named exports; they are imported inside braces and under exactly their own names. - `export default` is allowed once per file, is imported without braces and under any name. - Renaming works both on export and on import through `as`, and `import * as ns` collects the whole module into one object. - Imports are static: you cannot write them inside `if`, `for` or a function; for on-demand loading there is `await import()`. - A module is loaded and cached once, and all of this only works in a module context (`type="module"` in HTML, or `.mjs` or `"type": "module"` in Node.js). ### Quick example File `math.js`: ```javascript export const PI = 3.14; export function add(a, b) { return a + b; } ``` File `app.js`: ```javascript import { PI, add } from './math.js'; console.log(PI); // 3.14 console.log(add(2, 3)); // 5 ``` ### Named export and default export A **named export** (`export`) lets you send several entities out of one file. ```javascript // math.js export const PI = 3.14; export function multiply(a, b) { return a * b; } ``` They must be imported **by name**, inside braces, and the names have to match: ```javascript import { PI, multiply } from './math.js'; ``` A **default export** (`export default`) sends out the one main entity of the file, most often the "main" object, function or class. ```javascript // math.js export default function add(a, b) { return a + b; } ``` It can be imported **under any name** and without braces: ```javascript import sum from './math.js'; console.log(sum(2, 3)); // 5 ``` A comparison of the two forms: | Criterion | `export` (named) | `export default` | | --- | --- | --- | | Count per file | As many as you like | Exactly one | | Import | Inside braces `{}` | Without braces | | Name | Must match | Can be anything | | Renaming on import | Through `as` | You simply write another name | | Example | `import { add } from './file.js'` | `import add from './file.js'` | The three typical combinations: ```javascript // math.js: named export export const PI = 3.14; export function add(a, b) { return a + b; } ``` ```javascript // app.js import { PI, add } from './math.js'; console.log(add(1, 2)); // 3 ``` ```javascript // math.js: default export (the function may be anonymous) export default function(a, b) { return a * b; } ``` ```javascript // app.js import multiply from './math.js'; console.log(multiply(2, 3)); // 6 ``` ```javascript // math.js: mixed export export const PI = 3.14; export default function add(a, b) { return a + b; } ``` ```javascript // app.js import add, { PI } from './math.js'; console.log(add(1, 2), PI); // 3 3.14 ``` ### Renaming, namespace import and re-export An entity can be renamed on export: ```javascript function sum(a, b) { return a + b; } export { sum as add }; ``` and on import: ```javascript import { add as plus } from './math.js'; plus(2, 3); // 5 ``` The whole module can be loaded as a single object, which is handy when there are many exports: ```javascript import * as math from './math.js'; console.log(math.PI); // 3.14 console.log(math.add(2, 3)); // 5 ``` A re-export lets one module repackage others, for example to give a folder a single entry file: ```javascript // utils.js export { add, multiply } from './math.js'; ``` Now the consumer takes everything from one place: ```javascript import { add } from './utils.js'; ``` ### How modules behave | Feature | Description | | --- | --- | | Works only in modules (`type="module"` in HTML, or `.mjs` or `"type": "module"` in Node.js) | Otherwise you get a `SyntaxError` | | Import and export are always static | They cannot be written inside `if`, `for` or a function | | Modules are cached | Loaded once and reused afterwards | | Module loading is asynchronous | For on-demand loading there is `await import()` | | A module body runs in strict mode and has its own scope | Module variables never land on the global object | Named imports are live bindings: if the module later changes an exported variable, the consumer sees the new value rather than a copy of the old one. A dynamic import loads a module on demand and returns a promise: ```javascript const math = await import('./math.js'); console.log(math.add(2, 3)); // 5 ``` It works inside an `async` function or at the top level of a module, and it is exactly what code splitting is built on. ### ES modules versus CommonJS | Criterion | ES modules (`import` / `export`) | CommonJS (`require` / `module.exports`) | | --- | --- | --- | | Syntax | `import x from './m.js'` | `const x = require('./m.js')` | | When links are resolved | Statically, before execution | Dynamically, at run time | | Where it works | Browser and Node.js | Historically Node.js | | Loading | Asynchronous, with `await import()` | `require` is synchronous | | What an import gives | Live bindings to the exported values | A copy of the `module.exports` object at call time | | Tree shaking | Possible thanks to static analysis | Practically impossible | ```javascript // CommonJS const { add } = require('./math.js'); module.exports = { add }; // ES modules import { add } from './math.js'; export { add }; ``` ### Summary | Keyword | What it does | Example | | --- | --- | --- | | `export` | Sends variables and functions outward | `export const PI = 3.14;` | | `export default` | Sends out the main entity of the file | `export default class User {}` | | `import` | Wires in the exported entities | `import { PI } from './math.js';` | Put simply: > `export` means "send outward", `import` means "load inward", and `export default` means "send the one main thing". ### Common mistakes 1. **Forgetting the module context.** A plain `<script src="app.js">` does not understand `import`; you need `<script type="module" src="app.js">`, and in Node.js either the `.mjs` extension or `"type": "module"` in `package.json`. 2. **Mixing up the braces.** `import { add } from './math.js'` takes a named export, `import add from './math.js'` takes the default. If the module has no default, the second form yields `undefined` or a bundler error. 3. **Getting a named import's name wrong.** Names must match character for character; to use another name you need `as`: `import { add as plus } from './math.js'`. 4. **Writing several `export default` statements in one file.** Exactly one is allowed, otherwise it is a `SyntaxError`. 5. **Putting `import` inside a condition or a function.** A static import is only valid at the top level of a module; for conditional loading there is `await import()`. 6. **Dropping the file extension in a relative path.** In the browser and in Node.js with ES modules `'./math'` does not resolve, you need `'./math.js'`, unlike the habit from CommonJS and bundlers. 7. **Expecting a module to run twice.** Modules are cached: no matter how many files import it, the module body executes once.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.