File Extension File Extension Guide

What is an MJS File?ES Module

A technical reference for the .mjs extension, a JavaScript file written as an ES module. What an MJS file is, why the extension exists, how it differs from a plain .js file, and how you open and run one.

ES Module 📝 Plain Text 🟨 JavaScript ⬢ Node.js
.MJS

JavaScript ES Module

Type:Source code
Extension:.mjs
Language:JavaScript
Module type:ES module
Runs in:Node.js, browsers

📖 What is an MJS File?

An MJS file is a JavaScript source code file written as an ES module. It uses the .mjs extension, and the extra letter m is the whole point, it marks the file as a module so that tools know to treat the code that way.

Inside it is ordinary JavaScript, the same plain-text code you would write in a .js file. What sets a .mjs apart is not the language but the label. The extension is a clear signal, to Node.js and to anyone reading the project, that the file uses the modern module style with import and export.

That signal matters because a plain .js file is ambiguous. In Node.js it could be one of two module styles depending on project settings, so the .mjs extension removes the doubt and says this file is an ES module, no matter the surrounding configuration.

Key Characteristics

  • JavaScript code, in plain readable text
  • An ES module, the modern module style
  • Uses import and export, not require
  • Marks itself, the m stands for module

Good to Know

  • Node.js reads it as ESM, by default
  • Removes .js ambiguity, no config needed
  • Runs in browsers too, as a module
  • Since ES6, the 2015 language update
💡 Why it matters: The .mjs extension is really a promise about how the code should be loaded. Knowing that explains why the same JavaScript behaves differently as .mjs versus .js, and why the extension exists at all.

⚡ Quick Facts

File Extension.mjs
Full NameJavaScript ES Module File
CategorySource code file
LanguageJavaScript
Module SystemES modules (ECMAScript)
FormatPlain text
Introduced WithECMAScript 6, in 2015
MIME Typetext/javascript
Runs InNode.js and web browsers
Related Extensions.js, .cjs, .ts, .json

🔍 What Is Inside

Open a .mjs file in an editor and you see JavaScript. What marks it as a module are the import and export keywords, which let one file share code with another. Here is a short example of each side.

A module that exports, and one that imports it

// greet.mjs, sharing a function
export function greet(name) {
  return `Hello, ${name}!`;
}

// main.mjs, using it
import { greet } from './greet.mjs';
console.log(greet('world'));

The first file uses export to make its greet function available. The second uses import to pull it in and then calls it. This pairing is the heart of the module system, code stays split across tidy files that each state clearly what they share and what they use.

🎯 Why the Extension Exists

JavaScript has two ways to split code into modules, and for years the .js extension could mean either. The .mjs extension was introduced to end that guessing.

The older style, CommonJS, came from Node.js and uses require to bring code in. The newer style, ES modules, is part of the JavaScript standard itself and uses import. Because a .js file could follow either style depending on a project setting, tools needed a reliable way to tell them apart. Giving ES modules their own .mjs extension does exactly that, so Node.js treats any .mjs as an ES module without needing extra configuration. The other way to reach the same place is a project-wide setting, a "type": "module" line in package.json, which turns the project's .js files into ES modules. Its counterpart, .cjs, always means CommonJS whatever that setting says.

💡 The letter m: The m in .mjs simply stands for module. It is a small addition that carries a clear message, this JavaScript is meant to be loaded as an ES module, full stop.
Two ways to get an ES module in Node.js name it .mjs app.mjs always an ES module on its own works file by file set the project type "type": "module" in package.json, covers the .js files works project wide the .mjs extension is the per-file route, package.json is the whole-project route

🔤 MJS vs JS Files

The difference between a .mjs and a plain .js file is not the language but the module system, and a few details follow from that.

Point.mjs (ES module).js (often CommonJS)
Imports withimportrequire
Exports withexportmodule.exports
Node.js reads asES moduleDepends on settings
Top-level variablesModule scopedCan hit global scope
Runs in browsers as a module~ as a script

A .mjs always uses the import and export keywords and is read as an ES module everywhere. A .js file leans on the older CommonJS style by default in Node.js, with require and module.exports, unless the project opts into modules. ES modules also keep their top-level variables to themselves rather than leaking into the global space, which keeps larger projects tidier. Their structure lets build tools do tree-shaking too, dropping code that is never imported so the final bundle stays lean.

Two ways JavaScript splits code into modules .mjs ES module (modern) export function ... import { ... } Node.js reads it as ESM by default .js / .cjs CommonJS (older) module.exports = ... require( ... ) the long-standing Node.js default the .mjs extension makes the ES module choice explicit

