Next.js製マークダウンブログの画像をMDファイルと同じ階層に置く

投稿 2021.10.15

目次

Next.jsでは「public」ファルダ配下から画像を参照するようになっています。
しかし、マークダウンでブログを書いている都合上、mdファイルと同じ場所に画像を配置したいと考えました。
以下のようなディレクトリ構成で画像を置いておけるようにします。

ディレクトリ構成
my-blog-project
  ┗ _posts
    ┗ my-first-post
      ┗ index.md
      ┗ 画像01.png
    ┗ my-seond-post
      ┗ index.md
      ┗ 画像02.png
    ┗ my-third-post
      ┗ index.md
      ┗ 画像01.png

プラグインをインストール

build時に静的ファイルを別のディレクトリへコピーできるプラグインをインストールします。

npm install -S copy-webpack-plugin write-file-webpack-plugin

「jpg」「png」ファイルを「public/assets/images/posts」にコピーできるように設定ファイルを変更します。

next.config.js
+const { resolve } = require('path')
 const withBundleAnalyzer = require('@next/bundle-analyzer')({
   enabled: process.env.ANALYZE === 'true',
 });
-
+const CopyFilePlugin = require('copy-webpack-plugin')
+const WriteFilePlugin = require('write-file-webpack-plugin')

+module.exports = {
+  webpack(config) {
+    config.plugins.push(
+      new CopyFilePlugin({
+        patterns: [
+          {
+            context: '_posts',
+            from: '**/*.{jpg,png}',
+            to: resolve(__dirname, 'public/assets/images/posts'),
+          },
+        ],
+      }),
+      new WriteFilePlugin()
+    )
+    return config
+  },
+}

画像の参照先をコピー先のディレクトリにする

mdファイル内の「@@imageUrl@@」の文字列をパスに置換する処理を記述します。

src/utils/Markdown.ts
 
-export async function markdownToHtml(content: string) {
+export async function markdownToHtml(content: string, slug?: string) {

  const markdownIt = new MarkdownIt(
    {
      langPrefix: 'language-',
      preset: 'default',
      linkify: true,
      breaks: true,
      html: true,
      typegraphy: true,
    }
  ).use(mdContainer, 'afilink', containerAfilinkOptions)
  .use(mdContainer, 'question', containerQuestionOptions)
  .use(mdContainer, 'attention', containerAttentionOptions);

-  return markdownIt.render(content).replace(//assets/images/posts/20211015-nextjs-image-dir/g, process.env.baseUrl || '');
+  return markdownIt.render(content).replace(/@@imageUrl@@/g, `/assets/images/posts/${slug}`);
 }

「markdownToHtml」の引数を増やしているので、呼び元も忘れずに更新します。

src/pages/posts/[slug].tsx
-  const content = await markdownToHtml(post.content || '');
+  const content = await markdownToHtml(post.content || '', params!.slug);

mdファイル内では以下のように書くことができます。

![](@@imageUrl@@/01.png)

この記事を書いた人

avatar

にいよん

WEBエンジニアで0&2歳娘のパパです。フルリモートでちいたまに引きこもり中。密かにFIRE目指してます。こんな情報を発信中→投資、IT技術、副業、仮想通貨、暗号資産、NFT、メタバース、ブロックチェーン

© 2021 - 2022 24365.dev