next-sanity icon indicating copy to clipboard operation
next-sanity copied to clipboard

Issue with Next.js revalidation

Open codercatdev opened this issue 1 year ago • 17 comments

Describe the bug

https://sanity-io-land.slack.com/archives/C9Z7RC3V1/p1718675586121679

I am getting Failed to parsed response body as JSON: Unexpected non-whitespace character after JSON at position 820 on production builds of my site. On the build that was successful to production and currently live, if I try to rebuild it throws these errors now.

I am using Next.j 14.2.3.

fetch.ts

import type { ClientPerspective, QueryParams } from "next-sanity";
import { draftMode } from "next/headers";

import { client } from "@/sanity/lib/client";
import { token } from "@/sanity/lib/token";

/**
 * Used to fetch data in Server Components, it has built in support for handling Draft Mode and perspectives.
 * When using the "published" perspective then time-based revalidation is used, set to match the time-to-live on Sanity's API CDN (60 seconds)
 * and will also fetch from the CDN.
 * When using the "previewDrafts" perspective then the data is fetched from the live API and isn't cached, it will also fetch draft content that isn't published yet.
 */
export async function sanityFetch<QueryResponse>({
  query,
  params = {},
  perspective = draftMode().isEnabled ? "previewDrafts" : "published",
  /**
   * Stega embedded Content Source Maps are used by Visual Editing by both the Sanity Presentation Tool and Vercel Visual Editing.
   * The Sanity Presentation Tool will enable Draft Mode when loading up the live preview, and we use it as a signal for when to embed source maps.
   * When outside of the Sanity Studio we also support the Vercel Toolbar Visual Editing feature, which is only enabled in production when it's a Vercel Preview Deployment.
   */
  stega = perspective === "previewDrafts" ||
    process.env.VERCEL_ENV === "preview",
}: {
  query: string;
  params?: QueryParams;
  perspective?: Omit<ClientPerspective, "raw">;
  stega?: boolean;
}) {
  if (perspective === "previewDrafts") {
    return client.fetch<QueryResponse>(query, params, {
      stega,
      perspective: "previewDrafts",
      // The token is required to fetch draft content
      token,
      // The `previewDrafts` perspective isn't available on the API CDN
      useCdn: false,
      // And we can't cache the responses as it would slow down the live preview experience
      next: { revalidate: 0 },
    });
  }
  return client.fetch<QueryResponse>(query, params, {
    stega,
    perspective: "published",
    // The `published` perspective is available on the API CDN
    useCdn: true,
    // Only enable Stega in production if it's a Vercel Preview Deployment, as the Vercel Toolbar supports Visual Editing
    // When using the `published` perspective we use time-based revalidation to match the time-to-live on Sanity's API CDN (60 seconds)
    next: { revalidate: 60 },
    // The token is required as we are using a private dataset
    token,
  });
}

client.ts

import { createClient } from "next-sanity";

import { apiVersion, dataset, projectId, studioUrl } from "@/sanity/lib/api";

export const client = createClient({
  projectId,
  dataset,
  apiVersion,
  useCdn: true,
  perspective: "published",
  stega: {
    studioUrl,
    // logger: console,
    filter: (props) => {
      if (props.sourcePath.at(-1) === "title") {
        return true;
      }

      return props.filterDefault(props);
    },
  },
});

To Reproduce

Steps to reproduce the behavior:

  1. git clone https://github.com/codercatdev/cms-sanity
  2. git checkout next-issue-1599
  3. pnpm i
  4. pnpm dev
  5. hit a route like http://localhost:3000/author/nick-rouech

Expected behavior

I would expect JSON not to contain any extra whitespace.

Screenshots

image

Which versions of Sanity are you using?

@sanity/cli (global) 3.46.1 (up to date) @sanity/assist 3.0.4 (up to date) @sanity/code-input 4.1.4 (up to date) @sanity/icons 3.2.0 (up to date) @sanity/image-url 1.0.2 (up to date) @sanity/preview-url-secret 1.6.17 (up to date) @sanity/ui 2.4.0 (up to date) @sanity/vision 3.46.1 (up to date) @sanity/webhook 4.0.4 (up to date) sanity 3.46.1 (up to date)

What operating system are you using? Mac 14.5 (23F79)

Which versions of Node.js / npm are you running? 10.8.1 v22.3.0

Additional context

I thought at first this was a stega issue as it seems to be related, but if I fetch with stega:false it still happens. Setting next:revalidate to 0 is the only thing that I found works.

The only change from the example is that when using the "published" perspective I also pass token as my dataset is not public.

codercatdev avatar Jun 18 '24 14:06 codercatdev

Okay I have narrowed this issue down to this setting in the next-sanity package of the client. next: { revalidate: 60 },

fetch.ts

  return client.fetch<QueryResponse>(query, params, {
    stega,
    perspective: "published",
    // The `published` perspective is available on the API CDN
    useCdn: true,
    // Only enable Stega in production if it's a Vercel Preview Deployment, as the Vercel Toolbar supports Visual Editing
    // When using the `published` perspective we use time-based revalidation to match the time-to-live on Sanity's API CDN (60 seconds)
    next: { revalidate: 60 },
    // The token is required as we are using a private dataset
    token,
  });

The only time I get good data is setting next: { revalidate: 0 },

codercatdev avatar Jun 18 '24 14:06 codercatdev

Thank you for making the effort to create a good repro for this. We'll have a look as soon as we get our hands free.

evenwestvang avatar Jun 19 '24 18:06 evenwestvang

@evenwestvang I am seeing issues that surround cloudinary.asset when this field is included at times the object fails and doesn't come back with data at all. I am not 💯 if this is related to the other issues or not.

GROQ

*[_type == "podcast" && views > 0]|order(views desc)[0...4]{
coverImage
}

Example in Next.js not returning this field image

Vision returns all of the data correctly, I am wondering if this could cause any of the whitespace as well, or if something isn't correct with the JSON. Since I have images all over the site from Cloudinary I obviously would see all the issues mentioned above.

image

Full JSON of the result from vision query-result.json

codercatdev avatar Jun 19 '24 23:06 codercatdev

Some more groq tests with cloudinary becoming an issue. I will also add that even if I try to just use the below it still goes missing inside of Next.js.

    coverImage{
      public_id,
    },

with-cloudinary.json - missing entries without-cloudinary.json - all entries valid

Again with these in vision or CLI it works.

codercatdev avatar Jun 19 '24 23:06 codercatdev

okay all of what I thought were issues with cloudinary.asset was not, it appears that is all due to a problem using taint.

simple repo: https://github.com/codercatdev/next-sanity-cloudinary-issue

image

This shows how the logger displays when using taint vs. the data actually appearing on the page. These two things DO NOT match.

The issue with Failed to parsed response body as JSON: Unexpected token '/', "/ still remains with any type of revalidate set on the client.

codercatdev avatar Jun 20 '24 14:06 codercatdev

I will pay for support to get this working @evenwestvang @kmelve is there someone I can do a call with to get this working. It is forcing me out of static and only allowing for a lambda based site, which I was hoping to avoid.

codercatdev avatar Jun 28 '24 12:06 codercatdev

@codercatdev is this issue still for grab?

Shub3am avatar Jul 03 '24 19:07 Shub3am

@Shub3am yes it should be, if you can't repro let me know and I will make sure that branch is usable for the issue.

codercatdev avatar Jul 04 '24 12:07 codercatdev

Sure, I am taking this one

Shub3am avatar Jul 04 '24 12:07 Shub3am

Any workaround to this issue?

danteissaias avatar Jul 23 '24 09:07 danteissaias

My only workaround was to stop generating anything statically. Not really a great workaround but for now that is what I have. So all of https://codingcat.dev is on demand.

codercatdev avatar Jul 23 '24 12:07 codercatdev

Same here, I only get this in dev environment

On Fri, 26 Jul 2024, 11:41 am Dante, @.***> wrote:

This only affects me during dev, not production. However none of the workaround are working for me.

— Reply to this email directly, view it on GitHub https://github.com/sanity-io/next-sanity/issues/1599#issuecomment-2252485507, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHXXP7FD34ZRJA7VGKESXY3ZOIRVZAVCNFSM6AAAAABJQDXA62VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENJSGQ4DKNJQG4 . You are receiving this because you are subscribed to this thread.Message ID: @.***>

iamifechi avatar Jul 26 '24 11:07 iamifechi

We are running into this same issue running app router and 15.0.4. @codercatdev did you ever figure out what was going on? We found a workaround by wrapping the whole thing in unstable_cache and using its revalidation logic instead. That has seemed to work but seems silly since its baked into fetch.

justinadkins avatar Jan 18 '25 00:01 justinadkins

Unfortunately no 😔

On Fri, Jan 17, 2025, 7:54 PM Justin Adkins @.***> wrote:

We are running into this same issue running app router and 15.0.4. @codercatdev https://github.com/codercatdev did you ever figure out what was going on? We found a workaround by wrapping the whole thing in unstable_cache and using its revalidation logic instead. That has seemed to work but seems silly since its baked into fetch.

— Reply to this email directly, view it on GitHub https://github.com/sanity-io/next-sanity/issues/1599#issuecomment-2599432472, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAXVMKN34WBU7XI47DRKJ532LGQ5LAVCNFSM6AAAAABVM7OPWOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKOJZGQZTENBXGI . You are receiving this because you were mentioned.Message ID: @.***>

codercatdev avatar Jan 19 '25 03:01 codercatdev

I have the same issues but in dev environment. Building works fine. Everytime next fast refresh is triggered it throws a similar error.

johannesstrueber avatar Mar 05 '25 13:03 johannesstrueber

I was able to fix my errors by changing the node version with nvm. i used v22.13.1 and got errors. On v20.18.1 the errors do not occur

johannesstrueber avatar Mar 10 '25 19:03 johannesstrueber

I was able to fix my errors by changing the node version with nvm. i used v22.13.1 and got errors. On v20.18.1 the errors do not occur

You have saved my life, the past 2 months I was stuck on this annoying bug. I changed back and forth node, react and next versions

NumanBashir avatar Apr 01 '25 16:04 NumanBashir