📂 How to Open an MJS File

A .mjs holds nothing but readable JavaScript, so getting one on screen is easy. Your choice of tool comes down to whether you only need to skim the code or intend to change it.

1

Any text editor

Notepad, TextEdit or Vim open a .mjs at once to read or change the JavaScript as text.

2

A code editor

Tools built for code, among them VS Code and Sublime, add colouring and hints that ease work on the module.

3

A full IDE

Visual Studio or WebStorm bundle editing with tools to run and debug the code in one place.

💡 Reading is not running: Opening a .mjs shows you the code, but it does not execute it. To see the module actually do something, you run it with Node.js or load it in a browser, which is a separate step.

▶️ How to Run One

An MJS file is code, so to make it do its work you hand it to something that runs JavaScript. There are two usual homes for that.

Run a module with Node.js

# run main.mjs from a terminal
node main.mjs

On a server or your own machine, Node.js runs a .mjs directly, as shown above, and treats it as an ES module without any extra flags on current versions. In a web page, a browser loads one through a script tag marked as a module, letting the file use import to bring in other modules. One rule catches people out, an ES module import must spell out the full filename including the .mjs, or the runtime cannot find it. Either way, the file is being executed rather than just read.

🌐 Serving MJS on the Web

If you publish a .mjs for a browser to load, one detail trips people up, the type the server says the file is.

A browser expects a module to arrive with a JavaScript media type, and text/javascript is the recommended one. Many servers already send that for .js files but do not yet do so for .mjs, so a module can be rejected with a message about a non-JavaScript type. The fix is to configure the server to serve .mjs with the right type. Some hosts, such as GitHub Pages, already handle this correctly.

⚠️ A common web snag: If a .mjs will not load in the browser and the console mentions a non-JavaScript MIME type, the file itself is fine. The server just needs to label .mjs as text/javascript.

🛠️ Common Issues

Problems with a .mjs seldom involve viewing the file, which any editor manages. They usually surface once the code is run.

Import statement errorA message that an import cannot be used outside a module means the code ran as CommonJS. The .mjs extension, or a module setting, fixes it.
Wrong MIME typeA browser refusing the file often points to the server labelling it wrongly. Serve .mjs as text/javascript.
Mixed module stylesBlending require with import in one project can clash. Keep a file to one style, using .mjs or .cjs to be explicit.
Path not foundES modules want the full filename in an import, including the .mjs, so leaving it off can break the import.

🔀 Related Formats

A .mjs sits among the other files you meet in a JavaScript project.

.jsThe general JavaScript file, treated as CommonJS by default in Node.js unless the project opts into modules.
.cjsThe explicit CommonJS counterpart to .mjs, always read with require and module.exports.
.tsA TypeScript file, a typed layer over JavaScript that compiles down to plain .js before it runs.
.mtsThe TypeScript take on an ES module, which the compiler turns into a .mjs file when it builds.
.jsonA data file often sat beside modules, holding configuration or content rather than runnable code.
.mapA source map, linking built code back to the original files to make debugging easier.

❓ Frequently Asked Questions

Any editor that handles text can open a .mjs, since the file is readable JavaScript. Notepad, TextEdit or Vim let you view or tweak the code immediately. Working on a module in earnest is nicer in an editor built for code, such as VS Code, Sublime or Atom, where colouring and hints help, or in an IDE like Visual Studio or WebStorm that also runs and debugs. Viewing a .mjs never executes it, though.

An MJS file is a JavaScript source code file written as an ES module, using the .mjs extension. Inside it is ordinary JavaScript in plain text, and the extension marks the file as a module so that tools treat it as ES module code. The m stands for module. It uses the import and export keywords to share code between files, and Node.js reads any .mjs as an ES module by default, without needing extra project configuration.

The difference is the module system, not the language. A .mjs is always an ES module, using import and export, and is read that way everywhere. A plain .js file uses the older CommonJS style by default in Node.js, with require and module.exports, unless the project opts into modules. ES modules also keep their top-level variables scoped to the file rather than the global space. Both hold JavaScript, but the extension signals how the code should be loaded.

Because a .js file was ambiguous. In Node.js it could follow either the older CommonJS style or the newer ES module style, depending on a project setting, so tools had no reliable way to tell them apart from the name alone. The .mjs extension fixes that by always meaning an ES module, so Node.js treats it as one without extra configuration. Its counterpart, .cjs, always means CommonJS. The extension is a clear label for how to load the file.

