モジュールの遅延読み込み
アプリケーションの初期読み込みを高速化するために、すべてのモジュールを最初から読み込むのではなく、必要になったタイミングで読み込む「遅延読み込み」が効果的です。
遅延読み込みとは
ページの初期表示に必要なコードだけを先に読み込み、その他の機能は後から読み込む手法です。
即時読み込み
すべてのモジュールを最初に読み込む。初期表示が遅くなる可能性がある。
遅延読み込み
必要なモジュールだけを必要なタイミングで読み込む。初期表示が高速化される。
動的インポートによる遅延読み込み
import() 関数を使用して、必要になった時点でモジュールを読み込みます。
// ボタンクリック時に初めてモジュールを読み込む
document.getElementById('chart-btn').addEventListener('click', async () => {
const { Chart } = await import('./chart.js');
const chart = new Chart('#container');
chart.render();
});ルートベースの遅延読み込み
SPA(Single Page Application)では、ページ遷移時に必要なコンポーネントだけを読み込むパターンが一般的です。
const routes = {
'/': () => import('./pages/Home.js'),
'/about': () => import('./pages/About.js'),
'/contact': () => import('./pages/Contact.js'),
'/dashboard': () => import('./pages/Dashboard.js')
};
async function navigate(path) {
const loader = routes[path];
if (loader) {
const module = await loader();
renderPage(module.default);
}
}
// ナビゲーションイベントで呼び出す
window.addEventListener('popstate', () => navigate(location.pathname));条件付き読み込み
特定の条件を満たした場合のみ、重いモジュールを読み込みます。
async function initEditor() {
const textarea = document.querySelector('textarea');
if (textarea && textarea.dataset.rich === 'true') {
// リッチエディタが必要な場合のみ読み込む
const { RichEditor } = await import('./RichEditor.js');
return new RichEditor(textarea);
}
return textarea;
}Intersection Observer との組み合わせ
要素が画面内に入ったタイミングでモジュールを読み込むパターンです。
const observer = new IntersectionObserver(async (entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
const element = entry.target;
if (element.dataset.component === 'gallery') {
const { Gallery } = await import('./Gallery.js');
new Gallery(element);
observer.unobserve(element);
}
}
}
});
// 遅延読み込み対象の要素を監視
document.querySelectorAll('[data-lazy]').forEach(el => {
observer.observe(el);
});プリロードによる最適化
遅延読み込みでも、ユーザーが使いそうな機能は事前にプリロードしておくと、体験が向上します。
<!-- 後で使う可能性が高いモジュールをプリロード -->
<link rel="modulepreload" href="./Chart.js">// マウスホバー時にプリロードを開始
document.getElementById('chart-btn').addEventListener('mouseenter', () => {
import('./Chart.js'); // プリロード(結果は使わない)
});
document.getElementById('chart-btn').addEventListener('click', async () => {
// キャッシュから即座に取得できる
const { Chart } = await import('./Chart.js');
new Chart('#container').render();
});ローディング表示
モジュールの読み込み中は、ユーザーにフィードバックを表示しましょう。
async function loadFeature() {
const container = document.getElementById('feature');
container.innerHTML = '<div class="loading">読み込み中...</div>';
try {
const { Feature } = await import('./Feature.js');
container.innerHTML = '';
new Feature(container);
} catch (error) {
container.innerHTML = '<div class="error">読み込みに失敗しました</div>';
}
}メリット
初期読み込みの高速化、必要なリソースだけをダウンロード、帯域の節約
注意点
ネットワーク遅延による待ち時間、適切なローディング UI の必要性
遅延読み込みを適切に活用することで、大規模なアプリケーションでも高速な初期表示を実現できます。