Skip to content

モジュールがデフォルトエクスポートしないエラーの解決方法

問題の説明

JavaScriptモジュールシステムを使用する際、次のエラーが発生することがあります:

SyntaxError: The requested module './TableCsv.js' does not provide an export named 'default'

このエラーは主に以下のような状況で発生します:

  • モジュールファイル(この場合 TableCsv.js)が export default を使用せずにクラスや関数を定義している
  • インポート側(main.js)で import X from 'module' 構文を使用している
  • モジュール内でエクスポートされていない変数やクラスを使用しようとしている

コード重複の追加問題

質問のコードでは、TableCsv.jsmain.js に重複したコードが含まれています:

  • 両方のファイルで tableRootcsvFileInput をクエリ
  • 両方のファイルで addEventListener を設定

この重複が原因で予期しない動作が発生する可能性があります。解決策の適用後に重複部分の削除が必要です。

エラーの原因分析

エラーの根本原因は以下の通りです:

  1. エクスポート宣言の欠如
    TableCsv.jsTableCsv クラスが定義されていますが、export キーワードが使われていません

  2. デフォルトエクスポートの誤解
    デフォルトエクスポート(export default ...)が存在しないにもかかわらず、デフォルトインポート構文(import X from ...)を使用

  3. モジュールシステムの不一致
    ファイルがESモジュール(import/export)として扱われる場合、従来のCommonJS形式(module.exports)とはエクスポート方法が異なります

解決方法

方法1: デフォルトエクスポートを使用する(推奨)

最も簡単な解決策は、TableCsv.js でクラスをデフォルトエクスポートすることです:

js
export default class TableCsv {
  // 既存のクラス実装をそのまま維持
  // ...
}
js
// デフォルトインポート({} は不要)
import TableCsv from "./TableCsv.js";

// 残りのコードは変更なし

なぜこれで解決するのか?

  • export default はモジュールの「主要なエクスポート」を定義します
  • import X from ... 構文はデフォルトエクスポート専用です
  • 1つのモジュールにデフォルトエクスポートは1つしか設定できません

方法2: 名前付きエクスポートを使用する

代わりの方法として、名前付きエクスポートを使用することも可能です:

js
export class TableCsv {  // exportキーワードを追加
  // 既存のクラス実装
  // ...
}
js
// 名前付きインポート({} が必須)
import { TableCsv } from "./TableCsv.js";

// 残りのコードは変更なし

エクスポート選択の注意点

名前付きエクスポートを使用する場合、インポート時には必ず中括弧{}を使用する必要があります。デフォルトエクスポートと名前付きエクスポートを同時に混在させることも可能ですが、混乱の元になるため推奨しません。

完全な修正コード

問題を完全に解決するには、重複コードの削除も必要です:

js
export default class TableCsv {
  constructor(root) {
    this.root = root;
  }

  update(data, headerColumns = []) {
    this.clear();
    this.setHeader(headerColumns);
    this.setBody(data);
  }

  clear() {
    this.root.innerHTML = "";
  }

  setHeader(headerColumns) {
    this.root.insertAdjacentHTML(
      "afterbegin",
      `
        <thead>
            <tr>
                ${headerColumns.map((text) => `<th>${text}</th>`).join("")}
            </tr>
        </thead>
      `
    );
  }

  setBody(data) {
    const rowsHtml = data.map((row) => {
      return `
            <tr>
                ${row.map((text) => `<td>${text}</td>`).join("")}
            </tr>
        `;
    });

    this.root.insertAdjacentHTML(
      "beforeend",
      `
        <tbody>
            ${rowsHtml.join("")}
        </tbody>
      `
    );
  }
}
js
import TableCsv from "./TableCsv.js";
import Papa from "papaparse"; // 必要に応じてPapaParseをインポート

const tableRoot = document.querySelector("#csvRoot");
const csvFileInput = document.querySelector("#csvFileInput");
const tableCsv = new TableCsv(tableRoot);

csvFileInput.addEventListener("change", (e) => {
  Papa.parse(csvFileInput.files[0], {
    delimiter: ",",
    skipEmptyLines: true,
    complete: (results) => {
      tableCsv.update(results.data.slice(1), results.data[0]);
    }
  });
});

よくある間違いと回避策

複数デフォルトエクスポートのエラー

js
export default class MyClass {} // デフォルトエクスポート
export default function myFunc() {} // エラー:デフォルトエクスポートは1つのみ

解決策

  • デフォルトエクスポートするのは1つのみ
  • 複数エクスポートする場合は名前付きエクスポートを使用
    js
    export class MyClass {}
    export function myFunc() {}

インポート方法の不一致

js
// デフォルトエクスポートされたクラスを...
// 誤った名前付きインポート
import { TableCsv } from './TableCsv.js' // エラー

// 正しいデフォルトインポート
import TableCsv from './TableCsv.js' // 正常動作

解決策

  • インポート方法はエクスポート方法と一致させる
  • IDEの自動補完機能を活用してエクスポートを確認

ブラウザ環境での注意点

HTMLファイルでモジュールを読み込む場合:

html
<!-- type="module" 属性を追加 -->
<script type="module" src="main.js"></script>

補足情報:モジュールシステムの違い

モジュールタイプエクスポート方法インポート方法主な使用環境
ESモジュールexport default Ximport X from 'module'ブラウザ、最新Node
(ESM)export { X }import { X } from 'module'
CommonJSmodule.exports = Xconst X = require('module')従来のNode環境
exports.X = ...const { X } = require(...)

まとめ

「モジュールがデフォルトエクスポートを提供しない」エラーを解決するには:

  1. TableCsv.js でクラスをエクスポートする

    js
    export default class TableCsv { ... }
  2. main.js で中括弧{}なしでインポートする

    js
    import TableCsv from './TableCsv.js'
  3. 重複するイベントリスナーコードを削除する

  4. HTMLファイルで <script type="module"> を忘れない

ESモジュールの仕様を正しく理解することで、モジュール間の連携がスムーズになり、この種のエラーを未然に防ぐことができます。