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

I obtained the binary tree output in the form of an object. How can I extract the values from this object and store them in an array to continue working on

Issue Statement In this scenario, you have been presented with a tree consisting of N nodes that are rooted at 1. Each node in the tree is associated with a special number, Se. Moreover, each node possesses a certain Power, which is determined by the count ...

How can I arrange a table in Angular by the value of a specific cell?

Here's the current layout of my table: Status Draft Pending Complete I'm looking for a way to sort these rows based on their values. The code snippet I've been using only allows sorting by clicking on the status header: onCh ...

Learn how to retrieve category page information within a component in Next.js!

I have a plan to develop a category page that will display all tags added to articles. By clicking on a specific tag, it should show a page with all articles containing that particular tag. For this project, I am using Next.js, SSG, and pulling the articl ...

Having trouble loading a local script using NextJs "beforeInteractive" strategy

In my project using Next.js "next": "14.1.0", I have a script that needs to set some window variables as shown below: //config.js window.REACT_APP_DEPLOY_ENV = "development" window.REACT_APP_VENDOR = "some-vendor-name&qu ...

Exploring Functions in Object Literal Notation in TypeScript: Why is the Context of 'this' Assigned as Type 'any'?

It appears that the question has been posed before, but my search yielded no results. The issue at hand seems rather straightforward. TypeScript integrates well with object literal notation, however, when methods are defined within, it struggles to handle ...

The absence of the import no longer causes the build to fail

Recently, after an update to the yup dependency in my create react-app project, I noticed that it stopped launching errors for invalid imports. Previously, I would receive the error "module filename has no exported member X" when running react-scripts buil ...

Warning: Potential Issue with Next-Auth

I've been diving into a project to create a Facebook clone using Next.js. As someone who is fairly new to this framework, I recently encountered an error message that left me uncertain whether it's a standard issue or a bug in my code. https://ne ...

Can you explain the contrast between afterInteractive and lazyOnload techniques?

When utilizing the new next/script component, we can make use of two distinct strategies: afterInteractive (default): This strategy is intended for scripts that need to fetch and execute content after the page has become interactive. Examples include tag ...

It appears that TypeScript is generating incorrect 'this' code without giving any warning

I seem to be facing some resistance filing a feature request related to this on GitHub issues, so I'll give it a shot here. Here is the code snippet that caused me trouble: export class Example { readonly myOtherElement: HTMLElement; public ...

How can I retrieve header values in the canActivate function in Angular?

Depending on the value of userRole received from the header, I need to redirect to different user pages. angular.routing.ts { path: '', pathMatch: 'full', redirectTo: '/login' }, { path: 'user', loadChildren: &apo ...

Why is the type of parameter 1 not an 'HTMLFormElement', causing the failure to construct 'FormData'?

When I try to execute the code, I encounter a JavaScript error. My objective is to store the data from the form. Error Message TypeError: Failed to create 'FormData': argument 1 is not an instance of 'HTMLFormElement'. The issue arise ...

Initiate the input change event manually

Struggling with creating a custom counter input component where the input value is controlled by custom increment/decrement buttons. Desired output: Content projection will be used to expose the input for form usage and adding properties like a regular n ...

Error encountered in Next.js when using GetStaticPaths

I'm encountering an issue with the getStaticPaths function in Next.JS: TypeError: cias.map is not a function https://i.stack.imgur.com/IVZDp.png Could anyone assist me with resolving this problem? Here's the code snippet: import React from &ap ...

Strategies for resolving type issues in NextJs with Typescript

In my project using Next.js with TypeScript, I encountered an issue while trying to utilize the skipLibCheck = false property for enhanced checking. This additional check caused the build process to break, resulting in the following error: Error info - U ...

When entering the website URL directly into the browser, the query parameters are being lost

Whenever I enter https://localhost/explore?name=teste in my browser, it redirects me to https://localhost/explore, causing the query parameters to be lost. However, when I click on a button, I am correctly redirected to https://localhost/explore?name=test ...

Error: Unable to locate sportsRecord due to missing function

updated answer1: Greetings, I have updated the question with some detailed records and console logs for better understanding. sportsRecord = { playerTigers:[ {TigerNo: 237, TigerName: "Bird Bay Area", TigerkGroupNo: 1, isDefault: true ...

Is it possible to effectively handle SSG, i18n, and dynamic routes in NextJS version 14 by solely utilizing the pages router?

As we strive to upgrade Next.js from version 12 to 14, the process of configuring i18n in a statically generated app using dynamic catch-all routes with the pages router has become unclear. The main issue arises when attempting to set the i18n configurati ...

Tips on updating checkbox background color after being selected

I've been working on creating checkboxes for seat selection in Angular using a TypeScript file, but I'm facing an issue where the background color of the checkbox doesn't change after checking them. Here's my TypeScript function: gener ...

Getting the URL path within getStaticPaths in Next.js

Is there a way to retrieve the last number from the current URL pathnames in getStaticPaths? http://localhost:3000/category/food/2 -> 2, http://localhost:3000/category/food/3 -> 3, ... I have attempted: export const getStaticPaths: GetStaticPaths = ...

What TypeScript declarations are needed for obtaining data using the GET method with Next.js 13 Routes API?

I'm looking for alternatives to the any type when creating a GET handler using the latest experimental routing API in Next.js 13. Check out my code snippet below: export async function GET(request: any, {params}: any) { function getRandomInt(min: n ...