Just migrated my NextJS project over from Amplify ...
# help
y
Just migrated my NextJS project over from Amplify to Seed. Everything seems to work perfectly but I'm realizing that previews don't work. Previewing PRs works fine but the particular use case that I'm looking to support is previewing content changes using the NextJS advanced previews feature: https://nextjs.org/docs/advanced-features/preview-mode. Any thoughts? This seems like it would require reading the
preview
cookie and bypassing the CDN and regenerate the page @ edge.
Our CMS (contentful) lets us specify a url pattern for preview generation
In the case of NextJS we specify a url like:
Copy code
https://<your-site>/api/preview?secret=<token>&slug=<path>
I now see this might an issue being worked on further upstream
f
Hey @Yousef, I know preview mode should be well supported by the underlying
lambda-at-edge
package - https://github.com/serverless-nextjs/serverless-next.js/pull/562
Let me look into how it’s configured.
I think this was an edge case that may have been resolved recently. Going to test it out
f
The
NextjsSite
uses a forked version of
lambda-at-edge
and pins it at v3.3.0.
Hmm is this resolved in v3.4.0-alpha.9?
y
ah ok hmmm
I'm unsure -- thought I'd be able to pin to latest to test but I suppose I can't.
f
Is it showing the statically generated page instead of the previewed page for you?
Here is the url
It sets cookie and redirects but appears to 500
if you remove the cookie you can see the page
f
got it.
y
!?
f
Let me give it a try.
Sorry I meant I see the 500 as well.
y
ah
f
I’m going to setup preview mode on my end now, and dig into it.
y
👍 fyi, these pages do use revalidate params as well
This also does seem to affect my amplify builds
So I presume it might be further upstream
f
Oh you mean you get 500 on Amplify as well?
y
correct
I've now moved from vercel -> amplify -> seed
This was a non-issue with vercel but has been since moving off
f
lol.. i see.. debugging it in SST should be easier than amplify… u have full transparency and full control over the resources
y
If it's simple enough to update the serverlessjs dependency to 3.4.0-alpha9 I can verify if this has been since resolved
f
Btw, have u tried turning off revalidate, and see if you still get 500?
y
not yet but I can give that a shot
f
That shouldn’t be related, but why not give it a try.
y
brb after 16 min build lol
f
If you want to test out 3.4.0-alpha9, you can: 1. add a
serverless.yml
in your project with content:
Copy code
myNextApplication:
  component: "@sls-next/serverless-component@3.4.0-alpha.9"
2. npm/yarn install -g serverless (or install locally) 3. run
serverless
y
👍
f
This will use Serverless Component to deploy the site, might be the quickest way to checkup on 3.4.0-alpha9.
Run
serverless remove
and remove
serverless.yml
to clean everything up afterwards.
okay.. lemme setup preview mode on my end in the mean while
y
Thanks for the help -- don't mean to cause a distraction!
f
Np! Just got preview mode working locally.. deploying to live now
I just took a peak at ur build time on Seed, building Next.js app took 6min, does it take that long on Amplify and Vercel?
y
I see anywhere between 16-22 min to build and deploy
Across Seed, Amplify and Vercel
Build optimization is something I'm actively working on for this project
What variables contribute to longer deployment times? Size of static assets?
Removing revalidate didn't seem to solve the issue
f
hmm.. preview mode seems to work for me
You should see
IsPreview: false
It will set the cookie and then redirects to
/preview
y
hmmm
f
And you will see
IsPreview: true
This is the code for
/api/preview
Copy code
export default function handler(req, res) {
  res.setPreviewData({})
  res.redirect('/preview')
}
And this is the cleaned up code for
/preview
Copy code
export async function getStaticProps(context) {
  return {
    props: {
      isPreview: context.preview ? "true" : "false",
    }
  }
}

export default function Post({ isPreview, envUrl }) {
  return (
    <h1>Is Preview: {isPreview}</h1>
  )
}
See if you spot anything obvious.
If not, we can dig into ur Lambda log in CloudWatch
y
Nothing immediately obvious as to why I get 500s.
Ok...so now it works.
I stopped pre-rendering
Copy code
export async function getStaticPaths({ locales }: GetStaticPathsContext) {
  const allPages = await getAllPagesWithSlug()

  return {
    paths: [], // getLocalePaths(allPages, locales),
    fallback: 'blocking',
  }
}
are you setting getStaticPaths() ?
works perfectly fine now without the pre-rendering I was doing
Can you try pre-rendering by setting getStaticPaths?
f
lemme give it a try
Got it setup locally. Deploying..
/api/preview
looks like this now (takes a slug query string and redirects to it)
Copy code
export default function handler(req, res) {
  res.setPreviewData({})
  res.redirect(req.query.slug)
}
/ssg-preview/[id]
looks like this now (2 pages,
/ssg-preview/hello
and
/ssg-preview/world
)
Copy code
export async function getStaticProps(context) {
  return {
    props: {
      title: context.params.id,
      isPreview: context.preview ? "true" : "false",
    }
  }
}

export async function getStaticPaths() {
  return {
    paths: [
      {
        params: {
          id: "hello"
        }
      },
      {
        params: {
          id: "world"
        }
      }
    ],
    fallback: false
  }
}

