Testing

ES6 Modules: Browser Support, Features, Known Issues

ES6 modules work in Chrome 61+, Edge 16+, Firefox 60+, Safari 11+, Opera 48+, Samsung Internet 8.2+, and Android. Learn ES6 modules browser support and limits.

Author

Prince Dewani

May 6, 2026

ES6 modules are the ECMAScript module system that lets JavaScript files share code through import and export statements. They work in Chrome 61+, Edge 16+, Firefox 60+, Safari 11+ on macOS and iOS, Opera 48+, Samsung Internet 8.2+, and Chrome for Android 61+, while Internet Explorer never added support.

This guide covers what ES6 modules are, the supported browsers, the key features, how to use them in browsers, the differences from CommonJS, and known issues.

What are ES6 modules?

ES6 modules are the JavaScript module system standardized in ECMAScript 2015 and maintained by the TC39 committee. Each .js file becomes a module with its own scope, and developers use the export statement to expose values and the import statement to pull them into other files.

Which browsers support ES6 modules?

ES6 modules work natively in every major modern browser through the script type=module tag, with the exception of Internet Explorer.

Loading browser compatibility data...

ES6 modules compatibility in Chrome

Chrome supports ES6 modules from Chrome 61 on Windows, macOS, Linux, ChromeOS, and Android. Chrome 60 had modules disabled by default behind the chrome://flags experimental web platform features flag, and Chrome 4 to 59 did not support them. Chrome for Android follows the same version numbering as desktop Chrome.

ES6 modules compatibility in Edge

Microsoft Edge supports ES6 modules from Edge 16 on Windows. Edge 15 had them disabled by default behind a flag, and Edge 12 to 14 did not support them. Chromium Edge from Edge 79 inherits full ES6 module support from the Chromium engine and ships modules enabled by default on every desktop platform.

ES6 modules compatibility in Firefox

Firefox supports ES6 modules from Firefox 60 on Windows, macOS, Linux, and Android. Firefox 54 to 59 had modules disabled by default behind the dom.moduleScripts.enabled flag in about:config, and Firefox 2 to 53 did not support them at all. Firefox for Android follows the same version numbering.

ES6 modules compatibility in Safari

Safari supports ES6 modules from Safari 11 on macOS and from Safari 11 on iOS and iPadOS. Safari 10.1 had partial support that recognized type=module but did not honor the nomodule attribute, so it ran both the modern and legacy code paths. Safari 3 to 10 did not support modules at all.

ES6 modules compatibility in Opera

Opera supports ES6 modules from Opera 48 on Windows, macOS, and Linux. Opera 47 had modules disabled by default behind a flag, and Opera 9 to 46 did not support them. Opera Mobile is built on the same Chromium engine and supports ES6 modules from Opera Mobile 48 on Android.

ES6 modules compatibility in Samsung Internet

Samsung Internet supports ES6 modules from Samsung Internet 8.2 on Galaxy phones and tablets. Earlier versions 4.0 to 7.4 did not support them. Samsung Internet shares the Chromium engine, so module loading, dynamic import, and the nomodule fallback all track Chrome behavior closely.

ES6 modules compatibility in Android Browser

Chrome for Android supports ES6 modules from Chrome for Android 61, the same version as desktop Chrome. The legacy stock Android Browser, which shipped as the default through Android 4.4, never added support. On modern Android phones, use Chrome, Firefox, or Samsung Internet for a working ES6 module setup.

ES6 modules compatibility in Internet Explorer

Internet Explorer does not support ES6 modules in any version. IE 11 is the last release and Microsoft has retired the browser. Sites that still target IE 11 must transpile import and export statements down to ES5 with a tool like Babel, Webpack, or Rollup before shipping the JavaScript bundle.

Note

Note: ES6 modules behave differently across older Safari, Edge, and Android Browser builds. Test them on real browsers and OS with TestMu AI. Try TestMu AI free!

What are the key features of ES6 modules?

ES6 modules add five features that change how JavaScript files load, share code, and run in a browser.

  • Static import and export: The import and export keywords let one file expose specific values and another file pull them in by name. The parser reads the statements before execution, so bundlers and engines build a static dependency graph for tree-shaking and dead-code removal.
  • Strict mode by default: Every module runs in JavaScript strict mode without needing the "use strict" directive. Undeclared variables, duplicate parameter names, and the with statement all throw an error instead of failing silently.
  • Deferred execution: A script tag with type="module" runs after the HTML document is parsed, the same as a script with the defer attribute. The browser fetches modules in parallel and runs them in document order.
  • Live bindings: When module A imports a value from module B, A reads the live binding rather than a copy. If B updates the export, A sees the new value on the next read.
  • Dynamic import: The import() expression returns a Promise and lets you load a module at runtime based on user actions, route changes, or feature detection. This unlocks code splitting without a build step.

How do you use ES6 modules in a browser?

