LottieFiles / dotlottie-web

Official LottieFiles player for rendering Lottie and dotLottie animations in the web. Supports React, Vue, Svelte, SolidJS and Web Components.
https://developers.lottiefiles.com/docs/dotlottie-player/
MIT License
191 stars 11 forks source link

Manual setWasmUrl causes fetch for wasm file for every animation [@lottiefiles/dotlottie-react] #402

Open aalcott14 opened 3 days ago

aalcott14 commented 3 days ago

Overview

I'm attempting to use DotLottieWorkerReact and use the setWasmUrl method to retrieve the wasm file from my own server rather than the public CDN (for security purposes). It seems to work except that the fetch to the wasm url gets made for every single animation rather than a single fetch, like what occurs if setWasmUrl is not invoked and defers to the CDN.

I'm wondering what is causing the fetch to get made subsequent times when this does not occur without the use of setWasmUrl.

Only a single fetch occurs when using DotLottieReact component instead of DotLottieWorkerReact

Here's an example of my code:

import React, { MutableRefObject, useEffect, useState } from 'react';
import { DotLottieWorker, DotLottieWorkerReact, DotLottieWorkerReactProps, setWasmUrl } from '@lottiefiles/dotlottie-react';
import wasmURL from '@lottiefiles/dotlottie-web/dist/dotlottie-player.wasm?url';

setWasmUrl(`${window.location.origin}${wasmURL}`);

export interface LottieWebWorkerProps extends Omit<DotLottieWorkerReactProps, 'dotLottieRefCallback'> {
  lottieRef: MutableRefObject<DotLottieWorker>
  onLoad?: () => void;
  onComplete?: () => void;
}

export default function LottieWebWorker({ lottieRef, onLoad, onComplete, ...rest }: LottieWebWorkerProps) {
  const [dotLottie, setDotLottie] = useState<DotLottieWorker | null>(null);

  useEffect(() => {
    if (dotLottie) {
      if (lottieRef) {
        lottieRef.current = dotLottie;
      }
      if (onLoad) {
        dotLottie.addEventListener('load', onLoad);
      }
      if (onComplete) {
        dotLottie.addEventListener('complete', onComplete);
      }
    }

    return () => {
      if (dotLottie) {
        if (onLoad) {
          dotLottie.removeEventListener('load', onLoad);
        }
        if (onComplete) {
          dotLottie.removeEventListener('complete', onComplete);
        }
      }
    }
  }, [dotLottie, onLoad, onComplete]);

  return (
    <DotLottieWorkerReact
      dotLottieRefCallback={setDotLottie}
      {...rest}
    />
  );
}

...

Labels

theashraf commented 10 hours ago

@aalcott14 fetching the WASM module should occur only once, even within a worker, as you mentioned, since all dotLottie instances created by workers share the same memory.

~The only exception is if you're using the workerId prop, which allows you to group animations into separate workers. Is that the case ?~

theashraf commented 10 hours ago

reproducible on the perf-test page

image
aalcott14 commented 26 minutes ago

Hi @theashraf, thanks for taking a look! Yes, as you can see on the perf test page, this issue becomes quite problematic from a performance perspective as the requests pile up