aws-amplify / amplify-hosting

AWS Amplify Hosting provides a Git-based workflow for deploying and hosting fullstack serverless web applications.
https://aws.amazon.com/amplify/hosting/
Apache License 2.0
449 stars 113 forks source link

Server-side rendering support / SSR #412

Closed ChristopheBougere closed 3 years ago

ChristopheBougere commented 4 years ago

Is your feature request related to a problem? Please describe. I created a web app using Amplify+React. Now I need to work on the SEO, but this requires server-side rendering (I am using react-helmet-async to change <title> and <meta> tags dynamically, but google and other search engines stick with the static versions in index.html. Note that I can't do static exporting (because my page titles and descriptions depend on data from the API).

Describe the solution you'd like I would like server-side rendering to be managed by the Amplify Console itself. Next.js seems to be the best way to do this in React for now, but I would be quite open to other solutions.

Additional context I don't find any workaround to do SSR with Amplify when using hosting. I could surely do SSR by hosting it on my own S3+CloudFront and maybe adding some lambda@edge, but I would definitely miss the managed hosting benefits. However, SEO is a very high priority for the next few months, so I will have to find a solution. The easiest alternative as of now would be to use Zeit Now) for hosting, as described in this post

sebsto commented 4 years ago

Christophe, see https://github.com/aws-amplify/amplify-js/issues/1613

ZachMurray commented 4 years ago

Is your feature request related to a problem? Please describe. I created a web app using Amplify+React. Now I need to work on the SEO, but this requires server-side rendering (I am using react-helmet-async to change <title> and <meta> tags dynamically, but google and other search engines stick with the static versions in index.html. Note that I can't do static exporting (because my page titles and descriptions depend on data from the API).

Describe the solution you'd like I would like server-side rendering to be managed by the Amplify Console itself. Next.js seems to be the best way to do this in React for now, but I would be quite open to other solutions.

Additional context I don't find any workaround to do SSR with Amplify when using hosting. I could surely do SSR by hosting it on my own S3+CloudFront and maybe adding some lambda@edge, but I would definitely miss the managed hosting benefits. However, SEO is a very high priority for the next few months, so I will have to find a solution. The easiest alternative as of now would be to use Zeit Now) for hosting, as described in this post

Same Problem I Have.

agrant-intix commented 4 years ago

@swaminator is there a timeframe on next JS support with Amplify? I note it was added as a feature request on 7 Feb

ChristopheBougere commented 4 years ago

With Next.js support being in public preview (cf https://github.com/aws-amplify/amplify-js/issues/5435), it would be great to know if we can expect it to be supported by the console as well in the short term (so we can still use amplify hosting with SSR).

@swaminator @ericclemmons do you have any information on this topic?

Nickman87 commented 4 years ago

Still looking for a good all-in hosting system for next.js applications. I was thinking the Amplify system would be a great fit but definitely needs good SSR support for it to be usefull. Any news on this?

dabit3 commented 3 years ago

@Nickman87 Amplify hosting support for SSR is in the works!

In the meantime, you can use the Serverless Next.js Component to deploy Next.js to AWS with SSR and API routes.

Here's how:

  1. Create a file called serverless.yml in the root of your Next.js app
  2. Add the following 2 lines of configuration (version should be updated to the latest stable release, which as of this writing is 1.16.0):
myNextAPp:
  component: "@sls-next/serverless-component@1.16.0
  1. Deploy by running npx serverless.

We will update this once Amplify SSR support is officially launched for the hosting service.

ericclemmons commented 3 years ago

@Nickman87 Agreed! We have @dabit3's suggestion documented on our Next.js' Getting Started page, including a short video.

I tested it myself & it worked great πŸ’ͺ

IamManchanda commented 3 years ago

Eagerly awaiting SSR support for AWS Amplify Console for both Next.js (React) & Nuxt.js (Vue) ✈️

ericclemmons commented 3 years ago

@IamManchanda Me too! :) Can you tell me more about your Next.js app?

The more we know about your usage, the better we can support you πŸ’ͺ

agrant-intix commented 3 years ago

Hi @ericclemmons

Can talk for my next.js project wanting AWS console support.

Are you using getInitialProps? Yes Are you using getServerSideProps? Yes Are you using getStaticProps? Not currently Are you using getStaticPaths? Not currently Are you using fallback: true or fallback: false? fallback: false Are you using revalidate at all? No Are you using /api/* routes? Yes Are you running next export or only next build? Only next build

ChristopheBougere commented 3 years ago

For anyone interested in making the console deploying the serverless next.js component (waiting for official support), here is the way I did it:

amplify.yml

version: 1
applications:
  - backend:
      phases:
        preBuild:
          commands:
            - nvm use $VERSION_NODE_12
            - npm ci
        build:
          commands:
            - nvm use $VERSION_NODE_DEFAULT
            - amplifyPush --simple
            - nvm use $VERSION_NODE_12
            - npm run build
            - aws s3 sync "s3://your-deployment-bucket/myamazingapp/${USER_BRANCH}/.serverless" .serverless
            - if [ "${USER_BRANCH}" = "staging" ]; then DOMAIN="example.com" SUBDOMAIN="staging" npx serverless ; fi
            - if [ "${USER_BRANCH}" = "prod" ]; then DOMAIN="example.com" SUBDOMAIN="www" npx serverless ; fi
            - aws s3 sync .serverless "s3://your-deployment-bucket/myamazingapp/${USER_BRANCH}/.serverless"
    frontend:
      phases:
        build:
          commands:
            - echo "Nothing to build here"
      artifacts:
        baseDirectory: .next
        files:
          - '**/*'
      cache:
        paths:
          - node_modules/**/*
    appRoot: web

serverless.yml

myamazingapp:
  component: '@sls-next/serverless-component@1.17.0'
  inputs:
    domain:
      - ${env.SUBDOMAIN}
      - ${env.DOMAIN}

A few notes:

@ericclemmons

damian-tripbuddi commented 3 years ago

I'm keen to see official support for this. As deploying to Vercel has proved to be challenging when my application is using Amplify. The way that Vercel splits SSG and SSR is amazing, and I hope that we can get the same advantages when Amplify Console has proper support for deploy SSR Next Applications.

ericclemmons commented 3 years ago

As deploying to Vercel has proved to be challenging when my application is using Amplify.

@damian-tripbuddi If you have more information or suggestions, please share πŸ™

ghost commented 3 years ago

Could someone please update https://aws.amazon.com/blogs/mobile/ssr-support-for-aws-amplify-javascript-libraries/ to change component: "@sls-next/serverless-component@1.16.0" to component: "@sls-next/serverless-component@1.17.0"?

ChristopheBougere commented 3 years ago

As deploying to Vercel has proved to be challenging when my application is using Amplify.

@damian-tripbuddi If you have more information or suggestions, please share πŸ™

@ericclemmons To follow up on this, the current solution using Serverless Next.js component shows huge perfomance issues for SSR and cold starts (the "require JS execution time" to be more specific, see this issue: https://github.com/serverless-nextjs/serverless-next.js/issues/547). There is a chance this could be linked to my app itself (and accumulation of react HoC), but I wanted to try deploying on Vercel to see if there is a difference. The thing is I don't want to commit my aws-exports.js file, which is mandatory for the build, and there is no simple way to generate it without setting up all the amplify kit, which indeed can be challenging on Vercel. I guess that might be what @damian-tripbuddi pointed out.

dabit3 commented 3 years ago

Thanks @Trevor-mc2, we've updated the post

JeffWeim commented 3 years ago

@dabit3 - I think some people are viewing your post on dev.to (I did) that mention 1.16.0, might be good to update there as well

Thanks @Trevor-mc2, we've updated the post

dabit3 commented 3 years ago

Thanks @JeffWeim, just updated there as well.

IamManchanda commented 3 years ago

Hey @ericclemmons Will the AWS Amplify JS + AWS Amplify Console support (SSR) also plans to include this feature πŸ‘‡ => https://nextjs.org/docs/basic-features/image-optimization (released on oct 27)

tariqinaam commented 3 years ago

@Nickman87 Amplify hosting support for SSR is in the works!

In the meantime, you can use the Serverless Next.js Component to deploy Next.js to AWS with SSR and API routes.

Here's how:

  1. Create a file called serverless.yml in the root of your Next.js app
  2. Add the following 2 lines of configuration (version should be updated to the latest stable release, which as of this writing is 1.16.0):
myNextAPp:
  component: "@sls-next/serverless-component@1.16.0
  1. Deploy by running npx serverless.

We will update this once Amplify SSR support is officially launched for the hosting service.

I am following guide on aws. I was able to run the app locally successfully. Deployed using above serverless component, cli shows successful deployment. However when visiting the cloudfront app url. I get following error: The Lambda function associated with the CloudFront distribution is invalid or doesn't have the required permissions. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.

and console response show LambdaExecutionErro

content-length: 1019 content-type: text/html server: CloudFront status: 503 x-cache: LambdaExecutionError from cloudfront

I checked cloudfront UI, deployment was successful and complete. I am not sure where do i look further to dig in this issue. Any lead would be helpful.|

Update I can see lambda execution is timing out without any further error. I increases execution to 15 sec, but still timing out.

ohlr commented 3 years ago

@tariqinaam you need to redeploy (run serverless) to create the new pages

tariqinaam commented 3 years ago

@tariqinaam you need to redeploy (run serverless) to create the new pages

It's failing on existing page. E.g homepage which obviously exist

dmsolutionz commented 3 years ago

@tariqinaam you need to redeploy (run serverless) to create the new pages

It's failing on existing page. E.g homepage which obviously exist

Increase the timeout to 25, try again. It could be the cold start.

tariqinaam commented 3 years ago

@tariqinaam you need to redeploy (run serverless) to create the new pages

It's failing on existing page. E.g homepage which obviously exist

Increase the timeout to 25, try again. It could be the cold start.

I have increased it to 30sec, but somehow response failing in 10 sec. Is there anything need to be changed to cloudfront side? One thing I noticed that serverless created cloudfront and lambda in us-east-1 region by default. whereas my application is in eu-west-1 region. could there be any permission issue between regions?

dmsolutionz commented 3 years ago

Cloudfront is distributed, it doesn't matter what region it is deployed to, what are your logs saying?

tariqinaam commented 3 years ago

Cloudfront is distributed, it doesn't matter what region it is deployed to, what are your logs saying?

log aren't much helpfull. it only says "Task timed out after 10.01 seconds" even though lambda execution is set to 30 sec

tariqinaam commented 3 years ago

Cloudfront is distributed, it doesn't matter what region it is deployed to, what are your logs saying?

log aren't much helpfull. it only says "Task timed out after 10.01 seconds" even though lambda execution is set to 30 sec

alright, I got it working. All I did was amplify push and npx serverless again. It seems (at least for my app) that amplify push was needed again (even if the app was already updated). so,

Doesnt make much sense but thats what fixed it.

viniciuspardini commented 3 years ago

Hey guys, do you have any sample application or maybe a boilerplate of a next application that you are running on amplify?

estyh commented 3 years ago

I am waiting for this feature - deploying via amplify. I don't need SSR, just support for /api routes with the new ssr context.

krikork commented 3 years ago

Hey guys, is there a tentative ETA on Amplify support for Next.js? A ballpark timeline would help me in making a decision on how to proceed.

agrant-intix commented 3 years ago

@Nickman87 Amplify hosting support for SSR is in the works!

In the meantime, you can use the Serverless Next.js Component to deploy Next.js to AWS with SSR and API routes.

Here's how:

  1. Create a file called serverless.yml in the root of your Next.js app
  2. Add the following 2 lines of configuration (version should be updated to the latest stable release, which as of this writing is 1.16.0):
myNextAPp:
  component: "@sls-next/serverless-component@1.16.0
  1. Deploy by running npx serverless.

We will update this once Amplify SSR support is officially launched for the hosting service.

I managed to follow this solution to get setup. It ideally seems that if this process could be replicated within the AWS console on builds then everything would all work out?

tariqinaam commented 3 years ago

I ended up using vercel for frontend app, and whole solution is working nicely. I have appsync for backend/api and frontend deployed on vercel. Only thing I couldn't figure out was aws-export.js, I had to commit it in repository for two system to work together.

DaveHudson commented 3 years ago

I wouldn't commit aws-export.js. it’s git ignored for a reason, it’s full of secrets.

If you need to use Vercel for SSR support I'd recommend replacing the entire DevOps pipeline Amplify provides for you. You could do this with GitHub actions. It's essentially a two step process:

  1. Run an amplify pull command in headless mode https://docs.amplify.aws/cli/usage/headless to download an Amplify backend you want to deploy with your frontend (this will include your aws-exports.js file).
  2. Deploy to Vercel, there is a GitHub action to do this https://github.com/marketplace/actions/vercel-action

You should use GitHub secrets to store any keys / tokens needed in the GitHub action for AWS and Vercel

kazukinagata commented 3 years ago

Hi there, I write a sample code based on @DaveHudson. See how to use vercel action.

Please let me know if you have any advice on how to improve the code!

# .github/workflows/deploy.yml
name: Deploy to vercel

on:
  push:
    branches: [main]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  deploy:
    name: deploy amplify app to vercel
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
      - name: Install amplify cli
        run: npm install --global --unsafe-perm @aws-amplify/cli@latest
      - name: Pull amplify
        run: ./.github/scripts/pull-amplify.sh
        shell: bash
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_REGION: ${{ secrets.AWS_REGION }}
      - name: Deploy
        uses: amondnet/vercel-action@v20.0.0
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }} # Required
          github-comment: false # Optional
          vercel-args: '--prod' #Optional
          vercel-org-id: ${{ secrets.ORG_ID}} #Required
          vercel-project-id: ${{ secrets.PROJECT_ID}} #Required
#!/bin/bash

#.github/scripts/pull-amplify.sh
set -e
IFS='|'

if [ -z "$AWS_ACCESS_KEY_ID" ] && [ -z "$AWS_SECRET_ACCESS_KEY" ] ; then
  echo "You must provide the action with both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables in order to deploy"
  exit 1
fi

if [ -z "$AWS_REGION" ] ; then
  echo "You must provide AWS_REGION environment variable in order to deploy"
  exit 1
fi

REACTCONFIG="{\
\"SourceDir\":\"src\",\
\"DistributionDir\":\"build\",\
\"BuildCommand\":\"npm run-script build\",\
\"StartCommand\":\"npm run-script start\"\
}"
AWSCLOUDFORMATIONCONFIG="{\
\"configLevel\":\"project\",\
\"useProfile\":false,\
\"profileName\":\"default\",\
\"accessKeyId\":\"$AWS_ACCESS_KEY_ID\",\
\"secretAccessKey\":\"$AWS_SECRET_ACCESS_KEY\",\
\"region\":\"$AWS_REGION\"\
}"
AMPLIFY="{\
\"projectName\":\"<Your Project Name>\",\
\"appId\":\"<Your App ID>\",\
\"envName\":\"<Your Env>\",\
\"defaultEditor\":\"code\"\
}"
FRONTEND="{\
\"frontend\":\"javascript\",\
\"framework\":\"react\",\
\"config\":$REACTCONFIG\
}"
PROVIDERS="{\
\"awscloudformation\":$AWSCLOUDFORMATIONCONFIG\
}"

echo "amplify version $(amplify --version)"

amplify pull \
--amplify $AMPLIFY \
--frontend $FRONTEND \
--providers $PROVIDERS \
--yes
DaveHudson commented 3 years ago

That is pretty much how I have it too πŸ‘

IamManchanda commented 3 years ago

Hello everyone, any updates on SSR Hosting?

dabit3 commented 3 years ago

Hey @IamManchanda, SSR support actively being developed but there is not a release date that we can share atm.

tmcw commented 3 years ago

It's pretty confusing that there's documentation for using Next.js with SSR, under the Amplify section of the documentation. I for one thought that the blog post about Amplify JavaScript getting SSR support and SSR Support for Amplify JavaScript, that Amplify had SSR support - but it seems, from this backscroll, that the amplify libraries support SSR, as long as you don't use Amplify-the-AWS-platform-product. It really seems like all these posts are announcing is that the "Amplify npm module works in Node and passes cookies through", not anything related to SSR rendering at all.

The comments on that blog post indicate that most of the other readers also were confused about this tricky distinction - that when the post refers to "an Amplify app", it is not referring to an app running "in Amplify", but an app that "uses the Amplify node module." I would assume that people assume the former, not the latter.

ibrahimcesar commented 3 years ago

As a long follower in this thread, just adding more context, I was using Serverless Next.js Component to deploy Next.js to AWS with SSR and API routes which works great with zero config but... I don't know how many are aware but as pointed both in Reddit then Twitter, this ships our account credentials to Serverless Framework for components.

Anyone trying to stick to Well-Architected Framework should take this as a liability in use it. I would love an ETA but I know is not a trivial feat either, with all other integrations and priorities going on. So, adding one more comment to SSR Hosting.

I'm trying to build a construct for CDK in the meantime, so if someone want to joined me, just reach out!

arjunnaha commented 3 years ago

A PR that adds a CDK construct to the Serverless Next.js Component is open and very close to being merged. This uses the builder function on the component to generate the Lambdas.

ibrahimcesar commented 3 years ago

Thanks a lot @arjunnaha for point me out!

A PR that adds a CDK construct to the Serverless Next.js Component is open and very close to being merged. This uses the builder function on the component to generate the Lambdas.

chrisl777 commented 3 years ago

To build on this use-case, what we would like to do in most projects, is to have good SEO for landing pages, blog, etc. But then after the user logs in, the site can be completely dynamic (for example, a user dashboard, settings page, managing payments, etc.). With the coming SSR approach, would there be a way to mix, i.e. SSR for the top-level pages, but dynamic for the post-login experience?

IamManchanda commented 3 years ago

Yes @chrisl777 Infact you can already do that with Vercel or Serverless Next.js deployment ... the thing awaited is "AWS Amplify Console" to support same

ibrahimcesar commented 3 years ago

Yes, the missing part basically is this. Which I must say is not something trivial. But already, in experimental model, is possible with CDK from Serverless Next.Js, a made a little write-up: https://dev.to/aws-builders/full-stack-cloud-ssr-with-next-js-tailwind-and-aws-cdk-416c and here an repo with an example: https://github.com/ibrahimcesar/next.js-amplify-workshop-with-cdk More and more I been using Amplify + CDK, so fits my workflow

nimacks commented 3 years ago

We are requesting feedback for a preview of SSR support in the Amplify Console. If you're interested in testing it out, send an email to [REDACTED] with the following details:

  1. Name
  2. AWS account Id
ibrahimcesar commented 3 years ago

Great!

Just applied. Waiting for this feature for a long time!

We are requesting feedback for a preview of SSR support in the Amplify Console. If you're interested in testing it out, send an email to [REDACTED] with the following details:

  1. Name
  2. AWS account Id
akan01n commented 3 years ago

Nice, just applied too!

We are requesting feedback for a preview of SSR support in the Amplify Console. If you're interested in testing it out, send an email to [REDACTED] with the following details:

1. Name

2. AWS account Id
IamManchanda commented 3 years ago

Thanks @nimacks ... I will surely do that tomorrow morning ... πŸ‘ (Late night here in India)

medelman17 commented 3 years ago

You shouldn't need to because this feature just works, but feel free to hit me up if you have any issues once you get activated, y'all. I've had the very enviable opportunity of getting to mess around with this for about a month now! I'm extremely confident that you're going to have a lot of fun, here.

IamManchanda commented 3 years ago

Yes @medelman17 I understand you especially on personal projects, "serverless next.js" is great but when it comes to offering stuff to clients, the best is to go with official stuff and thus AWS Amplify Console with "Dynamic/SSR" Hosting Support is really must πŸ‘ ...