How should JSON files stored on the server side be properly utilized in Next.js?

Currently, I have a collection of JSON files that I expose through an API endpoint on my web application for global access. This allows different parts of the application to retrieve the data by sending a fetch request to itself...

However, since this information doesn't need to be accessible to the public, I believe there must be a more efficient way to handle this as only the website itself requires access to the data.

I attempted to use the fs module directly, but it seems like it needs to be implemented within the pages utilizing getStaticProps/getServerSideProps. This would require me to rewrite the code on each page needing the data rather than just calling a pre-written function for fetching requests.

So, what is the proper approach to resolving this issue?

Answer №1

When comparing the use of fs with import/require, it seems that if you want to avoid rebuilding each time a file changes, opting for fs would be more suitable.

To abstract this behavior, creating a function based on the example provided at https://vercel.com/guides/loading-static-file-nextjs-api-route could be beneficial.

import { promises as fs } from 'fs';

export default async function Page() {
  const file = await fs.readFile(process.cwd() + '/app/data.json', 'utf8');
  const data = JSON.parse(file);

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
}

In any part of your code, you can define

const myReadFile = async (path: string) => {
  const file = await fs.readFile(process.cwd() + path, "utf8");
  const data = JSON.parse(file);
  return data;
};

And then call this function in any component

export default async function Page() {
  const data = myReadFile("/app/data.json");

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
}

While you may not save much character-wise, reusability is always advantageous to prevent repetitive tasks, and in this scenario, there are likely no downsides.

You have the flexibility to extend the function as needed - adding types for parsing or other customizations.

const myReadFileTyped = async <T,>(path: string): Promise<T> => {
  const file = await fs.readFile(process.cwd() + path, "utf8");
  const data: T = JSON.parse(file);
  return data;
};

For instance,

type Data = {title:string, content:string};
const data = await myReadFileTyped<Data>("/app/data.json")

and utilize the retrieved data in your component.

If error handling is required, you can implement a safe version of the function that returns null on exceptions:

const myReadFileSafe = async <T,>(path: string): Promise<T | null> => {
  try {
    const file = await fs.readFile(process.cwd() + path, "utf8");
    const data: T = JSON.parse(file);
    return data;
  } catch (e) {
    console.log(e);
    return null;
  }
};

Subsequently,

export default async function Page() {
  const data = await myReadFileSafe("/app/data.json");

  if (data === null) {
    return null;
  }

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
}

This approach allows for further customization and integration of validation processes, leveraging external libraries if necessary.

Answer №2

To enhance your project's tsconfig.json, consider including the following compilerOption:

    "compilerOptions: {
       "resolveJsonModule": true,
    }

This will allow you to access strongly typed data structures from files stored privately on your server, which will then be included in the JavaScript bundle...

    import stuff from "./stuff.json";

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering an issue while trying to import the validator module in NextJS 13

I encountered a peculiar issue while trying to import a module. Nextjs presented the following error message: ./application/sign_in/sign_in_store.ts:2:0 Module not found: Can't resolve 'validator' 1 | import { createEvent, createStore } fr ...

Determine the originating page in Next.js that leads to the current page

Imagine a scenario with three pages: A, B, and C. In this setup, it is possible to navigate from page A to C, as well as from page B to C. However, the displayed content on page C will vary depending on the origin page of the navigation. I am curious to ...

Backdrop dimming the Material UI Modal

My modal is designed to display the status of a transaction on my website, but I'm facing an issue where the backdrop dimming effect is being applied over the modal. Instead of appearing white as intended, the modal ends up having a dark gray tint. I ...

swap out an element in an array with an extra element

