Search code examples
reactjsmonorepoyarn-berry

How to load images from Common Component in Monorepo UI Packages?


I'm building a monorepo using the Yarnberry workspace (version 3.6). My folder structure is as follows:

pakages
|
└── ui
|   └──src
|       └──assets
|           └── close.png
|       └──modals
|            └──Modal.tsx
|         
sevices
└── 
    └── next-app

I've created a simple modal component in the UI folder, and that component uses the close image in assets.

And I imported it from the next-app project of services and confirmed that it was loaded normally. However, only the images did not load normally.

I got the value [object Object] from the src value of the image.

How can I solve this?

Below is the package.json for the ui folder.

{
  "name": "@common/ui",
  "packageManager": "[email protected]",
  "main": "./src/index.ts",
  "scripts": {
  ...
  },
  "devDependencies": {
    "@babel/cli": "^7.22.9",
    "@babel/core": "^7.22.9",
    "@babel/preset-env": "^7.22.9",
    "@babel/preset-react": "^7.22.5",
    "@babel/preset-typescript": "^7.22.5",
    "esbuild": "latest",
    "esbuild-css-modules-plugin": "^2.7.1",
    "esbuild-sass-plugin": "^2.10.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "sass": "^1.64.1",
    "vite": "^4.4.7"
  },
}
//index.ts
export { default as Modal } from "./modals/Modal";
//Modal.tsx
import Close from '../../assets/colse.png';
const Modal = ({ title, content, buttonName }: IConfirmType) => {
  return (
    <div className="popup_message_view_align">
      <img
        className="btn_close"
        src={Close}
        alt="close"
      />
      ...
    </div>
  );
};

Solution

  • Once Next.js builds the app, scripts and assets will be bundled and stored in .next directory. Image that is imported will be seen as an object as below.

    Example

    {
      src: '/_next/static/media/abcdef.a7717b40.jpg',
      height: 3800,
      width: 2850,
      blurDataURL: '/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fabcdef.a7717b40.jpg&w=6&q=70',
      blurWidth: 6,
      blurHeight: 8
    }
    

    As you can see, the final path won't be the same as the relative path you provided.

    You can either do

    <img
      className="btn_close"
      src={Close.src}
      alt="close"
    />
    

    Or, since you use Next.js you can also try using next/image. It will handle the imported image object internally plus better image optimization.

    import Image from 'next/image';
    
    //...
    
    <Image
      src={Close}
      alt="Close image"
      className="btn_close"
      width={600}
      height={400}
      priority
    />