Next.jsでmarkdownで挿入した画像をnext/imgタグを使って画像最適化する
背景
react-markdown を使って markdown→html 変換をしていたが、md 内に挿入した画像は、img タグとして html 化されることがわかった(next/img による画像最適が行われていない)。そのため、next/img タグを使用した html 変換ができる方法を探した。
結論
next-mdx-remote というパッケージを利用することでできた。
next.jsコード
[slug].js// this object will contain all the replacements we want to makeconst components = {img: (props) => (// height and width are part of the props, so they get automatically passed here with {...props}<Image {...props} layout="responsive" loading="lazy" />),};const PostContent = ({ post }) => {return (<><Head><title>{post.title} | MyWebsite</title></Head><article><header><h2 className={styles.header}>{post.title}</h2><span>Posted: <time dateTime={post.date}>{post.date}</time></span></header><div className={mdstyles.mdody}>{/* MDXRemote uses the components prop to decide which html elements to switch for components */}<MDXRemote {...post.mdxSource} components={components} /></div></article></>);}(snip)export const getStaticProps = async ({ params }) => {const postPath = path.join("data", `${params.slug}.md`);const file = matter.read(postPath);const post = {title: file.data.title,date: file.data.date,body: file.content,};// get your markdown here// pass your markdown string to the serialize functionconst mdxSource = await serialize(post.body, {mdxOptions: {// use the image size plugin, you can also specify which folder to load images from// in my case images are in /public/images/, so I just prepend 'public'rehypePlugins: [[imageSize, { dir: "public" }]],},});// return your serialized content as a prop herereturn {props: {post: {title: post.title,date: post.date,mdxSource},},};};
markdown中身
---
表示結果
参考にしたサイト
https://ironeko.com/posts/how-to-use-next-js-image-with-markdown-or-mdx