You run it with something that executes JavaScript. On a server or your own computer, Node.js runs a .mjs directly, with a command like node main.mjs, and treats it as an ES module on current versions without extra flags. In a web page, a browser runs one when it is loaded through a script tag marked as a module. Either way the file is being executed rather than just opened, which is a separate step from viewing the code.

For a quick look or a small change, a text editor such as Notepad, TextEdit or Vim is enough. Coders tend to reach for an editor built for the job, VS Code and Sublime and Atom among them, for its highlighting, or for an IDE such as Visual Studio or WebStorm that folds in running and debugging. Executing the module, though, means handing it to Node.js or a browser, so viewing and running can call for different tools.

ES module is short for ECMAScript module, the module system built into the JavaScript language standard. It arrived with ECMAScript 6 in 2015 and uses the import and export keywords to share code between files. It is the modern, official way to structure JavaScript, and it works in both browsers and Node.js. A .mjs file is simply a JavaScript file that uses this system, which is why the extension is often described as marking an ES module.

Yes, a browser can run a .mjs as a module. You load it in a web page through a script tag marked as a module, and the file can then use import to bring in other modules. One catch is that the server needs to send the file with a JavaScript media type, text/javascript, or the browser may refuse it. Loading a .mjs straight from your computer with a file path can also hit security limits, so serving it through a small web server is more reliable.

Usually because of a module mismatch. A message that an import statement cannot be used outside a module means the code ran as CommonJS instead of an ES module, which the .mjs extension or a module setting resolves. In a browser, a file rejected for a non-JavaScript type points to the server labelling .mjs wrongly, fixed by serving it as text/javascript. An import that omits the full filename, including the .mjs, can also fail, since ES modules want the complete path.

Opening a .mjs to read it in a text editor is safe, since it is just plain text. The care comes with running it, because a .mjs is JavaScript code that does whatever it is written to do. As with any script, only run a .mjs from a source you trust, and it is wise to read through an unfamiliar one before executing it with Node.js. Viewing the code carries no risk on its own, but executing untrusted code always does.

Both split JavaScript into modules, but with opposite styles. A .mjs is an ES module, using import and export, and Node.js reads it as ESM. A .cjs is a CommonJS module, using require and module.exports, and Node.js always reads it as CommonJS. The two extensions exist precisely so you can be explicit about which style a file uses, avoiding the ambiguity of a plain .js. In short, .mjs is the modern system and .cjs is the older one, each named so there is no doubt.

You can rename a .mjs to .js, but that alone does not change how the code runs, and it may reintroduce the ambiguity the .mjs extension was meant to remove. If you want the code to work as a plain .js, you also need the project set up for modules, or you rewrite the import and export lines into the CommonJS style with require and module.exports. So it is less a file conversion than a code change, since the extension reflects how the JavaScript is written.

Either works, and they solve the same problem differently. The .mjs extension marks one file as an ES module, so it is handy when a project is otherwise CommonJS but you want a single module file. Adding a "type": "module" line to package.json instead flips the whole project, so its .js files are all treated as ES modules. Many projects pick the package.json route and keep using .js, while .mjs stays useful for being explicit about one file regardless of the project setting.

Yes, if the importing file is itself running as an ES module, since import works between ES modules. A file that is running as CommonJS cannot use a plain import line to pull in a .mjs, though it can load one through a dynamic import instead. Whichever way, the import has to name the file in full, including the .mjs, or Node.js reports that it cannot find the module. Mixing the two module styles is where most of these errors come from.

A .mjs is a JavaScript ES module, ready to run as is. A .mts is the TypeScript equivalent, TypeScript source that is meant to be an ES module. You do not run a .mts directly, since the TypeScript compiler first turns it into a .mjs, which is the plain JavaScript that Node.js or a browser actually executes. So .mts is what you write in a TypeScript project, and .mjs is what it becomes after building. The pairing mirrors .cts compiling to .cjs on the CommonJS side.

📝 Summary

An MJS file is a JavaScript source code file written as an ES module, using the .mjs extension, where the m stands for module. Inside it is ordinary plain-text JavaScript, and the extension is a signal that the file uses the modern module style with the import and export keywords rather than the older CommonJS require and module.exports. The extension exists to end the ambiguity of a plain .js file, which Node.js could read as either style depending on project settings. Node.js treats any .mjs as an ES module by default, and its counterpart .cjs always means CommonJS. ES modules arrived with ECMAScript 6 in 2015, keep their top-level variables scoped to the file, and run in both Node.js and web browsers. A .mjs opens in any text editor, with a code editor or IDE bringing extra syntax help, and it runs under Node.js or inside a browser loaded as a module. When serving a .mjs to a browser, the server should label it text/javascript, or the file may be refused.