You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Yarnberry Monorepo中UI包公共组件图片加载异常问题?

Monorepo(Yarnberry 3.6)中UI包图片在Next.js项目显示异常的解决方案

问题背景

使用Yarnberry 3.6构建Monorepo,目录结构如下:

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

UI包的package.json配置如下:

{
  "name": "@common/ui",
  "packageManager": "yarn@3.6.1",
  "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"
  },
}

UI包相关代码:

// packages/ui/src/index.ts
export { default as Modal } from "./modals/Modal";
// packages/ui/src/modals/Modal.tsx
import Close from '../../assets/close.png';
const Modal = ({ title, content, buttonName }: IConfirmType) => {
  return (
    <div className="popup_message_view_align">
      <img
        className="btn_close"
        src={Close}
        alt="close"
      />
      ...
    </div>
  );
};

将UI包的Modal组件导入至services/next-app后,组件可正常渲染,但图片无法加载,img元素的src属性值显示为[object Object]。

问题原因

Next.js对静态资源的导入会返回一个包含src、width等属性的对象(而非直接返回文件路径字符串),而UI组件直接将该对象赋值给img的src属性,导致显示异常。同时,Monorepo中UI包的资源未被Next.js构建流程正确识别处理。

解决方案

方案1:修改组件中图片的使用方式

直接提取导入图片对象的src属性赋值给img标签:

// Modal.tsx
import Close from '../../assets/close.png';
const Modal = ({ title, content, buttonName }: IConfirmType) => {
  return (
    <div className="popup_message_view_align">
      <img
        className="btn_close"
        src={Close.src} {/* 改为获取src属性 */}
        alt="close"
      />
      ...
    </div>
  );
};

方案2:配置Next.js处理UI包资源

在services/next-app/next.config.js中添加transpilePackages,让Next.js将UI包纳入自身构建流程:

/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@common/ui'],
}

module.exports = nextConfig;

配置完成后重启Next.js项目,配合方案1即可正常加载图片。

方案3:预构建UI包资源

通过构建工具将UI包中的图片处理为可直接引用的路径,避免Next.js的资源解析逻辑干扰:

  1. 在UI包的package.json中添加构建脚本:
{
  "scripts": {
    "build": "esbuild src/index.ts --bundle --outfile=dist/index.js --loader:.png=file --asset-names=assets/[name]-[hash]"
  }
}

该命令会将图片复制到dist/assets目录,并在代码中替换为相对路径。
2. 修改UI包的package.json入口字段:

"main": "./dist/index.js",
"types": "./dist/index.d.ts" // 若需类型支持,需额外配置TypeScript编译输出类型声明
  1. 执行构建:yarn workspace @common/ui build,之后Next.js项目会使用构建后的UI包代码,图片路径可直接正常使用。

方案4:使用Next.js Image组件(需依赖Next.js)

若UI组件无需跨框架通用,可改用Next.js的Image组件,它会自动处理静态资源:

// Modal.tsx
import Image from 'next/image';
import Close from '../../assets/close.png';
const Modal = ({ title, content, buttonName }: IConfirmType) => {
  return (
    <div className="popup_message_view_align">
      <Image
        className="btn_close"
        src={Close}
        alt="close"
        width={24} // 根据实际图片尺寸设置
        height={24}
      />
      ...
    </div>
  );
};

内容的提问来源于stack exchange,提问作者김정수

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:39:51