GriffinJohnston / ldrs

Modern, tree-shakeable loader & spinner web components. Made with CSS, HTML and SVG. https://uiball.com/ldrs
MIT License
1.75k stars 54 forks source link

ReferenceError with Next.js13 or 14 #21

Closed Brightlight0721 closed 8 months ago

Brightlight0721 commented 9 months ago
⨯ node_modules\ldrs\dist\lib\LdrsBaseElement.js (1:16) @ HTMLElement
⨯ ReferenceError: HTMLElement is not defined

Next.js13 and 14 with ldrs occur errors above show in a console when npm run dev and loaders show in dev mode but not in production mode.

GriffinJohnston commented 9 months ago

Hi, did you follow the Nextjs platform guide? https://github.com/GriffinJohnston/ldrs/blob/main/framework-guides.md

milindgoel15 commented 8 months ago

Great work on the loaders & website.

Although it would be much better if it were a proper react component so it can be rendered in any type of component since the raw code does.

GriffinJohnston commented 8 months ago

It can be rendered in any type of component. The current issue is with SSR. There are easy workarounds though. Anyway, I'm closing this issue since I haven't heard from OP, and I think most likely they just need to follow the Next platform guide. Let me know if I'm wrong though!

milindgoel15 commented 8 months ago

It can be rendered in any type of component. The current issue is with SSR.

Only said because the raw code (HTML, CSS) works in SSR (nextjs 14 with server components).

Also, more like a suggestion, instead of having to register a loader, expose the loaders as direct component that can be just imported and used directly. (PS; I am not totally sure if this defeats the web components architecture. tbh I hardly understood the reason of web components. Please correct me if I am wrong.)

example:

import { Ring } from "ldrs";

const SomeComponent = () => {
   return (
      <>
         <Ring />
      </>
   )
}
GriffinJohnston commented 8 months ago

I totally hear you. Web components have to be registered before they work, hence that step. So they're definitely a little less convenient than just using a React component.

The reason I built this library using web components is so that it can be used in any context. So while there's more friction in SSR environments, the components themselves can be used with React, Vue, Svelte, Solid, Qwik, etc. You're not wrong that this is a trade-off though. Hopefully web components will integrate well with SSR some day (see https://developer.chrome.com/docs/css-ui/declarative-shadow-dom), but at the moment it's a bit annoying for sure.

That being said, the components are really just a convenience. As you've pointed out, it's always possible to copy/paste the HTML and CSS. Still a lot easier than spending hours hand-crafting your own elaborate CSS and SVG animation ;)

milindgoel15 commented 8 months ago

Thanks for the explanation. really appreciate it.

Brightlight0721 commented 8 months ago

Hi, did you follow the Nextjs platform guide? https://github.com/GriffinJohnston/ldrs/blob/main/framework-guides.md

oh I see now I understand.. thanks

angelmtztrc commented 8 months ago

I have the same error, but only in my production builds, develop seems to work just fine.

GriffinJohnston commented 8 months ago

How exactly have you implemented your loader? Would you mind posting a code snippet? Also, did you follow the Next.js platform guide?

angelmtztrc commented 8 months ago

this is my exact code:

'use client';
import { useEffect } from 'react';
import { lineSpinner } from 'ldrs';

const Loader = () => {
  useEffect(() => {
    async function getLoader() {
      lineSpinner.register();
    }
    getLoader();
  }, []);

  return (
    <section className="py-48 main-container lg:py-128  items-center px-24 flex flex-col lg:gap-64 gap-32 max-h-screen h-[calc(100vh-172px)] justify-center">
      <l-line-spinner
        size="50"
        stroke="3"
        speed="1"
        color="#DDDED8"
      ></l-line-spinner>
    </section>
  );
};

export default Loader;

I'm using Next 14.1.0 and React 18

GriffinJohnston commented 8 months ago

Ah okay yea. If you read through the Next guide, you'll see you can't use it that way due to SSR issues. So you either have to load the script in a layout file, or use a dynamic import, like so:

import { useEffect } from 'react'

export default function Loader() {
  useEffect(() => {
    async function getLoader() {
      const { spiral } = await import('ldrs')
      spiral.register()
    }
    getLoader()
  }, [])
  return <l-spiral color="coral"></l-spiral>
}

This issue gets raised enough that I'm planning on releasing a simple set of wrapper components that do this for you, so people can just import and go without having to read docs.