My array contains elements with both id and des properties. I would like to add an additional property like value:0 to each object in the array. I achieved this using a loop. let data = [ { "id": 1001, "des": "aaa" }, { ...

Is there a way to prevent an item from being selected in a Select component when the first letter of the option is pressed?

I'm currently working with the material UI Select component and I'm attempting to create a filter within it that will only display items matching the user's input. Below is a simplified example of my current project: function App() { con ...

What are the consequences of relying too heavily on deep type inference in React and Typescript?

In the process of migrating my React + Javascript project to Typescript, I am faced with preserving a nice unidirectional flow in my existing code. The current flow is structured as follows: 1. Component: FoobarListComponent -> useQueryFetchFoobars() 2 ...

NextJS MaterialUI: Unable to locate the 'react' module

Currently, I am working on a project where I am utilizing Next.js along with Material UI to streamline the process of designing interfaces. Within my Next.js application, I have integrated Material UI to create components. However, while using a specific ...

Challenging Issue: "The 'any' type cannot be assigned to the 'never' type"

Currently facing a challenging Typescript problem that has me puzzled. The issue arises at the line themeToChange[tileId][key] = value; The error message states Type 'any' is not assignable to type 'never' This error is directly rela ...

What causes the index to display [object Object] rather than an integer in React?

It has been a long time since I last worked with React, and now I'm facing an issue. Whenever I use console.log to display the index within the map function, my console output looks like this: https://i.stack.imgur.com/VbGmE.png However, the result ...

Creating a custom utility type in TypeScript for serializing an array of objects: What you need to know

Imagine I have the following specified object: type Test = { date: Date num: number str: string } In this object, there is a Date type that needs to be converted into a string ("serialized"). To achieve this, I came up with the concept of a Generic ...

Tips for utilizing intellisense from monaco.d.ts

Is there a way for me to incorporate monaco.d.ts in order to utilize intellisense with the monaco-editor package? I've recently integrated this package into a JavaScript project and everything is functioning properly. However, as I transition to Type ...

Error retrieving user by provider account ID using Google and Firebase adapter with Next Auth

Encountering an issue while trying to integrate Google Provider with Firebase Adapter in Next Auth. Upon selecting an account, the following error is displayed: Running Firebase 9 TypeError: client.collection is not a function at getUserByProvider ...

Steps for passing the :id parameter to an Angular 2 service using routes

Currently, I am trying to find a way to pass a Mac ID into a service using routes in order to filter data efficiently. In my app.html file, there is a dropdown menu where I manually input a list of Mac addresses. Through Angular activated routes, I am atte ...

Retrieving the value of an object using an array of keys

Consider the following object: const obj = { A:{ a1:'vala1', a2:'vala2' }, B:{ b1: 'valb1', b2: 'valb2' }, C:{ c1:{ c11:'valc11' }, c2:'valc2' } } We also have an array: const ...

The Angular 2 router is not compatible with using the same component but with different IDs

Currently utilizing the alpha8 router with 3 main routes: export const appRoutes: RouterConfig = [ { path: '', component: LandingComponent }, { path: 'blog', component: BlogComponent }, { path: 'posts/:id', compon ...

What is the best way to dynamically adjust the width of multiple divisions in Angular?

I am currently working on an angular project to create a sorting visualizer. My goal is to generate a visual representation of an array consisting of random numbers displayed as bars using divisions. Each bar's width will correspond to the value of th ...

Electron and React: Alert - Exceeded MaxListenersWarning: Potential memory leak detected in EventEmitter. [EventEmitter] has 21 updateDeviceList listeners added to it

I've been tirelessly searching to understand the root cause of this issue, and I believe I'm getting closer to unraveling the mystery. My method involves using USB detection to track the connection of USB devices: usbDetect.on('add', () ...

Problem encountered in NextJS/ReactJS when attempting to dynamically load a new component by clicking a button within the current component

In my NextJS project, I am working with 3 components named "Sidebar", "Woven", and "ToolsPage". Below are the respective codes for each: ToolsPage Component: "use client" import Woven from './components/weaved'; import Sidebar from &ap ...

An error occurs when attempting to use object mapping and the rest operator in a return statement due to

I've encountered a type mismatch error in my TypeScript project using Prisma while attempting to return an object with mapped properties in the getPool method. Let's take a look at the code snippet causing the issue: public async getPool({ id, v ...

Is time-based revalidation in NextJS factored into Vercel's build execution time?

Currently overseeing the staging environment of a substantial project comprising over 50 dynamic pages. These pages undergo time-based revalidation every 5 minutes on Vercel's complimentary tier. In addition, I am tasked with importing data for numer ...