Next.js Discord

Discord Forum

Uncaught (in promise) Error: Cannot find module as expression is too dynamic

Unanswered
HeapReaper posted this in #help-forum
Open in Discord
Hi!
So i'm trying to import FFMPEG into my app on the client side (i first made it just pure Preact but moving to NextJS.
I use this code:

  const ffmpegRef = useRef<FFmpeg | null>(null);
  const messageRef = useRef<HTMLParagraphElement | null>(null);

  useEffect(() => {
    const loadFFmpeg = async () => {
      const { FFmpeg } = await import('@ffmpeg/ffmpeg');
      const { toBlobURL } = await import('@ffmpeg/util');

      const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm';
      const ffmpeg = new FFmpeg();

      ffmpeg.on('log', ({ message }) => {
        if (messageRef.current) messageRef.current.innerHTML = message;
      });

      await ffmpeg.load({
        coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
        wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
        workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript'),
      });

      ffmpegRef.current = ffmpeg;
      setLoaded(true);
    };

    loadFFmpeg();
  }, []);

But i get the error:
Uncaught (in promise) Error: Cannot find module as expression is too dynamic page.tsx:30:19
    loadFFmpeg page.tsx:30
    AsyncFunctionThrow self-hosted:804
    (Async: async)
    useEffect page.tsx:40
    react_stack_bottom_frame react-dom-client.development.js:23668

Who can help?

9 Replies

Hi, i found a way! Gonna post it tomorrow when i'm out of bed!
@Dutch Probably its cuz of await import, if its still a problem
Oh didnt fix it.
I atm got:
  const loadFfmpeg = async () => {
    try {
      console.log("Loading ffmpeg...");

      const baseURL =
        "https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/umd";

      const ffmpeg = new FFmpeg();

      ffmpeg.on("log", ({ message }) => {
        if (messageRef.current) {
          messageRef.current.innerHTML = message;
        }
        console.log(message);
      });

      await ffmpeg.load({
        coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"),
        wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, "application/wasm"),
        workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, "text/javascript"),
      });

      ffmpegRef.current = ffmpeg;
      console.log("loaded ");
    } catch (error) {
      console.error(error);
    }
  };

When running npm run build i get the
Error occurred prerendering page "/afbeeldingen/converteer". Read more: https://nextjs.org/docs/messages/prerender-error
Error: ffmpeg.wasm does not support nodejs
    at new b (.next/server/chunks/ssr/[root-of-the-server]__a0e27f02._.js:1:122226)
    at i (.next/server/chunks/ssr/[root-of-the-server]__365f6c57._.js:1:850) {
  digest: '4143034953'
}
Export encountered an error on /afbeeldingen/converteer/page: /afbeeldingen/converteer, exiting the build.
 ⨯ Next.js build worker exited with code: 1 and signal: null
aerobytes@pop-os:~/WebstormProjects/KlikTools$ 
@Dutch It says the problem, ffmpeg.wasm doesnt support nodejs
Yeah I know. Tho i try to load ffmpeg on client side. It's get processed by nextjs and don't want that
@Dutch It says the problem, ffmpeg.wasm doesnt support nodejs
My pure Preact frontend works fine with:
  // Load external files after page load
  setTimeout(async () => {
    const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm';
    const ffmpeg = ffmpegRef.current;

    ffmpeg.on('log', ({ message }) => {
      if (messageRef.current) messageRef.current.innerHTML = message;
    });

    await ffmpeg.load({
      coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
      wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
      workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript'),
    });
    setLoaded(true);
  }, 400);

I add it in NextJS: Get the NodeJS error.
I have "use client"; in it and still NextJS is trying to execute it/render it
I now got:
/app/images/compress/page.tsx:
"use client"

import dynamic from "next/dynamic";

const CompressPage = dynamic(() => import("@/components/pages/compressPage"), { ssr: false });

export default function Page() {
  return <CompressPage />;
}

And then the compressPage:
"use client";

import { useRef, useEffect, useState } from "react";
import { toBlobURL } from "@ffmpeg/util";
import { FFmpeg } from "@ffmpeg/ffmpeg";

export default function CompressPage() {
  const ffmpegRef = useRef<FFmpeg | null>(null);
  const messageRef = useRef<HTMLDivElement>(null);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const loadFFmpeg = async () => {
      const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm';
      const ffmpeg = new FFmpeg();

      ffmpeg.on('log', ({ message }) => {
        if (messageRef.current) messageRef.current.innerHTML = message;
        console.log(message);
      });

      await ffmpeg.load({
        coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
        wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
        workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript'),
      });

      ffmpegRef.current = ffmpeg;
      setLoaded(true);
    };

    const timer = setTimeout(() => {
      void loadFFmpeg();
    }, 400);

    return () => clearTimeout(timer);
  }, []);

  return <div ref={messageRef}>{loaded ? "FFmpeg loaded" : "Loading FFmpeg..."}</div>;
}

But now getting again:
Uncaught (in promise) Error: Cannot find module as expression is too dynamic
@HeapReaper I now got: `/app/images/compress/page.tsx`: tsx "use client" import dynamic from "next/dynamic"; const CompressPage = dynamic(() => import("@/components/pages/compressPage"), { ssr: false }); export default function Page() { return <CompressPage />; } And then the `compressPage`: tsx "use client"; import { useRef, useEffect, useState } from "react"; import { toBlobURL } from "@ffmpeg/util"; import { FFmpeg } from "@ffmpeg/ffmpeg"; export default function CompressPage() { const ffmpegRef = useRef<FFmpeg | null>(null); const messageRef = useRef<HTMLDivElement>(null); const [loaded, setLoaded] = useState(false); useEffect(() => { const loadFFmpeg = async () => { const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm'; const ffmpeg = new FFmpeg(); ffmpeg.on('log', ({ message }) => { if (messageRef.current) messageRef.current.innerHTML = message; console.log(message); }); await ffmpeg.load({ coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'), wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'), workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript'), }); ffmpegRef.current = ffmpeg; setLoaded(true); }; const timer = setTimeout(() => { void loadFFmpeg(); }, 400); return () => clearTimeout(timer); }, []); return <div ref={messageRef}>{loaded ? "FFmpeg loaded" : "Loading FFmpeg..."}</div>; } But now getting again: `Uncaught (in promise) Error: Cannot find module as expression is too dynamic`
Dutch
Yea you should import things via script tag or regular imports, no need to inline links