serverless-nextjs / serverless-next.js

⚡ Deploy your Next.js apps on AWS Lambda@Edge via Serverless Components
MIT License
4.45k stars 454 forks source link

Specify a path in the bucket #851

Open lcswillems opened 3 years ago

lcswillems commented 3 years ago

Hi,

I know I can customize the bucket in which my code is stored with bucketName parameter. Is there a way to customize the path where the code is store in the bucket? It seems to be stored at the root but I would like it stored in a subfolder.

dphang commented 3 years ago

It only does if it you have basepath set, there is currently no way to define custom S3 path. May I ask what is the use case for this? Are you planning to store other things in the same bucket?

lcswillems commented 3 years ago

Do you have a link to basepath? I can't find any information about it.

Two use cases:

  1. I want to keep a copy of all my deployments without having to create a new bucket everytime.
  2. I do multiple simultaneous deployments on different stages.
dphang commented 3 years ago

Basepath is a Next.js feature: https://nextjs.org/docs/api-reference/next.config.js/basepath, it is meant for setting a path prefix for all your pages, so probably not what you want.

The use cases seem interesting, but I'm not quite sure if having a custom path within the same bucket is the right solution. For example, for use case (2), although it can work, it might not be a good idea to store multiple apps in the same bucket due to possible conflicts, such as making cleanup harder (right now I think we just delete the s3 bucket). I think it is better to have multiple serverless.yml and store the .serverless state separately for each stage.

And for (1), after a successful deployment, you could just store the .serverless_nextjs directory somewhere else, which has all the build outputs (static assets, lambda code, etc.) for that specific build. Right now (as of the latest alpha version), this component will preserve only the last 2 versions of outputs (pages + next data) in the S3 bucket to help when transitioning between Lambda versions.

Let's see what @danielcondemarin might have to say on this?

lcswillems commented 3 years ago

Thank you for your answer!

Why it would make to cleanup harder?

Why is it better to multiple serverless.yml? I have a stage per branch... and a lot of branches.

Why could I just store the .serverless_nextjs directory? How do I quickly rollback to a previous version?

dphang commented 3 years ago

Thank you for your answer!

Why it would make to cleanup harder?

This is because in the component's remove method, it removes the entire S3 bucket - by design one bucket stores only one app. See here: https://github.com/serverless-nextjs/serverless-next.js/blob/6adaf00bb12464c67fb26156cc0a10fcf9dbb816/packages/serverless-components/nextjs-component/src/component.ts#L746-L751

Why is it better to multiple serverless.yml? I have a stage per branch... and a lot of branches.

Usually to separate by multiple stages, see here for example: https://github.com/serverless-nextjs/serverless-next.js#cicd-multi-stage-deployments--a-new-cloudfront-distribution-is-created-on-every-ci-build-i-wasnt-expecting-that

Why could I just store the .serverless_nextjs directory? How do I quickly rollback to a previous version?

Currently these are the outputs of doing the deployment, so you could store it for history purposes only. For example create an action to move to S3, save as a CI/CD artifact, etc.

Right now I think the only good way to rollback is to build and redeploy an older version since with the latest alpha version, only the last 2 versions of pages/next data in S3 bucket are stored.. so just resetting the Lambda function versions would not work correctly (plus you would need to do this manually for both API and default lambdas). We could possibly improve in the future by allowing to store the last X versions instead of just 2.

lcswillems commented 3 years ago
dphang commented 3 years ago

@lcswillems yeah I understand, right now I am just trying to clarify how it is designed and the limitations due to that, so we can understand the proposal better.

I guess that unfortunately this was not designed with more complex deployment strategies in mind - more like one app per S3 bucket corresponding to a serverless.yml config file. So having multiple stages/apps involves doing something custom like having multiple serverless.yml files, maintaining your deployment state in S3 buckets and syncing etc before deployments (as the link here mentions: https://github.com/serverless-nextjs/serverless-next.js#cicd-multi-stage-deployments--a-new-cloudfront-distribution-is-created-on-every-ci-build-i-wasnt-expecting-that).

It's definitely on our roadmap to make this deployment state management more of a first-class concept, probably building it using Terraform/S3/etc. Thereafter, I think it might become easier to manage multiple branches / app deployments.

lcswillems commented 3 years ago

Okay @dphang! Thanks a lot for the dedicate to this project!!

mrjomp commented 3 years ago

I find the bucket prefix to be really useful if you wanted to use an existing bucket that already has some content in it.

Also that bucket prefix will need to get updated on the CloudFront Origin Path such that data gets pulled from that prefix as well.

mrjomp commented 3 years ago

Do you have a link to basepath? I can't find any information about it.

Two use cases:

  1. I want to keep a copy of all my deployments without having to create a new bucket everytime.
  2. I do multiple simultaneous deployments on different stages.

I'd like to do the same as well, I'd like to reuse a bucket with multiple bucket prefixes which will be used by different environments such as dev, qa, stage and prod. All living in the same bucket.

kyledecot commented 3 years ago

👋 Any update on support for this? My use case is similar to that of @lcswillems in that I would like to keep a history of "releases" under a prefix (e.g. releases/{SHA}/...) then use in conjunction with the distribution's Origin Path.

dphang commented 3 years ago

Yes, I think now with CloudFront functions it's easier to support a prefix path in S3 bucket. As we want to handle the static and _next/static without the overhead of a full Lambda (as it's not needed since they map directly to S3 paths). I think we should be able to modify the URI to add the prefix to ensure it routes correctly to S3 bucket