Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Preview Mode #562

Merged

Conversation

thchia
Copy link
Collaborator

@thchia thchia commented Aug 26, 2020

#355

Changes

lambda-at-edge-compat

  • NextJS internally calls res.writeHead(...).end(), so we have to return the res in writeHead.

lambda-at-edge

  • For all HTML/JSON data requests (including potential fallbacks), only forward the response to the origin if it is not a preview request.
  • When we reach the SSR portion, we are potentially still handling a JSON data request (due to changes in the previous point). Check and render/return the appropriate content.

Caveat

This is actually nothing to do with this library. It's more about the behaviour of NextJS.

Handling a client side transition in preview mode is not really supported beyond the first transition. After this, NextJS caches the JSON response in memory and does not even issue a new request if you navigate back to that page in the same session (without a refresh). Consider the following steps:

  1. Enter preview mode for mysite.com/blog/1 (an SSG page)
  2. mysite.com/blog/1 is SSR'd because we are in preview mode
  3. Navigate to mysite.com/blog/2 using next/link
  4. Navigate back to mysite.com/blog/1 using next/link
  5. JSON data for Blog 1 is generated at request time
  6. Repeat steps 3-4
  7. JSON data is not regenerated, because we already have it in memory and NextJS does not issue a new request

@thchia thchia force-pushed the feature/preview-mode branch from 13fb79b to e54d915 Compare August 27, 2020 12:02
@thchia thchia changed the title Support Preview Mode 🚧 Support Preview Mode Aug 27, 2020
@thchia thchia force-pushed the feature/preview-mode branch 2 times, most recently from bd82c46 to 5f28647 Compare August 30, 2020 10:20
@thchia thchia marked this pull request as draft August 30, 2020 10:21
@thchia
Copy link
Collaborator Author

thchia commented Aug 30, 2020

@danielcondemarin marking this as draft for now.

I have added rollup and am bundling the default handler. As a result of this, the build step for this package is getting fragmented, with one thing for default lambda and another for the api lambda and the build function (also, the bundler needs a different tsconfig).

Should we bundle the api lambda too? For now I am just telling the TS process for the existing build to ignore the default lambda file, and letting it get handled by rollup. We can have 2 sub-builds, one for the lambdas and one for the build function, with both going into the dist folder.

@danielcondemarin
Copy link
Contributor

danielcondemarin commented Aug 30, 2020

Should we bundle the api lambda too?

If it isn't much extra work go for it. There is refactor that could be made once the handler is bundled like splitting logic into other files etc.

For now I am just telling the TS process for the existing build to ignore the default lambda file, and letting it get handled by rollup. We can have 2 sub-builds, one for the lambdas and one for the build function, with both going into the dist folder.

Sounds good to me 👍

@thchia thchia force-pushed the feature/preview-mode branch 2 times, most recently from d40579b to 2ce1d38 Compare August 31, 2020 10:53
@thchia
Copy link
Collaborator Author

thchia commented Aug 31, 2020

@danielcondemarin this is good for review. I will squash the commits before we merge and close this though.

  • For some reason, rollup didn't like using a tsconfig that extends another tsconfig. Hence why tsconfig.bundle.json is standalone 🤷‍♀️
  • If the preview token verification fails, it's a "hard fail" rather than sending back a nice 403 page (like pages/_error.js). I'm neither here nor there on this, but I don't think it's necessary to go through the SSR for this.

@thchia thchia changed the title 🚧 Support Preview Mode Support Preview Mode Sep 1, 2020
- Fixed expected uri in origin response.
- Added util to rollup externals as it was breaking.
- Fixed some erroneous logic in the router, since it's now being used in the response handler
- Mocked console errors in tests
@thchia thchia force-pushed the feature/preview-mode branch from c60d647 to 6b95135 Compare September 1, 2020 01:26
@thchia thchia marked this pull request as ready for review September 1, 2020 01:26
@@ -272,7 +313,17 @@ const handleOriginRequest = async ({
}
Copy link
Collaborator

@dphang dphang Sep 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be moved into the else block below just before the await page.render(req, res), so we don't have to check whether it is error page every time

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean we know for a fact that data requests will not result in a possible error page?

Copy link
Collaborator

@dphang dphang Sep 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I guess unmatched data request can still go to pages/_error.js, maybe still need this at the start


it("handles preview mode", async () => {
const event = createCloudFrontEvent({
uri: "/preview",
Copy link
Collaborator

@dphang dphang Sep 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you would need to append trailing slash if trailingSlash is true to the URI, this test runs with both trailingSlash true and false

}
});

if (trailingSlash) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need the trailingSlash block here, I added a redirect test where you can add /preview as one of the tests, it will test both kinds of redirects

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean changing the URI in createCloudFrontEvent to be either /preview or /preview/ depending on whether trailingSlash is true, and then just testing for the expected response?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, basically if trailingSlash is true then you can pass /preview/ as the URI, otherwise it is /preview.

Then you can add the same path /preview as a test case in redirect test, it will auto append trailing slash and test the redirects

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also i think you can add /preview to redirect test (around line 158).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

prerenderManifest.preview.previewModeSigningKey
);
} catch (e) {
return {
Copy link
Collaborator

@dphang dphang Sep 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe some logging (at info level?) is useful here, I added it for 500 page as well, not sure if it's needed for this though

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a console.error, similar to the logging for the 500 response.

Copy link
Collaborator

@dphang dphang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to me besides minor comments, probably @danielcondemarin should approve since it's a bigger change

Copy link
Contributor

@danielcondemarin danielcondemarin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@danielcondemarin danielcondemarin merged commit 5e1ea38 into serverless-nextjs:master Sep 2, 2020
@danielcondemarin
Copy link
Contributor

I'll do some testing and get an alpha published tonight 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants