skip to Main Content
  • we have a large GatsbyJS 3 (React) project which is used to build multiple websites.
  • The websites are build each with a specific environment file and then uploaded to different locations.
  • The websites have the same code base with a few exceptions (eg. website specific components and images).
  • We don’t use SSR.

The problem is that the website specific components are quite large and therefore bloat up the code of the individual websites which dont use those specific components. This results for example in a bad lighthouse score (unused code) and bad user experience (longer loading times).

Here is a strongly simplified example component which displays a website specific svg (loaded via gatsby-plugin-react-svg):

import React from "react";

import Site1 from "../../images/site1.svg";
import Site2 from "../../images/site2.svg";
import Default from "../../images/default.svg";

const Image = () => {
  let staticImage = <Default />;

  switch (process.env.GATSBY_SITE) {
    case "site1":
      staticImage = <Site1 />;
      break;
    case "site2":
      staticImage = <Site2 />;
      break;
    default:
  }

  return (
    <>{staticImage}</>
  );
};

export default Image;

I guess/understand this wont work because GatsbyJS/React/Webpack (?) simply does not know what happens in this component and when to show which image.

I tried to use loadable components to address this issue but had no success. This is the example code from above but with loadable components:

import React from "react";

import loadable from "@loadable/component";

const DynamicImage = loadable(async () => {
  switch (process.env.GATSBY_SITE) {
    case "site1":
      return import("../../images/site1.svg");
    case "site2":
      return import("../../images/site2.svg");
    default:
      return import("../../images/default.svg");
  }
});

const Image = () => {
  return <DynamicImage />;
};

export default Image;

With this code all three images are still loaded although only one is shown. I would expect that only the used/required image (or component in other cases) is loaded.

2

Answers


  1. Did you try with the React.lazy function?

    const Github = React.lazy(async () => ({
      default: (await import("./github.svg")).ReactComponent,
    }));
    const Google = React.lazy(async () => ({
      default: (await import("./google.svg")).ReactComponent,
    }));
    
    const DynamicImage = () => {
        <React.Suspense fallback={<div>Loading...</div>}>
          {if(CONDITION) && <Github />}
          {if(OTHER_CONDITION) && <Google />}
        </React.Suspense>
    };
    

    See an example here:

    Edit React lazy svg loading (forked)

    Login or Signup to reply.
  2. this should work

    import React, { lazy, Suspense } from "react";
    
    const Site1 = lazy(() => import("../../images/site1.svg"));
    const Site2 = lazy(() => import("../../images/site2.svg"));
    const Default = lazy(() => import("../../images/default.svg"));
    
    const Image = () => {
      let StaticImage = Default;
    
      switch (process.env.GATSBY_SITE) {
        case "site1":
          StaticImage = Site1;
          break;
        case "site2":
          StaticImage = Site2;
          break;
        default:
      }
    
      return (
        <Suspense fallback={<div>Loading...</div>}>
          <StaticImage />
        </Suspense>
      );
    };
    
    export default Image;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search