【JavaScript】ES Modulesの基本!import/exportでコードを分割し、Webサイトを効率化する方法
※本ページのリンクにはプロモーションが含まれています。
こんにちは、Ryohei(@ityryohei)です!
JavaScriptのアプリケーションが大きくなるにつれて、コードを小さなファイルに分けて管理するモジュールシステムは必須の技術です。現代のWeb開発では、ECMAScriptの標準であるES Modules (ESM) がその役割を担います。
ESMの基本を学ぶことは、コードを整理し、Webサイトの表示速度を上げるための土台となります。
本記事では、ESMの基本的な使い方であるimportとexportの構文から、ブラウザが裏側でモジュールを読み込む仕組み(非同期ロード)、そしてWebサイトの初期ロードを速くするテクニックを解説します。
コードが長くなりすぎてファイルが読みにくいけど、ファイルを分けたらどうやって繋げばいいんだろう?
上記の疑問にお答えします。
1. なぜコードを分割し、ES Modulesを使うのか
アプリ開発では、すべてのコードを一つの大きなファイル(main.jsなど)に書くのは非効率です。
コード分割のメリット
- 管理のしやすさ:
関連する機能ごとにファイルを分けることで、コードが見やすく、修正しやすくなります。 - 名前の衝突防止:
ファイルごとに変数の適用範囲(スコープ)が区切られるため、他のファイルで定義した変数名と間違えて使ってしまう「名前の衝突」を防げます。 - 効率化(Tree Shaking):
使っていないコードを最終的なファイルから取り除く「Tree Shaking」という技術が可能になり、Webサイトの読み込みが速くなります。
ES Modules(ESM)は、このコード分割を実現するためのブラウザ標準の仕組みです。
2. ES Modulesの基本:exportとimportの使い方
ESMは、データをエクスポート(外に出す)する側と、それをインポート(取り込む)する側に分かれて機能します。
2-1. export:他のファイルで使えるようにする
他のファイルで利用したい関数や定数には、exportキーワードをつけます。
名前付きエクスポート (Named Exports)
複数の要素をエクスポートする標準的な方法です。
JavaScript(utils.js)
// 他のファイルで「PI」という名前で使えるようになる
export const PI = 3.14;
// 他のファイルで「calculateArea」という名前で使えるようになる
export function calculateArea(radius) {
return PI * radius * radius;
}
デフォルトエクスポート (Default Export)
ファイル内で最も主要な機能を一つだけエクスポートする場合に使います。
JavaScript(logger.js)
const logger = (message) => console.log(`[LOG]: ${message}`);
// このファイルで最も重要な関数としてエクスポート
export default logger;
2-2. import:他のファイルから機能を取り込む
exportされた機能を取り込むには、importキーワードを使います。
名前付きインポート
exportされたときと同じ名前で、{}(波括弧)を使って受け取ります。
JavaScript(app.js)
// utils.js から PI と calculateArea を取り込む
import { PI, calculateArea } from './utils.js';
console.log(calculateArea(5));
デフォルトインポート
default exportでエクスポートされたものは、{}を使わず、自由に名前を付けて受け取ることができます。
JavaScript(app.js)
// logger.js から default export された関数を log という名前で受け取る
import log from './logger.js';
log('アプリケーション開始');
3. ブラウザがモジュールを読み込む仕組み
ESMがWebサイトの効率化に貢献できるのは、ブラウザでの読み込み方に秘密があります。
3-1. HTMLでの読み込み方
HTML内でESMを使うには、<script>タグに type="module" 属性をつけます。
HTML
<script type="module" src="main.js"></script>
type="module" をつけると、そのスクリプトは以下の特徴を持ちます。
- 非同期ロード:
他のHTMLの読み込みや解析をブロックせず、ファイルは非同期で読み込まれます。 - 自動解決:
main.jsが他のファイルをimportしていれば、ブラウザはそれらのファイルも自動で探し、並行して読み込みます。
3-2. ライブバインディング(参照の共有)
ESMは、インポートした値とエクスポート元の値を参照で繋げます(ライブバインディング)。
つまり、エクスポート元のファイルで値が変わると、インポートした側のファイルでも、その値がリアルタイムで更新されます。
JavaScript(counter.js)
// カウンターの値
export let count = 0;
export const increment = () => { count++; };
JavaScript(app.js)
import { count, increment } from './counter.js';
console.log(count); // -> 0
increment(); // count の値を変更
console.log(count); // -> 1 (変更が反映されている)
4. Webサイトの初期ロードを速くするテクニック
ESMの応用として、Webサイトの初期ロードを速くする「遅延ロード」のテクニックを見てみましょう。
動的インポート(import())とは
通常のimport文はファイルの冒頭に書かれ、ページが読み込まれた瞬間に実行されます。これに対し、動的インポート (import()) は、コードの実行中に必要なときだけモジュールを非同期で読み込むための仕組みです。
動的インポートは、モジュール全体をロードするPromiseを返します。
JavaScript
// 初期画面には不要な大きなファイルを、ボタンクリック時に読み込む例
document.getElementById('lazy-button').addEventListener('click', async () => {
// 1. ファイルが非同期で読み込まれる(Promise)
const module = await import('./large-chart-library.js');
// 2. ロード完了後、モジュール内の関数を実行
module.renderChart();
});
コード分割(Code Splitting)による効率化
この動的インポートを活用することで、Webサイトの初期ロードに必要なファイルサイズを大幅に減らせます。
- 効果:
アプリケーションの初期画面の表示に不要な大きなコードを別のファイルに分離(コード分割)し、ユーザーがその機能を使おうとしたときだけロードします。
これにより、ユーザーはより早くメイン画面を見ることができ、Webサイトの体感速度が向上します。
最後に
ES Modulesの基本を理解することは、モダンなWeb開発で必須のステップです。
export/import: コードを機能ごとに分割し、整理しましょう。- ライブバインディング: 値が参照で共有されることを意識してコードを書きましょう。
- 動的インポート: 初期ロードに不要な大きなモジュールは
import()で遅延ロードし、Webサイトを効率化しましょう。
これらの知識を活かし、分かりやすく、そして高速に動作するWebアプリケーションを構築してください。
以上、ES Modulesを活用したコード分割とWebサイト効率化の基本のご紹介でした!