React项目通过路径数组加载Markdown原始内容到对象数组的问题
问题原因
你遇到的问题本质是打包工具的静态资源处理机制导致的:
- 直接写在
links数组里的字符串路径属于纯文本,不会被Webpack/Vite等打包工具识别为资源导入,打包过程不会对这些路径做转换、也不会把对应的.md文件打包到最终的产物目录里。你fetch这些路径的时候,因为目标资源不存在,单页应用的路由 fallback 规则会直接返回index.html的内容,所以你拿到的是页面代码而不是md内容。 - 单独
import file1 from 'xxx.md'的时候,打包工具会识别这是资源导入请求,会自动将对应的md文件处理为静态资源、生成正确的可访问路径,同时将打包后的资源路径赋值给file1变量,所以fetch这个路径能正常拿到md内容。
解决方案
方案1:使用require动态导入(适配Webpack项目,比如CRA创建的项目)
遍历路径数组的时候用require动态导入,拿到正确的资源路径再fetch:
// links_file.js 里的路径要改成相对当前logic.js的相对路径 export const links = ["./path/to/file1.md", "./path/to/file2.md"] // logic.js 里修改逻辑 componentDidMount() { links.map(async (link, index) => { // 动态require拿到打包后的正确路径 const mdPath = require(`${link}`); const resp = await fetch(mdPath); const text = await resp.text(); let files = [...this.state.files]; let updatedFile = {...files[index], content: text}; files[index] = updatedFile; this.setState({files}); }) }
如果require提示找不到模块,你可以给路径加个固定前缀避免动态导入的歧义:
export const links = ["file1.md", "file2.md"] // 导入的时候加前缀 const mdPath = require(`./mdDir/${link}`);
方案2:使用import.meta.glob批量导入(适配Vite项目)
Vite不支持动态require,用自带的glob批量导入所有md文件即可:
// logic.js 里直接批量导入,不需要单独定义links数组 const mdModules = import.meta.glob('./path/to/mds/*.md', { as: 'raw' }) // { as: 'raw' } 配置可以直接拿到md的文本内容,不需要额外fetch componentDidMount() { const files = []; for (const path in mdModules) { mdModules[path]().then(content => { files.push({ path, content }) this.setState({files}) }) } }
如果需要保留自定义的路径数组,也可以结合使用:
export const links = ["./path/to/file1.md", "./path/to/file2.md"] const mdModules = import.meta.glob('./path/to/mds/*.md', { as: 'raw' }) componentDidMount() { links.map(async (link, index) => { const content = await mdModules[link](); let files = [...this.state.files]; let updatedFile = {...files[index], content}; files[index] = updatedFile; this.setState({files}); }) }
方案3:把md文件放到public目录(通用方案)
如果不想折腾打包工具的配置,直接把所有md文件放到项目的public目录下,fetch的时候写绝对路径即可:
// 比如把md文件放到public/mds目录下 export const links = ["/mds/file1.md", "/mds/file2.md"] // 直接fetch即可,不需要导入,public目录的资源会直接被托管 fetch(link).then(resp => resp.text()).then(text => { // 处理内容 })
其他注意事项
你提供的示例代码里存在变量名笔误:fetch(link).then(resp => { return response.text() }) 中回调参数是resp,但调用的是response,会抛出未定义错误,实际使用时需要修正。
内容的提问来源于stack exchange,提问作者Jiahui Chen
相关产品推荐
相关产品推荐

