如何在React应用客户端列出源文件夹内容?
解决React客户端无法读取/src/pages目录内容的问题
嘿,这个问题我之前踩过坑!浏览器环境是没有权限直接访问本地文件系统的,你用的glob还有Node.js里的readdir都是服务端/Node.js环境的API,在浏览器里跑肯定会报错~下面给你几个可行的解决方案:
方案1:构建时预生成文件清单
我们可以在项目构建前,用Node.js脚本遍历/src/pages目录,把所有md文件的列表生成一个JSON文件,然后在React组件里直接导入这个JSON来用。
- 先写一个生成清单的脚本,比如
scripts/generate-pages-list.js:
const fs = require('fs'); const path = require('path'); // 目标目录路径 const pagesDir = path.resolve(__dirname, '../src/pages'); // 获取所有.md结尾的文件 const mdFiles = fs.readdirSync(pagesDir).filter(file => file.endsWith('.md')); // 把文件列表写入JSON文件 fs.writeFileSync( path.resolve(__dirname, '../src/pages-list.json'), JSON.stringify(mdFiles, null, 2) );
- 修改
package.json的构建命令,让脚本在构建前自动执行:
{ "scripts": { "prebuild": "node scripts/generate-pages-list.js", "build": "react-scripts build", // 如果是Create React App项目 "prestart": "node scripts/generate-pages-list.js", "start": "react-scripts start" } }
- 在React组件里导入并使用这个文件列表:
import pagesList from './pages-list.json'; function Directory() { return ( <div className="directory"> <h2>目录</h2> <ul> {pagesList.map(fileName => { const pageSlug = fileName.replace('.md', ''); return ( <li key={fileName}> <a href={`/${pageSlug}`}>{pageSlug}</a> </li> ); })} </ul> </div> ); }
方案2:用Webpack的require.context(适用于Webpack/CRA项目)
Webpack提供了require.contextAPI,可以动态导入指定目录下的文件,同时获取文件路径信息,不需要额外写脚本:
// 遍历src/pages下所有.md文件,不递归子目录 const mdContext = require.context('../pages', false, /\.md$/); // 把文件路径转换成可用的目录项 const pagesList = mdContext.keys().map(filePath => { // 提取文件名,比如 './guide.md' -> 'guide' const pageName = filePath.replace(/^\.\/(.*)\.md$/, '$1'); return { name: pageName, // 如果需要获取文件内容,可以这样导入 content: mdContext(filePath).default }; }); // 用这个列表来渲染目录 function Directory() { return ( <ul> {pagesList.map(page => ( <li key={page.name}> <a href={`/${page.name}`}>{page.name}</a> </li> ))} </ul> ); }
方案3:用Vite的import.meta.glob(适用于Vite项目)
如果你的项目用Vite构建,那可以用Vite原生支持的import.meta.glob,用法更简洁:
// 同步导入src/pages下所有.md文件 const mdFiles = import.meta.glob('../pages/*.md', { eager: true }); // 转换为目录列表 const pagesList = Object.entries(mdFiles).map(([filePath, module]) => { const pageName = filePath.replace(/^\.\.\/pages\/(.*)\.md$/, '$1'); return { name: pageName, content: module.default }; }); // 渲染目录 function Directory() { return ( <ul> {pagesList.map(page => ( <li key={page.name}> <a href={`/${page.name}`}>{page.name}</a> </li> ))} </ul> ); }
核心思路就是:浏览器无法直接读取本地文件系统,必须借助构建工具在构建阶段提前获取文件信息,或者用构建工具的动态导入能力来收集文件列表。
内容的提问来源于stack exchange,提问作者Mathieu Marques
相关产品推荐
相关产品推荐

