sanity-io / next-sanity

Sanity.io toolkit for Next.js
https://www.sanity.io/
MIT License
787 stars 94 forks source link

Issue with Next.js revalidation #1599

Open codercatdev opened 5 months ago

codercatdev commented 5 months ago

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 commented 5 months ago

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 },

evenwestvang commented 5 months ago

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.

codercatdev commented 5 months ago

@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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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.

Shub3am commented 5 months ago

@codercatdev is this issue still for grab?

codercatdev commented 5 months ago

@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.

Shub3am commented 5 months ago

Sure, I am taking this one

danteissaias commented 4 months ago

Any workaround to this issue?

codercatdev commented 4 months ago

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.

iamifechi commented 4 months ago

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: @.***>