如何将Markdown本地图片转为Next.js 13 <Image />标签?(基于remark等工具链)
Next.js + Contentlayer 本地图片无法渲染解决方法
问题根源
这锅得Contentlayer背——它默认把Markdown里的图片转成普通<img>标签,既不会换成Next.js带优化的next/image组件,本地相对路径在Next.js的路由规则下也没法正确识别,自然显示破碎图。
解决步骤
1. 安装必要依赖
先装两个插件,用来移除图片外层的<p>标签、把普通<img>转成Next.js的Image组件:
npm install remark-unwrap-images rehype-react
2. 修改Contentlayer配置
打开contentlayer.config.js,先引入所需模块:
import { rehypeReact } from 'rehype-react' import Image from 'next/image' import { remarkUnwrapImages } from 'remark-unwrap-images'
然后更新MDX的插件配置:
mdx: { remarkPlugins: [ remarkGfm, remarkUnwrapImages // 移除图片外层的<p>标签,避免布局错乱 ], rehypePlugins: [ rehypeSlug, [ rehypePrettyCode, { theme: ..., // 保留你原有的主题配置 onVisitLine(node) {...}, // 保留原有的行处理逻辑 onVisitHighlightedLine(node) {...}, onVisitHighlightedWord(node) {...}, }, ], [ rehypeAutolinkHeadings, {...}, // 保留原有的锚点配置 ], // 核心:添加该插件将普通<img>替换为Next.js Image组件 [ rehypeReact, { createElement: React.createElement, components: { img: (props) => { // 处理路径:假设图片存放在public/images目录下 let src = props.src // 将Markdown中的相对路径转为Next.js可识别的绝对路径 if (src.startsWith('./')) { src = src.replace('./', '/images/') } return ( <Image src={src} alt={props.alt} width={800} // 根据需求调整默认宽度 height={600} // 根据需求调整默认高度 loading="lazy" // 开启懒加载 className="rounded-lg" // 可选:添加自定义样式,比如圆角 /> ) } } } ] ], }
3. 调整图片存放位置
把本地图片放到Next.js的public/images目录中,确保路径替换逻辑能生效。如果你的Markdown和图片按文章目录分存(比如content/posts/xxx.md对应content/posts/images/teapot.jpg),则修改路径处理逻辑:
// 利用Contentlayer提供的文件路径,拼接图片真实路径 const relativeDir = document._raw.sourceFilePath.split('/').slice(0, -1).join('/') src = `/${relativeDir}/${props.src.replace('./', '')}`
4. 额外注意事项
- 确保
next.config.js的图片配置正常,本地图片无需设置images.domains,但使用外部图片时需要添加对应域名。 - 若你用
useMDXComponent渲染内容,无需额外传递组件参数,rehype-react已完成替换工作。
总结
这不是Remark/Rehype或Next.js的问题,只是Contentlayer默认未适配Next.js的图片组件体系,需要手动添加插件转换标签、处理路径即可解决。
内容的提问来源于stack exchange,提问作者yen
相关产品推荐
相关产品推荐

