0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

.mjs ファイルは、JavaScriptのECMAScript Modules (ES Modules) 形式であることを明示するためのファイル拡張子です。ES Modulesは、現代のJavaScriptで推奨されるモジュールシステムであり、importexport 文を使用してモジュールを管理します。📦

.mjs ファイルが登場した背景 📜

歴史的に、Node.jsなどのJavaScript実行環境では CommonJS という異なるモジュールシステムが広く使われてきました。CommonJSでは require()module.exports を使用します。

しかし、ウェブブラウザや新しいJavaScriptの仕様では、ES Modules が標準となりました。ここで問題が発生しました。

  • .js ファイルの曖昧さ: ある .js ファイルがCommonJS形式なのか、ES Modules形式なのかを、ファイルの内容を解析せずに判断するのは難しいです。
  • Node.jsの互換性問題: Node.jsはCommonJSが主流だったため、ES Modulesの導入には互換性の課題がありました。

この問題を解決するために、Node.jsコミュニティを中心に .mjs 拡張子("Module JavaScript" の略と言われることが多い)が導入されました。これにより、ファイル拡張子を見ただけで、それがES Modules形式のファイルであることが明確にわかるようになりました。


.mjs ファイルと .js ファイルの主な違い ✨

特徴 .mjs ファイル .js ファイル(デフォルト)
モジュール形式 ECMAScript Modules (ES Modules) として扱われることが保証されます。import / export 構文が機能します。 Node.js環境では、デフォルトで CommonJS として扱われます(ただし、package.json"type": "module" が設定されているディレクトリ内ではES Modulesとして扱われることもあります)。<br>ブラウザ環境では、HTMLの <script type="module"> で読み込まれた場合はES Modules、それ以外は従来のスクリプトとして扱われます。
厳格モード デフォルトで厳格モード (strict mode) で実行されます。 デフォルトでは厳格モードではありません(ただし、CommonJSモジュールは暗黙的に厳格モードになることがあります)。
this の挙動 最上位スコープの thisundefined です。 最上位スコープの thismodule.exports を指します。
解決ルール 異なる解決ルールが適用される場合があります(例: .js, .json, .node の順で解決するなど)。 異なる解決ルールが適用される場合があります(例: .js, .json, .node の順で解決するなど)。

.mjs ファイルの活用シナリオ 🚀

  1. Node.js 環境でのES Modulesの使用:
    Node.jsの古いバージョンや、package.json"type": "commonjs" が設定されているプロジェクトで、ES Modulesを明示的に使用したい場合に .mjs 拡張子を利用します。

    // my-module.mjs (ES Modules)
    export function greet(name) {
      return `Hello, ${name}!`;
    }
    
    // app.js (CommonJS環境から.mjsを読み込む場合)
    // Node.js v13.2.0 以降では、動的 import() で .mjs を読み込めます
    async function run() {
      const { greet } = await import('./my-module.mjs');
      console.log(greet('World')); // Hello, World!
    }
    run();
    
  2. ブラウザ環境での明確化:
    ブラウザで直接ES Modulesを読み込む場合、HTMLの <script type="module" src="app.mjs"></script> とすることで、そのファイルがES Modulesであることをより明確に示せます(ただし、.js 拡張子でも type="module" があればES Modulesとして扱われます)。

  3. モジュールバンドラーとの連携:
    WebpackやRollupなどのモジュールバンドラーは、.mjs 拡張子をES Modulesとして正しく認識し、処理してくれます。これにより、様々なモジュール形式が混在するプロジェクトでも、バンドラーが適切に処理できるようになります。


.mjs ファイルのサンプルコードと使用した場合・使用しなかった場合の比較 📊

ここでは、Node.js環境におけるES Modulesの扱いを比較してみましょう。

📌 サンプルコード (.mjs ファイルを使用した場合)

message.mjs:

// これはES Modules形式
export const hello = "Hello from .mjs!";
export function sayGoodbye() {
  return "Goodbye from .mjs!";
}

app.js:

// CommonJS環境のファイル
// .mjs ファイルは、Node.jsの動的 import() を使って読み込む
async function run() {
  try {
    const { hello, sayGoodbye } = await import('./message.mjs');
    console.log(hello);         // 出力: Hello from .mjs!
    console.log(sayGoodbye());  // 出力: Goodbye from .mjs!
  } catch (error) {
    console.error("Error importing .mjs:", error);
  }
}

run();

// CommonJS形式で何かをエクスポートする例 (app.js自体はCommonJS)
module.exports = {
  appName: "My Hybrid App"
};

実行コマンド:
node app.js

この場合、app.js はCommonJSモジュールとして実行されつつ、import() を使って .mjs ファイルをES Modulesとして非同期に読み込み、そのエクスポートされた値を利用できます。


📌 .mjs ファイルを使用しなかった場合の比較(.js ファイルと type: "module"

Node.jsでES Modulesを.js ファイルで扱いたい場合、最も一般的な方法は、プロジェクトの package.json"type": "module" を追加することです。これにより、そのディレクトリ内(およびサブディレクトリ)のすべての .js ファイルがデフォルトでES Modulesとして扱われるようになります。

package.json:

{
  "name": "my-es-module-app",
  "version": "1.0.0",
  "type": "module", //  これが重要 
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  }
}

message.js:

// package.jsonで "type": "module" が設定されているので、これはES Modules形式
export const hello = "Hello from .js (ESM)!";
export function sayGoodbye() {
  return "Goodbye from .js (ESM)!";
}

app.js:

// package.jsonで "type": "module" が設定されているので、これもES Modules形式
import { hello, sayGoodbye } from './message.js'; // ✨ .js 拡張子が必要になることが多い ✨

console.log(hello);         // 出力: Hello from .js (ESM)!
console.log(sayGoodbye());  // 出力: Goodbye from .js (ESM)!

// ES Modules形式で何かをエクスポートする例
export const appVersion = "1.0";

実行コマンド:
node app.js

この設定では、すべての .js ファイルがES Modulesとして扱われるため、CommonJSの require()module.exports を使用するとエラーになります。プロジェクト全体をES Modulesに移行する場合に適しています。


.mjs 拡張子は、CommonJSが主流の環境でES Modulesを部分的に導入したい場合や、ファイル形式を明確に識別したい場合に特に有効です。一方、プロジェクト全体をES Modulesに移行する場合は、package.json"type": "module" を設定し、すべての .js ファイルをES Modulesとして扱うのが一般的になっています。どちらの方法を選ぶかは、プロジェクトの要件や環境によって異なります。 🚨

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?