Import Maps let you use npm-style bare specifiers in the browser without a bundler. Map package names to URLs, pin versions, and scope dependencies natively.
An import map is a JSON object in a <script type="importmap"> tag that maps bare specifiers to URLs:
<script type="importmap">
{
"imports": {
"lodash": "https://esm.sh/[email protected]",
"react": "https://esm.sh/react@19",
"react-dom/client": "https://esm.sh/react-dom@19/client"
}
}
</script>
<script type="module">
// Now bare specifiers work - just like in Node.js!
import { debounce } from 'lodash';
import React from 'react';
import { createRoot } from 'react-dom/client';
const debouncedLog = debounce(console.log, 300);
</script>
No Bundler Required!
Import maps enable using npm packages directly in the browser. Combined with CDNs like esm.sh or jspm.io, you can build applications without any build step.
Map entire package directories using trailing slashes, or create path aliases:
<script type="importmap">
{
"imports": {
"lodash/": "https://esm.sh/[email protected]/",
"@/": "./src/",
"#components/": "./src/components/",
"#utils/": "./src/utils/"
}
}
</script>
<script type="module">
// Import specific lodash functions
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';
// Use path aliases (like TypeScript paths)
import { Header } from '@/components/Header.js';
import { formatDate } from '#utils/date.js';
</script>
Different parts of your app can resolve the same specifier to different URLs. This solves version conflicts:
<script type="importmap">
{
"imports": {
"lodash": "https://esm.sh/[email protected]"
},
"scopes": {
"/legacy-widget/": {
"lodash": "https://esm.sh/[email protected]"
},
"/admin-panel/": {
"lodash": "https://esm.sh/[email protected]",
"chart.js": "https://esm.sh/chart.js@4"
}
}
}
</script>
<!-- Modules in /legacy-widget/ get lodash v3 -->
<!-- Everything else gets lodash v4 -->
Use CDNs that serve npm packages as ES Modules:
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@19",
"three": "https://esm.sh/[email protected]",
"zod": "https://esm.sh/[email protected]",
"date-fns": "https://esm.sh/date-fns@4"
}
}
</script>
esm.sh
Auto-converts npm packages to ESM. Supports TypeScript types. Recommended for most use cases.
jspm.io
JSPM Generator creates import maps automatically from package.json dependencies.
unpkg.com
Serves files directly from npm packages. Use ?module query for ESM output.
Generate import maps dynamically for advanced use cases:
// Generate an import map from your dependencies
const importMap = {
imports: {
'lodash': `https://esm.sh/lodash-es@${LODASH_VERSION}`,
'react': `https://esm.sh/react@${REACT_VERSION}`
}
};
const script = document.createElement('script');
script.type = 'importmap';
script.textContent = JSON.stringify(importMap);
document.head.appendChild(script);
// IMPORTANT: Import map must be added BEFORE
// any module scripts are loaded
Rules:
type="module" scripts| Browser | Version | Release Date |
|---|---|---|
| Chrome | 89+ | March 2021 |
| Edge | 89+ | March 2021 |
| Firefox | 108+ | December 2022 |
| Safari | 16.4+ | March 2023 |
Universal Support (2024+)
Import Maps are supported by 95%+ of global browser users. No polyfill needed for modern browser targets.
Import Maps are a browser feature that lets you control how JavaScript module specifiers are resolved. They enable npm-style bare specifiers (like 'import React from "react"') directly in browsers without a bundler, by mapping package names to URLs.
Yes, as of 2024, Import Maps are supported in all modern browsers: Chrome 89+, Edge 89+, Firefox 108+, and Safari 16.4+. This covers over 95% of global browser usage.
Yes! Import Maps are designed specifically for bundler-free development. Combined with CDNs like esm.sh or jspm.io, you can use any npm package directly in the browser with just a script tag and an import map.
Import Maps support scoped resolutions, allowing different parts of your application to use different versions of the same package. The 'scopes' field lets you specify different URL mappings for modules loaded from specific paths.