samvera-labs / clover-iiif

Extensible IIIF front-end toolkit and Manifest viewer. Accessible. Composable. Open Source.
https://samvera-labs.github.io/clover-iiif/
Other
63 stars 15 forks source link

Gatsby Build Failures #175

Closed MWhiteFearless closed 7 months ago

MWhiteFearless commented 8 months ago

Hello,

First, thanks for building out such a great viewer! I'm trying to use it on a project, and it runs fine locally but when we go to deploy with gatsby build, we get several SSR related errors and the build fails

error Generating SSR bundle failed

Reading from "node:buffer" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.
error Generating SSR bundle failed

Reading from "node:fs" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.

and many more similar errors. I've tried several webpack workarounds, installing past versions of Clover, upgrading React, to no avail. I'm thinking that there might be incompatible node versions, but I've had a hard time finding what's required for Clover.

My project:

"dependencies": {
    "@samvera/clover-iiif": "^2.3.2",
    "algoliasearch": "^4.10.5",
    "assets": "file:src/assets",
    "atoms": "file:src/components/atoms",
    "caniuse-api": "^3.0.0",
    "classnames": "^2.3.1",
    "detect-browser": "^5.3.0",
    "embla-carousel-react": "^8.0.0-rc18",
    "gatsby": "3.14.5",
    "gatsby-plugin-algolia": "^0.25.0",
    "gatsby-plugin-google-tagmanager": "^3.14.0",
    "gatsby-plugin-image": "2.6.0",
    "gatsby-plugin-manifest": "^3.14.0",
    "gatsby-plugin-react-helmet": "^4.14.0",
    "gatsby-plugin-robots-txt": "^1.7.0",
    "gatsby-plugin-s3": "^0.3.8",
    "gatsby-plugin-sass": "^4.14.0",
    "gatsby-plugin-sharp": "^3.14.0",
    "gatsby-plugin-sitemap": "^4.10.0",
    "gatsby-source-filesystem": "^3.14.0",
    "gatsby-source-graphql": "^3.14.0",
    "gatsby-transformer-sharp": "^3.14.0",
    "gsap": "^3.10.4",
    "interweave": "^12.9.0",
    "jest-junit": "^12.2.0",
    "molecules": "file:src/components/molecules",
    "moment": "^2.29.4",
    "moment-duration-format": "^2.3.2",
    "npm": "^6.14.15",
    "organisms": "file:src/components/organisms",
    "react": "^17.0.2",
    "react-autosuggest": "^10.1.0",
    "react-compare-image": "^3.1.0",
    "react-dom": "^17.0.2",
    "react-helmet": "^6.1.0",
    "react-instantsearch-dom": "^6.12.1",
    "react-modal": "^3.14.3",
    "sass": "^1.39.0",
  },

Node 14.18.3 
NPM 6.14.18

Do you know if my node version is incompatible, or maybe of another way to resolve this error? Thanks for the help!

mathewjordan commented 8 months ago

Hi @MWhiteFearless

The SSR build fail is due to Clover's inclusion of OpenSeadragon as a dependency. OpenSeadragon includes function calls on instantiation to the browser window -- which causes the crash.

To accommodate this, Clover must be imported in an alternative method. I'm not extremely familiar with Gatsby these days, however, in Next.js this is completed using the next/dynamic (https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading#importing-client-components). See https://samvera-labs.github.io/clover-iiif/docs/viewer#nextjs.

In Gatsby, this could possibly be completed with the following pattern:

import React, { Suspense, lazy, useEffect, useState } from "react";

const CloverViewer = lazy(() =>
  import("@samvera/clover-iiif").then((Clover) => Clover.Viewer)
);

const DynamicCloverViewer = () => {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    // This effect will run only once after the initial render, hence setting isClient to true
    setIsClient(true);
  }, []);

  return (
    <div>
      {isClient && (
        <Suspense fallback={<div>Loading...</div>}>
          <CloverViewer iiifContent="https://api.dc.library.northwestern.edu/api/v2/works/76d0aebe-fc8a-4c6f-91dd-31026e67301e?as=iiif" />
        </Suspense>
      )}
    </div>
  );
};

export default DynamicCloverViewer;
mathewjordan commented 8 months ago

@MWhiteFearless Here's a codesandbox as an example if helpful. https://codesandbox.io/p/sandbox/clover-lazy-suspense-8vgwg4

Let me know if this works for you in Gatsby!

MWhiteFearless commented 8 months ago

Thanks for the suggestion! Unfortunately I still get the same build errors with those changes

mathewjordan commented 8 months ago

Thanks for the suggestion! Unfortunately I still get the same build errors with those changes

Hmmm... Darn. Do you have a public repo of your codebase?

MWhiteFearless commented 8 months ago

Unfortunately our project is private, though we have been able to deploy Mirador successfully in the project (which also uses openseadragon) so I wonder if the issue might be something else? Mirador doesn't actually work for our use case which is why I'm still trying to get Clover to deploy :)

mathewjordan commented 8 months ago

@MWhiteFearless If you are restricting yourself to just the Viewer component, can you try this revised component where the Viewer is the default export? I'm able to get this to build in this Gatsby instance. https://codesandbox.io/p/devbox/gatsby-clover-98c3lw?file=%252Fsrc%252Fcomponents%252Fviewer.js

Note the difference on the lazy import

const CloverViewer = lazy(() => import("@samvera/clover-iiif"))

Full block:

import React, { Suspense, lazy, useEffect, useState } from "react"

const CloverViewer = lazy(() => import("@samvera/clover-iiif"))

const DynamicCloverViewer = () => {
  const [isClient, setIsClient] = useState(false)

  useEffect(() => {
    // This effect will run only once after the initial render, hence setting isClient to true
    setIsClient(true)
  }, [])

  return (
    <div>
      {isClient && (
        <Suspense fallback={<div>Loading...</div>}>
          <CloverViewer iiifContent="https://api.dc.library.northwestern.edu/api/v2/works/76d0aebe-fc8a-4c6f-91dd-31026e67301e?as=iiif" />
        </Suspense>
      )}
    </div>
  )
}

export default DynamicCloverViewer
mathewjordan commented 8 months ago

@MWhiteFearless I grossly overlooked your React version. Sadly, Clover has issues with older versions of React. Is it possible to update React 18 @latest for your project? This in conjunction with my previous comment might send it in the right direction.

MWhiteFearless commented 8 months ago

I tried the react 18 and lazy/Suspense suggestions together and still get the same error, next maybe I'll try this workaround https://www.gatsbyjs.com/docs/using-client-side-only-packages/#workaround-4-load-client-side-dependent-components-with-loadable-components. Interesting that you can get it to build without issue, maybe this is an issue related to Gatsby 3

MWhiteFearless commented 7 months ago

I determined that the errors I was running in to were actually related to @iiif/vault and incompatible dependency versions there, not openseadragon. I've moved forward with implementing openseadragon on its own and have it working :) thanks for helping troubleshoot! The lazy loading suggestion was helpful for getting openseadragon working. I think to get clover working on my project we would have to upgrade gatsby and node, which unfortunately isn't an option for us. We can probably close this issue!

mathewjordan commented 7 months ago

@MWhiteFearless I'm going to close this but I also want to make you aware of a new Image component that is essentially a styled OpenSeadragon wrapper. https://samvera-labs.github.io/clover-iiif/docs/image