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

Node.js/Next.js遍历文件夹提取React文件frontmatter方案

在Next.js中自动遍历文件夹提取frontmatter的实现方案

Next.js中文件系统操作必须在服务器端环境执行(服务器组件、API路由、数据获取方法),客户端组件无法直接访问本地文件系统。以下是具体实现步骤:

核心思路

  1. 使用Node.js内置的fs/promises和path模块读取目标文件夹
  2. 过滤出.jsx格式的文件
  3. 动态导入每个文件,提取导出的frontmatter对象

App Router(服务器组件)实现

在App Router的服务器组件中直接执行文件遍历逻辑:

// app/blog/page.jsx (服务器组件,默认异步)
import fs from 'fs/promises';
import path from 'path';

export default async function BlogPage() {
  // 获取content文件夹的绝对路径
  const contentDir = path.join(process.cwd(), 'content');
  // 读取文件夹内所有文件
  const files = await fs.readdir(contentDir);
  // 过滤出.jsx后缀的文件
  const jsxFiles = files.filter(file => file.endsWith('.jsx'));

  // 批量提取frontmatter
  const posts = await Promise.all(jsxFiles.map(async (file) => {
    // 动态导入目标文件,解构获取frontmatter
    const { frontmatter } = await import(`../../content/${file}`);
    // 附加文件slug(去掉.jsx后缀)
    return {
      ...frontmatter,
      slug: file.replace('.jsx', '')
    };
  }));

  // 渲染博客列表
  return (
    <div className="blog-list">
      <h1>我的博客</h1>
      <ul>
        {posts.map(post => (
          <li key={post.slug} className="blog-item">
            <h2>{post.title}</h2>
            <p>发布日期:{post.published}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

Pages Router(getStaticProps)实现

如果使用Pages Router,可在getStaticProps中完成文件遍历,再将数据传递给页面组件:

// pages/blog.js
import fs from 'fs/promises';
import path from 'path';

// 服务器端数据获取
export async function getStaticProps() {
  const contentDir = path.join(process.cwd(), 'content');
  const files = await fs.readdir(contentDir);
  const jsxFiles = files.filter(file => file.endsWith('.jsx'));

  const posts = await Promise.all(jsxFiles.map(async (file) => {
    const { frontmatter } = await import(`../content/${file}`);
    return {
      ...frontmatter,
      slug: file.replace('.jsx', '')
    };
  }));

  return {
    props: { posts } // 传递给页面组件的props
  };
}

// 页面组件
export default function BlogPage({ posts }) {
  return (
    <div className="blog-list">
      <h1>我的博客</h1>
      <ul>
        {posts.map(post => (
          <li key={post.slug} className="blog-item">
            <h2>{post.title}</h2>
            <p>发布日期:{post.published}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

关键注意事项

  • 路径正确性:动态导入的路径需根据你的组件位置调整,确保能正确指向content文件夹内的文件
  • 编译兼容性:Next.js会自动转译.jsx文件,无需额外配置即可动态导入
  • 并发处理:Promise.all会并行处理所有文件导入,适合博客文章这类数量不大的场景;若文件量极大,可考虑限制并发数
  • 字段扩展性:如果frontmatter包含author、tags等其他字段,可直接在返回对象中添加,无需修改核心逻辑

内容的提问来源于stack exchange,提问作者antonwilhelm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 19:41:19