Next.js: Enable preview mode during development in an iframe

Created on 26 Mar 2020  路  12Comments  路  Source: vercel/next.js

Feature request

Is your feature request related to a problem? Please describe.

Storyblok visual composer runs NextJS inside an IFrame. Due to this handling the cookie to enable preview mode is never set and the preview mode does not work for SSG handling.

Describe the solution you'd like

Probably it would be a good idea if the preview mode could be enabled through URL params. The cookie solution might break other headless CMS systems as well

Describe alternatives you've considered

Alternatively I'd like to run my site in SSR mode on a specific domain. It feels like a hack because I would need to deploy every project twice for each mode.

story feature request

Most helpful comment

+1! CraftCMS's preview mode is also using iFrames.

All 12 comments

+1! CraftCMS's preview mode is also using iFrames.

This is fixed by https://github.com/zeit/next.js/pull/11495 I guess?

From what I can see using Storyblok, this is still an issue @timneutkens after upgrading to latest canary build.

The 307 response has the set-cookie headers with SameSite set to lax
image

But unlike running in localhost outside of Storyblok, the actual nextjs response doesn't contain the cookies in its request headers.
image

@timneutkens on NextJS 9.3.4 its still an issue in Storyblok, I have the exact behaviour as @ChrisDalley pointed out. Currently I use a SSR page and share the logic between SSG and SSR to solve the issue

I tried with 9.3.6 the updated handling of the updated cms examples:

res.write(
    `<!DOCTYPE html><html><head><meta http-equiv="Refresh" content="0; url=${currentSlug}" />
    <script>window.location.href = '${currentSlug}'</script>
    </head>`
  )
res.end()

But the issue is still around, the previewData is getting lost. Did anybody got around this issue yet?

@dohomi - not yet, reverted back to using a separate server/routes for generating preview pages, though with Vercels new lambda # limits for hosting I would really like to get rid of them and onto the new preview functionality.

I am using a SSR route now but on local environment this does not work at all:

Error was not caught DOMException: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.

This seems for me like a bug in the new version of NextJS (v. 9.4.x)

Just a heads up, If you're using Brave, make sure to turn off Brave Shield on storyblok.com. It will block the cookies required for preview mode.

I'm having the same issue with Storyblok. @timneutkens, is it possible to add sameSite option in res.setPreviewData?
next/next-server/server/api-utils.ts#L467
next/next-server/server/api-utils.ts#L476
It works fine when its property is empty (none), so it would be great to decide if someone wants to use lax by default.

I'm having the same issue with Storyblok. @timneutkens, is it possible to add sameSite option in res.setPreviewData?
next/next-server/server/api-utils.ts#L467
next/next-server/server/api-utils.ts#L476
It works fine when its property is empty (none), so it would be great to decide if someone wants to use lax by default.

btw here is a workaround:

const IS_PROD = process.env.NODE_ENV === "production";

const setCookieSameSite = (res, value) => {
  const cookies = res.getHeader("Set-Cookie");
  res.setHeader(
    "Set-Cookie",
    cookies?.map((cookie) =>
      cookies.replace(
        cookie,
        "SameSite=Lax",
        `SameSite=${value}; ${IS_PROD ? "Secure;" : ""}`
      )
    )
  );
};

export const preview = async (req, res) => {
  // ...
  res.setPreviewData({});
  setCookieSameSite(res, "None");
  // ...
}

To use preview mode correctly on localhost, if you are using Chrome, disable Cookies without SameSite must be secure (chrome://flags/#cookies-without-same-site-must-be-secure) option.

btw here is a workaround:

const setCookieSameSite = (res, value) => {
  const cookies = res.getHeader('Set-Cookie');
  res.setHeader('Set-Cookie', cookies?.map((cookie) => cookie.replace("SameSite=Lax", `SameSite=${value}`)))
}

export const preview = async (req, res) => {
  // ...
  res.setPreviewData({});
  setCookieSameSite(res, "None");
  // ...
}

Unfortunately this doesn't work in the latest chrome, it complains that secure also needs to be set.

btw here is a workaround:

const setCookieSameSite = (res, value) => {
  const cookies = res.getHeader('Set-Cookie');
  res.setHeader('Set-Cookie', cookies?.map((cookie) => cookie.replace("SameSite=Lax", `SameSite=${value}`)))
}

export const preview = async (req, res) => {
  // ...
  res.setPreviewData({});
  setCookieSameSite(res, "None");
  // ...
}

Unfortunately this doesn't work in the latest chrome, it complains that secure also needs to be set.

Thanks. I updated the comment.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kenji4569 picture kenji4569  路  3Comments

swrdfish picture swrdfish  路  3Comments

formula349 picture formula349  路  3Comments

renatorib picture renatorib  路  3Comments

olifante picture olifante  路  3Comments