export default function Post({ title, isPreview }) {
  return (
    <div>
      <h1>Title: {title}</h1>
      <h1>IsPreview: {isPreview}</h1>
    </div>
  )
}
y
nice
you're a nextjs pro!
f
lol that’s an overstatement 🤣
y
at this point I'm curious as to whether this is truly a bug -- but I'm ok with this tradeoff (not pre-rendering)
f
hmm that also worked
That will redirect to /ssg-preview/hello, and it shows
true
Not sure how much work would it be if you removed all other pages in ur app and just had the
/[id]
page and the preview api route. And instead of hitting contentful for content, put in some dummy content inline. Strip it to the minimal and see if the issue still persist?
y
I will give that a try. Thanks for your help. I'll let you know once I've identified the issue
f
Yup! Keep me posted.
y
So I was able to get past these issues on my end and after carefully testing things looked good but after going live I think we might be seeing a more recent issue come up in prodcutio
I'm going to try to deploy serverless with alpha9 to see if it resolves
The gist here is that locale redirects aren't being respected appropriately, causing 404s
f
Oh I see. Yeah I did see one of the recent alpha releases had a locale fix.
y
oh no
How much lift would it be to get that fix in there -- after some testing we decided to go live
today
f
Did you get a chance to try out the alpha9?
y
not yet -- hitting some difficulty with that at the moment. About to give redirecting on the specific path a try
Copy code
/en-GB//* -> /en-GB/*
f
Lemme give it a try on my end. How can I reproduce the locale redirect issue?
y
Ok so let me summarize what I'm seeing
https://hautehijab.com/en-GB https://dev.hautehijab.com/en-GB Once you get past modal and select 'UK' you should be able to click Shop -> Underscarves
What is weird is that the code running in both stages should be the same but the behaviour seems different
I'm running another deployment for good measure to both dev and prod
If you want to hold off on testing this -- I can try to reproduce with a smaller example on my end to see if it persists
@Frank do you know if there's any issue swapping the custom domain configuration to use www as the default instead of directing www -> naked
f
Should work. Give it a try!
y
welp i think i made things worse
Copy code
Resource handler returned message: "Invalid request provided: The specified SSL certificate doesn't exist, isn't in us-east-1 region, isn't valid, or doesn't include a valid certificate chain. (Service: CloudFront, Status Code: 400, Request ID: e4799a06-2d30-47de-9473-44e41e092cdc, Extended Request ID: null)" (RequestToken: b9b46af0-6649-563d-7cce-6eb87bf19b41, HandlerErrorCode: InvalidRequest)
f
Can I see how you are defining the
NextjsSite
?
y
Copy code
import * as sst from '@serverless-stack/resources';

export default class MyStack extends sst.Stack {
  constructor(scope: any, id: string, props: any) {
    super(scope, id, props);

    const site = new sst.NextjsSite(this, 'NextSite', {
      path: './',
      customDomain: {
        domainName:
          scope.stage === "prod" ? "<http://hautehijab.com|hautehijab.com>" : `${scope.stage}.<http://hautehijab.com|hautehijab.com>`,
        domainAlias: scope.stage === "prod" ? "<http://www.hautehijab.com|www.hautehijab.com>" : undefined,
        hostedZone: "<http://hautehijab.com|hautehijab.com>",
      }
    });

    this.addOutputs({
      URL: site.url,
    });
  }
}
originally it was like this
but then i wanted to swap the dns defaults
to
Copy code
import * as sst from '@serverless-stack/resources';

export default class MyStack extends sst.Stack {
  constructor(scope: any, id: string, props: any) {
    super(scope, id, props);

    const site = new sst.NextjsSite(this, 'NextSite', {
      path: './',
      customDomain: {
        domainName:
          scope.stage === "prod" ? "<http://www.hautehijab.com|www.hautehijab.com>" : `${scope.stage}.<http://hautehijab.com|hautehijab.com>`,
        domainAlias: scope.stage === "prod" ? "<http://hautehijab.com|hautehijab.com>" : undefined,
        hostedZone: "<http://hautehijab.com|hautehijab.com>",
      }
    });

    this.addOutputs({
      URL: site.url,
    });
  }
}
i would consider destroying the stack and rebuilding it but this is serving production at this point
dont want have any dns propagation issues
Deleting stack and rebuilding
Is it possible to remap a new stage 'production' to production in seed
nvm figured itout
So I swapped the dns attributes in the new stack and now locale redirects are working fine
f
@Yousef were you able to get the www domain with naked alias to work?
y
Yes after destroying the stack and rebuilding it with the following
Copy code
const site = new sst.NextjsSite(this, 'NextSite', {
      path: './',
      customDomain: {
        domainName:
          scope.stage === "production" ? "<http://www.hautehijab.com|www.hautehijab.com>" : `${scope.stage}.<http://hautehijab.com|hautehijab.com>`,
        domainAlias: scope.stage === "production" ? "<http://hautehijab.com|hautehijab.com>" : undefined,
        hostedZone: "<http://hautehijab.com|hautehijab.com>",
      }
    });
I had to use
www
as the default domain and naked domain as the alias
everything is working smoothly so far
f
Nice! 🤞