Next.js API Route: ファイルをサーブする
Next.js API Route: ファイルをサーブする
環境:
- next: v10.0.1
参考:
- https://nextjs.org/docs/basic-features/data-fetching#reading-files-use-processcwd
- https://github.com/vercel/next.js/issues/8251
- https://medium.com/@boris.poehland.business/next-js-api-routes-how-to-read-files-from-directory-compatible-with-vercel-5fb5837694b9
getStaticProps
通常、静的ファイルをNext.js上で読み込みたい場合、getStaticProps
を使う。これはサーバーサイドで呼び出されるので、fs
などが使える。
// This function gets called at build time on server-side. // It won't be called on client-side, so you can even do // direct database queries. See the "Technical details" section. export async function getStaticProps() { const postsDirectory = path.join(process.cwd(), 'posts') const filenames = fs.readdirSync(postsDirectory) const posts = filenames.map((filename) => { const filePath = path.join(postsDirectory, filename) const fileContents = fs.readFileSync(filePath, 'utf8') // Generally you would parse/transform the contents // For example you can transform markdown to HTML here return { filename, content: fileContents, } }) // By returning { props: posts }, the Blog component // will receive `posts` as a prop at build time return { props: { posts, }, } }
ただしgetInitialProps
とコンフリクトするため、このメソッドと同時に使用したい場合は、API Routeからファイルをサーブする方法を模索することになる。
API Routeからファイルをサーブする
相対パスでpath.resolve
を使えば、ローカルでもVercel上でも動作する。
import { NextApiRequest, NextApiResponse } from "next"; import fs from "fs"; import path from "path"; export default (req: NextApiRequest, res: NextApiResponse): void => { res.statusCode = 200; const postsDirectory = path.resolve('./public', 'posts') const filenames = fs.readdirSync(postsDirectory) const posts = filenames.map((filename) => { const filePath = path.resolve(postsDirectory, filename) const fileContents = fs.readFileSync(filePath, 'utf8') return { filename, content: fileContents, } }) res.json({ posts }); };
最初Issueを探っててこれを見つけたがVercel上では動かなかった。バージョンが古くて本番環境のパスが変わったりしたんだろうか