You can run ES6 modules in any modern browser by adding type="module" to the script tag and serving the files through a web server. The browser then handles fetching, parsing, and dependency resolution for you.

  • Author your module: Save a .js file and use the export statement to expose functions, classes, or constants. For example, write export function add(a, b) at the top of math.js to share an add helper.
  • Add type=module to the script tag: In your HTML, write <script type="module" src="main.js"></script> so the browser parses the file as a module instead of a classic script.
  • Serve the file over HTTP or HTTPS: Open the page through a local web server such as npx serve or python -m http.server. Modules do not run from the file:// protocol because the browser blocks cross-origin module requests.
  • Set the JavaScript MIME type: Configure your server to return text/javascript or application/javascript for .js and .mjs files. Modules served with text/plain or application/octet-stream fail to load.
  • Add a nomodule fallback: Pair the module script with a transpiled fallback using <script nomodule src="legacy.js"></script>. Browsers that support modules ignore the nomodule script, and IE 11 runs only the legacy bundle.
  • Confirm in DevTools: Open the Network tab in Chrome 61+, Firefox 60+, or Safari 11+, refresh the page, and check that every module file loads with a 200 status and the JavaScript MIME type.

The snippet below shows a minimal two-file ES6 module setup that runs in any modern browser through a single HTML page:

// math.js - export named values from a module
export function add(a, b) {
  return a + b;
}

export const PI = 3.14159;

// main.js - import the values into another module
import { add, PI } from './math.js';

console.log('add(2, 3):', add(2, 3));
console.log('PI is:', PI);

// In your HTML, load the entry module with type="module":
// <script type="module" src="main.js"></script>
...

What is the difference between ES6 modules and CommonJS?

ES6 modules and CommonJS are both JavaScript module systems but differ in syntax, loading model, and runtime support. ES6 modules are the browser-native standard, while CommonJS is the original Node.js convention.

DimensionES6 ModulesCommonJS
OriginECMAScript 2015 standard, maintained by TC39Node.js convention based on the CommonJS spec
Syntaximport and export keywordsrequire() and module.exports
Loading modelStatic, parsed before executionDynamic, evaluated at runtime
Strict modeAlways onOff by default
Runtime supportModern browsers and Node.js 12+Node.js native; browsers need a bundler
File extension.mjs or .js with type:module in package.json.js or .cjs
BindingsLive bindings to the original valueCopy of the exported value at require time
Top-level awaitSupportedNot supported
Tree-shakingYes, the static graph allows dead-code removalLimited, dynamic shape blocks most analysis

What are the known issues with ES6 modules?

ES6 modules are widely supported, but a handful of real edge cases still trip up developers in production. The biggest hits are Internet Explorer, server configuration, and a few module-specific browser rules.

  • Internet Explorer never added support: IE 11 cannot parse import or export and treats script type=module as an unknown script type. Sites that still target IE 11 must ship a transpiled ES5 bundle through the nomodule fallback.
  • CORS rules apply to module scripts: Module fetches always go through CORS, even for same-origin pages opened from the file:// protocol. Pages must run on a real server, and cross-origin modules need an Access-Control-Allow-Origin header.
  • Strict MIME type checks: Browsers reject module scripts that arrive with a non-JavaScript MIME type. Servers must send text/javascript or application/javascript for .js and .mjs files; text/plain or octet-stream cause the module to fail with a NetworkError.
  • Bare specifiers need import maps: An import like import lodash from "lodash" does not work in the browser without an import map. Without one, every import path must start with /, ./, or ../.
  • JSON, CSS, and HTML imports are still being standardized: Import attributes for JSON ship in Chrome and Edge, but CSS and HTML imports remain partial across browsers. Bundlers smooth this over, but native code may need a fetch fallback.
  • Top-level await blocks the subgraph: A module that awaits at the top level pauses every module that imports it until the Promise resolves. This is useful but can stall the page if the awaited request is slow.
  • Service workers and classic workers cannot import: Module scripts inside Service Workers need {type: 'module'} in the registration call, and Worker support for ES6 modules landed late in Firefox and Safari. Test worker module loading on every target browser.

In my experience, the most surprising failure happens when a developer opens an HTML file directly from the disk and sees a CORS error in the console. The page works the moment they serve the same files through npx serve, so always run modules through a real web server before debugging anything else.

...

Citations

All ES6 module version numbers and platform notes in this guide come from these primary sources:

Author

Prince Dewani is a Community Contributor at TestMu AI, where he manages content strategies around software testing, QA, and test automation. He is certified in Selenium, Cypress, Playwright, Appium, Automation Testing, and KaneAI. Prince has also presented academic research at the international conference PBCON-01. He further specializes in on-page SEO, bridging marketing with core testing technologies. On LinkedIn, he is followed by 4,300+ QA engineers, developers, DevOps experts, tech leaders, and AI-focused practitioners in the global testing community.

Open in ChatGPT Icon

Open in ChatGPT

Open in Claude Icon

Open in Claude

Open in Perplexity Icon

Open in Perplexity

Open in Grok Icon

Open in Grok

Open in Gemini AI Icon

Open in Gemini AI

Copied to Clipboard!
...

3000+ Browsers. One Platform.

See exactly how your site performs everywhere.

Try it free
...

Write Tests in Plain English with KaneAI

Create, debug, and evolve tests using natural language.

Try for free

Frequently asked questions

Did you find this page helpful?

More Related Hubs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests