みかづきブログ・カスタム

基本的にはちょちょいのほいです。

Next.js + PixiJSでPIXI.loaders.Loaderを使った際、ホットリロード時に'Error: Resource named "RESOURCE_NAME" already exists.' となるのを防ぐ 🛡

f:id:kimizuka:20210103011013j:plain


ことの発端

Next.js + PixiJSでサイトをつくっていて、

useEffect(() => {
  if (!app) {
    return;
  }

  app.loader.add('resource-1', '/resource/1.png')
            .load((loader, resources) => {
              setResources(resources);
            });
  }
}, [app]); // appは一度しか登録されないし更新されない

みたいな感じのコードを書いた時、更新箇所によってはホットリロード時に、PIXI.loaders.Loaderがリソースを登録しなおそうとしてしまい、

'Error: Resource named "RESOURCE_NAME" already exists.'

と、エラーになるので非常に困ってました。

対策1(没案)

おそらくホットリロードが効く開発時しか困ることはないと思ったので、

useEffect(() => {
  if (!app) {
    return;
  }

  try {
    app.loader.add('resource-1', '/resource/1.png')
              .load((loader, resources) => {
                setResources(resources);
              });
  } catch (err) {
    console.error(err);
  }
}, [app]);

という感じでtry-catchで囲ってしまうことも検討したのですが、本当にエラーの時に握り潰してしまうのはよくなさそうなのでやめました。
(本当のエラーが拾えるかは謎ですが)

対策2(採用案)

console.dir(app.loader);

で、loaderの中身をみたところ、resetというメソッドを見つけたので、

useEffect(() => {
  if (!app) {
    return;
  }

  app.loader.reset()
            .add('resource-1', '/resource/1.png')
            .load((loader, resources) => {
              setResources(resources);
            });
  }
}, [app]);

という感じで毎回リセットしてから使うことにしました。

ドキュメントで確認したところ、resetというメソッドは見つからず、

pixijs.download

継承元のREADMEにも記載は見つからなかったのですが、

github.com

継承元のソースコードに記載を見つけました。

github.com

/**
 * Resets the queue of the loader to prepare for a new load.
 */
reset(): this
{
    this.progress = 0;
    this.loading = false;

    this._queue.reset();
    this._queue.pause();  

と書いてあるので、メソッドチェーンも効きますし、queueを空にしてくれるメソッドのようです。