Mastering JavaScript Import Syntax: How to Consume Any Module Like a Pro

A Companion Guide to export with Practical Use Cases and Gotchas

Mastering JavaScript Import Syntax: How to Consume Any Module Like a Pro
Photo by Javier Del pino / Unsplash

If you’ve already familiarized yourself with the various ways to export in JavaScript modules, the next natural step is understanding how to import them efficiently.

This article walks you through all valid import patterns in JavaScript, how they relate to the different export types, and provides real-world usage tips to avoid confusion—especially when dealing with default vs named exports.


🔹 Why Use import?

The import keyword allows your JavaScript file to consume exported functionality from another file or module. It’s a core feature of ES Modules (ESM), which are now natively supported in all modern environments, including the browser and Node.js (with .mjs or type: "module" in package.json).


✅ Basic Import Patterns

1. Importing Default Exports

import MyModule from './my-module.js';

This works with:

// my-module.js
export default function MyModule() { }
Note: You can name the default import anything you want, since it's not tied to the original declaration name.

2. Importing Named Exports

import { add, subtract } from './math.js';

This works with:

// math.js
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
🟡 Must match the exported name exactly.

3. Renaming Imports with as

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

This is useful to avoid naming collisions or make naming more meaningful in your context.


4. Importing Everything as a Namespace

import * as utils from './utils.js';

Now you can use it like:

utils.validate();
utils.format();

This works well when you're importing a utility module or when you want clarity on where a function comes from.


5. Importing Mixed Default and Named Exports

import MyComponent, { helper } from './component.js';

This matches:

export default function MyComponent() { }
export const helper = () => { /* ... */ }

6. Importing from Re-exported Modules

If another file re-exports something:

// index.js
export * from './math.js';
export { default as Logger } from './logger.js';

You can import it like:

import { add } from './index.js';
import { Logger } from './index.js';

⚠️ Common Import Mistakes

❌ Mixing Up Default vs Named

// Wrong!
import { MyComponent } from './MyComponent'; // throws if MyComponent is default

// Correct:
import MyComponent from './MyComponent';

❌ Forgetting File Extensions (in the browser)

In Node.js, .js extensions can often be omitted, but in the browser (especially when using native <script type="module">), you must include .js or .mjs.


📌 Dynamic Imports (import())

You can also load modules dynamically:

const module = await import('./my-module.js');
module.default();

Useful for:

  • Lazy loading components or logic
  • Loading based on conditions or routes
  • Reducing bundle size (tree-shaking)

📦 Importing from NPM Packages

import React from 'react';                       // default export
import { useState } from 'react';                // named export
import * as lodash from 'lodash';                // namespace
import debounce from 'lodash/debounce';          // scoped import
Tip: Use bundlers (like Vite, Webpack, ESBuild) to handle optimized imports and tree-shaking.

🧠 Finally

Importing is the flip side of exporting, and being fluent in both gives you powerful control over code organization.

  • Use default imports when a file has one main purpose.
  • Use named imports for utilities and shared logic.
  • Use namespace imports when grouping makes your code easier to read.
  • Avoid mixing import styles unnecessarily—consistency matters.

Support Us