Read/Write JSON to Next.js/Vercel in production?
Unanswered
Spectacled bear posted this in #help-forum
Spectacled bearOP
(How) to read/write JSON files to a Next.js 14 project in Vercel?
I'm basically using a JSON file to populate the purely static content.
And I'm writing form data, sent from the client, into another JSON file.
Locally it works fine.
Inspecting the directory structure during deployment, using
But I still get this error during deployment:
I'm basically using a JSON file to populate the purely static content.
And I'm writing form data, sent from the client, into another JSON file.
Locally it works fine.
Inspecting the directory structure during deployment, using
fs.readdir() reveals the same directory structure.But I still get this error during deployment:
[Error: ENOENT: no such file or directory, open '/vercel/path0/src/lib/ortDb.json'] {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/vercel/path0/src/lib/ortDb.json'
}18 Replies
Spectacled bearOP
additional code info
@app/hpin/[cityName]/page.tsx:
@/app/actions.ts:
@/utils.js:
@app/hpin/[cityName]/page.tsx:
import { getNonEmptyHpData } from "@/app/actions"
export const dynamicParams = false
export default async function locationPage({ params }) {
const decodedCityName = decodeURIComponent(params.cityName)
const ortDB = await getNonEmptyHpData()
return <>
{/* listing data here */}
</>
}
export const generateStaticParams = async () => {
const nonEmptyCitiesData = Object.entries(await getNonEmptyHpData())
const params = [];
for (const [cityName, plzArray] of nonEmptyCitiesData) {
params.push({ cityName: cityName });
}
return params;
};@/app/actions.ts:
'use server'
import { readdir } from "fs"
import path from "path"
const { readJson } = require('@/utils')
export async function getAllHpData() {
const dataFilePath = path.join(process.cwd(), './src/lib')
console.log('dataFilePath', dataFilePath)
await readdir(dataFilePath, (err, files) => console.log('files', files))
return await readJson()
}
export async function getNonEmptyHpData() {
// console.log('getNonEmptyHpData action')
const ortDB = await getAllHpData()
// more stuff going on
}@/utils.js:
const fs = require("fs/promises");
const path = require("path");
async function readJson() {
try {
const readJsonFilePath = path.join(process.cwd(), './src/lib')
const data = await fs.readFile(path.join(readJsonFilePath, 'ortDb.json'), 'utf-8') // ERROR HERE (during build in deployment)
const dataObj = JSON.parse(data);
return dataObj
} catch (error) {
throw error
}
}I think you problem is here path.join(process.cwd(), './src/lib'), does it work in a local build? console.log(readJsonFilePath) in a local build to check
try this?
const readJsonFilePath = path.join(process.cwd(), 'src', 'lib')@Ray try this?
ts
const readJsonFilePath = path.join(process.cwd(), 'src', 'lib')
Spectacled bearOP
tried all possible combinations for that - probably also this one.
for hours I tried to log all possible paths in the deployed next.js project.
But I didn't find the JSON file to
However I just found out that I can simply put the JSON file into the public folder, import it from there and simply use it as object inside my JS code:
... which makes the
for hours I tried to log all possible paths in the deployed next.js project.
But I didn't find the JSON file to
generateStaticParams().However I just found out that I can simply put the JSON file into the public folder, import it from there and simply use it as object inside my JS code:
'use server'
import ortDbJson from "/public/ortDbInPublic.json"
export async function getAllHpData(){
return ortDbJson
}... which makes the
getAllHpData() redundant for now.But I still wonder if it should theoretically possible to read/write JSON on a Vercel server.
Because I actually don't want to make the JSON public.
However I imagine that Vercel doesn't like the idea of people using their servers as DBs by reading and writing JSON.
So maybe they prevent it?🤔
Because I actually don't want to make the JSON public.
However I imagine that Vercel doesn't like the idea of people using their servers as DBs by reading and writing JSON.
So maybe they prevent it?🤔
Northern Wheatear
You can import the json file from anywhere within the project. There is no necessity to put it in public folder
Also you can't write to a json or any file if you are deploying it on vercel. Reading works
@Northern Wheatear You can import the json file from anywhere within the project. There is no necessity to put it in public folder
Spectacled bearOP
Good point!
Didn't try this yet.ðŸ˜
Didn't try this yet.ðŸ˜
@Northern Wheatear Also you can't write to a json or any file if you are deploying it on vercel. Reading works
Spectacled bearOP
So Vercel generally doesn't allow writing to any project dir, right?
I think I quickly discovered this, getting a 405 HTTP response after submitting the form which under the hood tried to write a JSON to the root directory.
I think I quickly discovered this, getting a 405 HTTP response after submitting the form which under the hood tried to write a JSON to the root directory.
Northern Wheatear
Not only vercel but I think if your app is working on any serverless environment writing to a file doesn't work
Also if you intend to write to a file with subsequent deploys of the app the data will be lost anyways. So why don't you try using a database instead
Spectacled bearOP
very good point, which I didn't consider before👌🤣
Thanks a lot @Northern Wheatear
I think I'll read from JSON during build for now and gonna save the form submissions to a DB
I think I'll read from JSON during build for now and gonna save the form submissions to a DB
Northern Wheatear
Actually, you can temporarily write to a file even while deployed to vercel. You just need to read and write the file from
For example if the api routes can generate some large video then you can write it to the /tmp folder and then later upload to s3 by reading from /tmp folder
/tmp directory. But use this way only when you need to store some chunks of data temporarily (because that data will get cleared within some time) and then immediately write to an object storage like S3.For example if the api routes can generate some large video then you can write it to the /tmp folder and then later upload to s3 by reading from /tmp folder
But this method should only be used as a last resort. It is better to store such data in memory itself and write to s3 directly
@Northern Wheatear Actually, you can temporarily write to a file even while deployed to vercel. You just need to read and write the file from `/tmp` directory. But use this way only when you need to store some chunks of data temporarily (because that data will get cleared within some time) and then immediately write to an object storage like S3.
For example if the api routes can generate some large video then you can write it to the /tmp folder and then later upload to s3 by reading from /tmp folder
Spectacled bearOP
Thank you.
I'm gonna learn about this once I have large chunks of data.
So far it's only a bit of text.
So directly storing it in the DB is probably the best way to go.
I'm gonna learn about this once I have large chunks of data.
So far it's only a bit of text.
So directly storing it in the DB is probably the best way to go.
Northern Wheatear
As long as its just text content writing directly to the DB is the best way 😅