Nuxt.jsでmp3をassetsディレクトリから読み込む方法【2021年版】

意外と苦戦したので、その記録をここに記します。

環境

npm: 6.14.8
Nuxt.js: 2.15.3
mode: Universal (SSR)

まずは、公式ドキュメントを確認!

Vue,Nuxtは公式ドキュメントが充実&分かりやすいので、何か調べたいことがあると公式ドキュメントを確認しています。(もちろん、Vue,Nuxtに限らず基本的に公式ドキュメントを見た方がいいよね。)

はい、見つけました。ばっちり知りたいことが書いてありました。

assets ディレクトリからオーディオファイルを読み込む - Nuxt.js

オーディオファイルを読み込むにはWebpackの設定を拡張する必要があるらしく、そのためにnuxt.config.jsを以下のように修正します。

export default {
  build: {
    extend(config, ctx) {
      config.module.rules.push({
        test: /\.(ogg|mp3|wav|mpe?g)$/i,
        loader: 'file-loader',
        options: {
          name: '[path][name].[ext]',
        },
      })
    },
  }
}


これで解決、、、?

と思ったら、

僕の環境では、全然読み込んでくれない!!!!!!

色んな記事を見てもこれで上手くいってるようでしたが、僕の環境ではダメでした、、、

では、どうしたのか?


色々調べた結果、以下のページを発見しました。

'src' of img tag become src="[object Module]" in browser · Issue #1612 · vuejs/vue-loader

そこに興味深いことが書かれていました。以下引用。

It's because in @vue/component-compiler-utils we transformed the asset urls to require statements, which expect CommonJS modules, while the recent major release of url-loader emits ES modules by default.


DeepL翻訳で日本語に翻訳すると、

これは、@vue/component-compiler-utilsで、アセットのURLをrequire文に変換しているためで、このrequire文はCommonJSモジュールを期待していますが、最近のメジャーリリースのurl-loaderはデフォルトでESモジュールを出力します。


細かいところはよく理解していないのですが、要するに、CommonJSモジュールを期待しているところにESモジュールで出力してしまっていること、これが原因であるということを理解しました。

なので、Webpackの設定をCommonJSモジュールを出力するように修正しました。

export default {
  build: {
    extend(config, ctx) {
      config.module.rules.push({
        test: /\.(ogg|mp3|wav|mpe?g)$/i,
        loader: 'file-loader',
        options: {
          name: '[path][name].[ext]',
     esModule: false, // ←ここに追加!
        },
      })
    },
  }
}


これで、上手く読み込まれました!やったー!!!!

結論

公式ドキュメントの情報も古いことがある。githubのissuesすごい。