plyr-react icon indicating copy to clipboard operation
plyr-react copied to clipboard

"ReferenceError: document is not defined" in Next.js13 & 14

Open eliyo opened this issue 8 months ago • 14 comments

I am using plyr-react in a Next.js 14.0.1 environment (also tried with v13) and pages using plyr-react (5.3.0) fail to load or build with errors of type "ReferenceError: document is not defined" node_modules\plyr\dist\plyr.js:302:21

From my understanding, it seems the runtime tries to access the document object where there isn't one, like when running in a server environment. These errors can be fixed by checking validity of the document object before accessing it, but I don't think this is a proper fix, it seems the code is being run within a context it shouldn't be run into.

Windows 10, Node.js 21.1.0, Next.js 14.0.1, plyr-react 5.3.0, react 18.2.0

FYI I didn't have this problem when I worked on my site about 6 months ago, but now I upgraded everything I have it all the time, this blocks the build.

Steps to reproduce:

  1. install latest next.js and example app using: npx create-next-app@latest
  2. npm install plyr-react
  3. into the app's src/app/page.tsx, import plyr and and a <Plyr> tag in the Home function.
import Plyr from "plyr-react"
import "plyr-react/plyr.css"
(...)
<Plyr (...) />
  1. npm run dev
  2. open page in browser and see the error "ReferenceError: document is not defined"

eliyo avatar Nov 01 '23 17:11 eliyo

Same issue here. No idea what changed, please let me know if there's a package update that broke Plyr...

maxiedaniels avatar Nov 13 '23 21:11 maxiedaniels

@maxiedaniels @eliyo @Clueed
I have created discussing on nextjs repo

https://github.com/vercel/next.js/discussions/58911

please add more question and details also there

chintan9 avatar Nov 26 '23 02:11 chintan9

@maxiedaniels @eliyo @Clueed I have created discussing on nextjs repo

vercel/next.js#58911

please add more question and details also there

I don't know if this is an error due to nextjs version or your source code. But this error appears in nextjs 14.0.2 and above, but 14.0.1 still works normally.

timomedia avatar Dec 08 '23 06:12 timomedia

The error disappeared for me, no idea why. I had already tried deleting node_modules and my package lock file, but it hadn’t fixed it. I gave up and then somehow a day later I realized the error had disappeared.

maxiedaniels avatar Dec 08 '23 06:12 maxiedaniels

Also getting this error but with Remix

the-rich-piana avatar Jan 04 '24 21:01 the-rich-piana

same, got this error with nextjs 14.0.2

DarKS4ys avatar Jan 07 '24 09:01 DarKS4ys

same, got this error with nextjs 14.0.2 @chintan9 It only has errors with version 14.0.2 and above. Even the latest version 14.1.0 still has this error, however next.js seems to ignore it and allow buid.

timomedia avatar Jan 19 '24 07:01 timomedia

@timomedia it allows me to run npm run dev if I recall but I can’t do an actual build or deploy on vercel

maxiedaniels avatar Jan 19 '24 15:01 maxiedaniels

Hello, To fix it, make it client a component and use next dynamic import

const Plyr = dynamic(() => import("plyr-react"), { ssr: false });

it should work ;)

sekmet avatar Feb 05 '24 15:02 sekmet

Hello, To fix it, make it client a component and use next dynamic import

const Plyr = dynamic(() => import("plyr-react"), { ssr: false });

it should work ;)

This works to render, but it doesn't seem possible to get the ref to to the component. If you just attach the ref prop you get Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()

All my attempts beyond this to dynamically import usePlyr and do React.forwardRef() have failed, as well as all attempts to do a basic forwarded-ref component.

Currently stuck with not being able to use this library, which is a bummer.

c0bra avatar Feb 06 '24 18:02 c0bra

I was getting this problem too but I now resolved it (I think). Here's an example component if it helps anyone out there:

"use client";

import { FC } from "react";
import dynamic from "next/dynamic";
import "plyr-react/plyr.css";

const Plyr = dynamic(async () => await import("plyr-react"), { ssr: false });

type Video = {
  id: string;
  source: Plyr.Provider;
};

type Props = {
  video?: Video;
};

const VideoPlayer: FC<Props> = ({ video, ...rest }) => {
  return video?.id && video?.source ? (
    <Plyr
      {...rest}
      source={{
        type: "video",
        sources: [{ src: video.id, provider: video.source }],
      }}
      options={{
        controls: [
          "play",
          "play-large",
          "progress",
          "current-time",
          "mute",
          "volume",
          "fullscreen",
        ],
      }}
    />
  ) : null;
};

export default VideoPlayer;

Interestingly, if I add className onto the <Plyr /> component, it completely breaks it. Very odd. e.g. <Plyr className="this-will-break" />. Perhaps usage of the hook might be better for these cases?

michaelpumo avatar Feb 20 '24 21:02 michaelpumo

The dynamic load fixed it for me (const Plyr = dynamic(() => import("plyr-react"), { ssr: false });) edit I was getting a VERY weird bug that was breaking fast refresh and also an entire component, turns out it was this fix. So i had to do:

const PlyrComponent = React.useMemo(() => { return dynamic(() => import("plyr-react"), { ssr: false }); }, []);

And then <PlyrComponent ...> instead of <Plyr ...>

Just sharing in case someone else has the same bug!

maxiedaniels avatar Feb 21 '24 06:02 maxiedaniels

@maxiedaniels @michaelpumo It really doesn't work. I tried using dynamic but it didn't work. I created a component called Player to use in different pages and using it the way you do doesn't work at all. Below is my original code that tried to use dynamic

"use client"
import React, { useEffect, useRef } from "react";
import dynamic from "next/dynamic";
import Hls from "hls.js";

const PlyrComponent = dynamic(() => import("plyr-react"), { ssr: false });
export default function Player({ videoUrl, poster }) {
    const option = {
        autoplay: false,
        controls: [
            'rewind',
            'play',
            'fast-forward',
            'progress',
            'current-time',
            'duration',
            'mute',
            'volume',
            'settings',
            'quality',
            'fullscreen',
        ],
    };
    const ref = useRef(null);

    useEffect(() => {
        const loadVideo = async () => {
            if (ref.current && typeof window !== 'undefined') {
                const plyr = ref.current.get('plyr');
                if (plyr) {
                    var hls = new Hls();
                    hls.loadSource(videoUrl);
                    hls.attachMedia(plyr.media);

                    hls.on(Hls.Events.MANIFEST_PARSED, function () {
                        plyr.play();
                    });
                }
            }
        };
        loadVideo();
    }, [videoUrl]);
    return (
        <PlyrComponent
            ref={ref}
            playsInline
            source={{
                type: "video",
                sources: [{ src: videoUrl, type: 'application/vnd.apple.mpegurl' }],
            }}
            poster={poster}
            options={option}
        />
    );
}

timomedia avatar Mar 23 '24 05:03 timomedia