So, I have a bunch of SSG pages in Next.js and as such, I am creating the navigation over over which has a bunch of routes. SO, I want to "cache" the first api call and just get the cached (written to file data) after that. I am using this, and it is NOT creating the file. I get the following error and as such, I am always hitting the api.
I log in the catch, and it gives the error. File is never created.
ERROR:
Error: ENOENT: no such file or directory, open '/Users/jim/company/clientapp/.next/server/pages/Users/jim/company/clientapp/.routes'
My code:
import fs from 'fs';
import path from 'path';
/* api */
import routes from '@api/rest/routes';
const ROUTE_CACHE_PATH = path.resolve('.routes');
export default async function getCacheRoutes() {
let cachedData
try {
cachedData = JSON.parse(
fs.readFileSync(path.join(__dirname, ROUTE_CACHE_PATH), 'utf8')
)
} catch (error) {
// logger here
}
if (!cachedData) {
const data = await routes() // this is the api request, it works
try {
fs.writeFileSync(
path.join(__dirname, ROUTE_CACHE_PATH),
JSON.stringify(data),
{ flag: 'w' }. // With or without this, doesn't work.
)
} catch (error) {
// Logger here
}
cachedData = data
}
return cachedData
}
CodePudding user response:
It fails because the path to the file in ROUTE_CACHE_PATH
, and readFileSync
is incorrect throughout.
Try setting up the correct path, and then use it throughout:
// setup the correct path to file, use it throughout
// writes to the file `routes` in CWD
const ROUTE_CACHE_PATH = path.resolve(path.join(process.cwd(), 'routes'));
and now reference it throughout:
fs.readFileSync(ROUTE_CACHE_PATH, 'utf8')
and
fs.writeFileSync(
ROUTE_CACHE_PATH,
Bear in mind that JSON.parse
might also fail here, if it's not parsable data you send, so you might consider adding a handler for that too, or maybe on the sender part.
With this code, the reading and writing are sort of independent. So, a better way might be to move the file writing in the error part, IMHO:
try {
readFile
} catch() {
writeFile
}
Here's the rearranged code:
import fs from 'fs';
import path from 'path';
/* api */
import routes from '@api/rest/routes';
// setup the correct path to file, use it throughout
// writes to the file `routes` in CWD
const ROUTE_CACHE_PATH = path.resolve(path.join(process.cwd(), 'routes'));
export default async function getCacheRoutes() {
// setup variables to be accessible for later
let cachedData;
let data;
// first, read the file
// if it fails, there is no file
// so move the file writing to the error part
// note that parsing might also fail, so handle that there too
try {
// parsing might fail here though..
cachedData = JSON.parse(
fs.readFileSync(ROUTE_CACHE_PATH, 'utf8')
)
} catch (error) {
// reading failed, handle file writing
// parsing and other errors here
console.log(error);
// if there is no file, get data and write a fresh file
if (error.code === 'ENOENT') {
// todo: make sure it's always a JSON as string,
// otherwise parsing will fail..
data = await routes();
try {
fs.writeFileSync(
ROUTE_CACHE_PATH,
JSON.stringify(data), {
flag: 'w'
}
)
} catch (error) {
// parsing might fail..
console.log(error);
}
} else {
// or some other error: JSON parsing failed, for example
console.log('handle some other error', error);
}
cachedData = data;
}
return cachedData
}