Next.js如何读取Public文件夹下Songs目录的文件并完成渲染?
Next.js遍历public目录下Songs文件夹的实现方案
你说的不能直接用fs,是指不能在客户端运行的代码中调用fs,只要在服务端执行的逻辑里用fs就完全合规,以下是两种常用实现方式:
方案1:App Router 服务端组件实现(推荐)
App Router默认所有组件都是服务端组件,运行在Node侧,可直接调用fs读取文件:
import fs from 'fs' import path from 'path' export default function SongList() { // 拼接public/Songs的绝对路径 const songsDirPath = path.join(process.cwd(), 'public', 'Songs') // 读取目录并过滤音频文件,可按需增减支持的后缀 const songList = fs.readdirSync(songsDirPath).filter(fileName => { const ext = path.extname(fileName).toLowerCase() return ['.mp3', '.flac', '.wav', '.ogg'].includes(ext) }) // 你的渲染逻辑 return ( <div className="song-list"> {songList.map(songName => ( <div key={songName} className="song-item"> <p>{songName}</p> {/* public下的资源直接用/Songs前缀访问,注意转义特殊字符 */} <audio controls src={`/Songs/${encodeURIComponent(songName)}`} /> </div> ))} </div> ) }
方案2:Pages Router / 客户端组件实现
如果用Pages Router,或者需要把歌曲列表传给客户端组件使用,可在服务端数据获取接口里读取文件,再通过props传给组件:
import fs from 'fs' import path from 'path' // 页面组件 export default function SongPage({ songList }) { // 你的渲染逻辑 return ( <div className="song-list"> {songList.map(songName => ( <div key={songName} className="song-item"> <p>{songName}</p> <audio controls src={`/Songs/${encodeURIComponent(songName)}`} /> </div> ))} </div> ) } // 服务端数据获取逻辑,运行在Node侧,可直接调用fs export async function getStaticProps() { const songsDirPath = path.join(process.cwd(), 'public', 'Songs') const songList = fs.readdirSync(songsDirPath).filter(fileName => { const ext = path.extname(fileName).toLowerCase() return ['.mp3', '.flac', '.wav', '.ogg'].includes(ext) }) return { props: { songList }, // 按需设置增量静态再生周期,单位秒,设置后会定期更新歌曲列表 revalidate: 3600 } }
注意事项
- 如果歌曲文件名包含中文、空格或特殊字符,必须用
encodeURIComponent转义后再拼到资源路径里,避免出现404 - 如果希望新增歌曲后无需重新构建就能更新列表,可调整
revalidate参数的数值,或者改用getServerSideProps每次请求都读取最新的文件列表
内容的提问来源于stack exchange,提问作者lowfi 2
相关产品推荐
相关产品推荐

