cdk-nextjs 0.2.7 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.jsii +74 -71
  2. package/API.md +23 -13
  3. package/README.md +10 -6
  4. package/assets/lambdas/assets-deployment/assets-deployment.lambda/index.js +1 -1
  5. package/docs/breaking-changes.md +6 -0
  6. package/docs/cdk-nextjs-NextjsGlobalContainers.png +0 -0
  7. package/docs/cdk-nextjs-NextjsGlobalFunctions.png +0 -0
  8. package/docs/cdk-nextjs-NextjsRegionalContainers.png +0 -0
  9. package/docs/cdk-nextjs.drawio +29 -35
  10. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +1 -1
  11. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  12. package/lib/lambdas/assets-deployment/fs-to-s3.js +6 -2
  13. package/lib/nextjs-assets-deployment.js +1 -1
  14. package/lib/nextjs-build/cache-handler.cjs +676 -704
  15. package/lib/nextjs-build/global-containers.Dockerfile +1 -3
  16. package/lib/nextjs-build/global-functions.Dockerfile +2 -3
  17. package/lib/nextjs-build/nextjs-build.js +5 -11
  18. package/lib/nextjs-build/regional-containers.Dockerfile +1 -3
  19. package/lib/nextjs-compute/nextjs-containers.js +5 -8
  20. package/lib/nextjs-compute/nextjs-functions.js +1 -1
  21. package/lib/nextjs-distribution.d.ts +4 -4
  22. package/lib/nextjs-distribution.js +4 -5
  23. package/lib/nextjs-file-system.js +1 -1
  24. package/lib/nextjs-invalidation.js +1 -1
  25. package/lib/nextjs-revalidation.js +1 -1
  26. package/lib/nextjs-static-assets.js +1 -1
  27. package/lib/nextjs-vpc.d.ts +20 -8
  28. package/lib/nextjs-vpc.js +25 -11
  29. package/lib/root-constructs/nextjs-global-containers.js +1 -1
  30. package/lib/root-constructs/nextjs-global-functions.js +1 -1
  31. package/lib/root-constructs/nextjs-regional-containers.js +1 -1
  32. package/package.json +14 -16
  33. package/lib/nextjs-build/symlink.d.ts +0 -1
  34. package/lib/nextjs-build/symlink.js +0 -47
  35. package/lib/nextjs-build/symlink.mjs +0 -28
package/.jsii CHANGED
@@ -7,7 +7,7 @@
7
7
  ]
8
8
  },
9
9
  "dependencies": {
10
- "aws-cdk-lib": "^2.177.0",
10
+ "aws-cdk-lib": "^2.186.0",
11
11
  "constructs": "^10.0.5"
12
12
  },
13
13
  "dependencyClosure": {
@@ -37,32 +37,6 @@
37
37
  }
38
38
  }
39
39
  },
40
- "@aws-cdk/asset-kubectl-v20": {
41
- "targets": {
42
- "dotnet": {
43
- "namespace": "Amazon.CDK.Asset.KubectlV20",
44
- "packageId": "Amazon.CDK.Asset.KubectlV20"
45
- },
46
- "go": {
47
- "moduleName": "github.com/cdklabs/awscdk-asset-kubectl-go",
48
- "packageName": "kubectlv20"
49
- },
50
- "java": {
51
- "maven": {
52
- "artifactId": "cdk-asset-kubectl-v20",
53
- "groupId": "software.amazon.awscdk"
54
- },
55
- "package": "software.amazon.awscdk.cdk.asset.kubectl.v20"
56
- },
57
- "js": {
58
- "npm": "@aws-cdk/asset-kubectl-v20"
59
- },
60
- "python": {
61
- "distName": "aws-cdk.asset-kubectl-v20",
62
- "module": "aws_cdk.asset_kubectl_v20"
63
- }
64
- }
65
- },
66
40
  "@aws-cdk/asset-node-proxy-agent-v6": {
67
41
  "targets": {
68
42
  "dotnet": {
@@ -967,6 +941,19 @@
967
941
  }
968
942
  }
969
943
  },
944
+ "aws-cdk-lib.aws_cognito_identitypool": {
945
+ "targets": {
946
+ "dotnet": {
947
+ "namespace": "Amazon.CDK.AWS.Cognito.Identitypool"
948
+ },
949
+ "java": {
950
+ "package": "software.amazon.awscdk.services.cognito.identitypool"
951
+ },
952
+ "python": {
953
+ "module": "aws_cdk.aws_cognito_identitypool"
954
+ }
955
+ }
956
+ },
970
957
  "aws-cdk-lib.aws_comprehend": {
971
958
  "targets": {
972
959
  "dotnet": {
@@ -1643,6 +1630,19 @@
1643
1630
  }
1644
1631
  }
1645
1632
  },
1633
+ "aws-cdk-lib.aws_gameliftstreams": {
1634
+ "targets": {
1635
+ "dotnet": {
1636
+ "package": "Amazon.CDK.AWS.GameLiftStreams"
1637
+ },
1638
+ "java": {
1639
+ "package": "software.amazon.awscdk.services.gameliftstreams"
1640
+ },
1641
+ "python": {
1642
+ "module": "aws_cdk.aws_gameliftstreams"
1643
+ }
1644
+ }
1645
+ },
1646
1646
  "aws-cdk-lib.aws_globalaccelerator": {
1647
1647
  "targets": {
1648
1648
  "dotnet": {
@@ -3268,6 +3268,19 @@
3268
3268
  }
3269
3269
  }
3270
3270
  },
3271
+ "aws-cdk-lib.aws_scheduler_targets": {
3272
+ "targets": {
3273
+ "dotnet": {
3274
+ "namespace": "Amazon.CDK.AWS.Scheduler.Targets"
3275
+ },
3276
+ "java": {
3277
+ "package": "software.amazon.awscdk.services.scheduler.targets"
3278
+ },
3279
+ "python": {
3280
+ "module": "aws_cdk.aws_scheduler_targets"
3281
+ }
3282
+ }
3283
+ },
3271
3284
  "aws-cdk-lib.aws_sdb": {
3272
3285
  "targets": {
3273
3286
  "dotnet": {
@@ -3815,19 +3828,6 @@
3815
3828
  }
3816
3829
  }
3817
3830
  },
3818
- "aws-cdk-lib.lambda_layer_kubectl": {
3819
- "targets": {
3820
- "dotnet": {
3821
- "namespace": "Amazon.CDK.LambdaLayer.Kubectl"
3822
- },
3823
- "java": {
3824
- "package": "software.amazon.awscdk.lambdalayer.kubectl"
3825
- },
3826
- "python": {
3827
- "module": "aws_cdk.lambda_layer_kubectl"
3828
- }
3829
- }
3830
- },
3831
3831
  "aws-cdk-lib.lambda_layer_node_proxy_agent": {
3832
3832
  "targets": {
3833
3833
  "dotnet": {
@@ -3938,7 +3938,7 @@
3938
3938
  "stability": "stable"
3939
3939
  },
3940
3940
  "homepage": "https://github.com/cdklabs/cdk-nextjs.git",
3941
- "jsiiVersion": "5.5.25 (build c24bfd2)",
3941
+ "jsiiVersion": "5.5.26 (build adcbaf3)",
3942
3942
  "keywords": [
3943
3943
  "aws",
3944
3944
  "aws-cdk",
@@ -3958,7 +3958,7 @@
3958
3958
  },
3959
3959
  "name": "cdk-nextjs",
3960
3960
  "readme": {
3961
- "markdown": "![Version](https://img.shields.io/github/v/release/cdklabs/cdk-nextjs)\n[![npm version](https://img.shields.io/npm/v/cdk-nextjs.svg?style=flat-square)](https://www.npmjs.org/package/cdk-nextjs)\n![License](https://img.shields.io/github/license/cdklabs/cdk-nextjs)\n\n# CDK Next.js Construct Library\n\n<!--BEGIN STABILITY BANNER-->\n\n---\n\n![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge)\n\n> The APIs of higher level constructs in this module are experimental and under active development.\n> They are subject to non-backward compatible changes or removal in any future version. These are\n> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be\n> announced in the release notes. This means that while you may use them, you may need to update\n> your source code when upgrading to a newer version of this package.\n\n---\n\n<!--END STABILITY BANNER-->\n\nDeploy [Next.js](https://nextjs.org/) apps on [AWS](https://aws.amazon.com/) with the [AWS CDK](https://aws.amazon.com/cdk/).\n\n## Features\n\n- Supports all features of Next.js App and Pages Router for [Node.js Runtime](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes#nodejs-runtime)\n- Choose your AWS architecture for Next.js with the supported constructs: `NextjsGlobalFunctions`, `NextjsGlobalContainers`, `NextjsRegionalContainers`.\n- Global Content Delivery Network (CDN) built with [Amazon CloudFront](https://aws.amazon.com/cloudfront/) to deliver content with low latency and high transfer speeds.\n- Serverless functions powered by [AWS Lambda](https://aws.amazon.com/lambda/) or serverless containers powered by [AWS Fargate](https://aws.amazon.com/fargate/).\n- Static assets (JS, CSS, public folder) are stored and served from [Amazon Simple Storage Service (S3)](https://aws.amazon.com/s3/) for global constructs to decrease latency and reduce compute costs.\n- [Optimized images](https://nextjs.org/docs/pages/building-your-application/optimizing/images), [data cache](https://nextjs.org/docs/app/building-your-application/caching#data-cache), and [full route cache](https://nextjs.org/docs/app/building-your-application/caching#full-route-cache) are shared across compute with [Amazon Elastic File System (EFS)](https://aws.amazon.com/efs/).\n- Customize every construct via `overrides`.\n- WIP: When using AWS Lambda for compute, async revalidation is supported with [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/).\n- AWS security and operational best practices are utilized, guided by [cdk-nag](https://github.com/cdklabs/cdk-nag).\n- First class support for [monorepos](https://monorepo.tools/).\n- [AWS GovCloud (US)](https://aws.amazon.com/govcloud-us) compatible (with `NextjsRegionalContainers`).\n\n## Getting Started\n\n1. If you don’t have a Next.js project yet, follow [these steps](https://nextjs.org/docs/getting-started) to create one.\n1. Install [Docker](https://www.docker.com/). We recommend [Rancher Desktop](https://rancherdesktop.io/) with dockerd (moby) container engine enabled.\n1. Install [Node.js](https://nodejs.org/en). We recommend the long term support (LTS) version.\n1. Set your [next.config.js](https://nextjs.org/docs/pages/api-reference/next-config-js) [output](https://nextjs.org/docs/pages/api-reference/next-config-js/output) key to `\"standalone\"`. Learn more here about [Standalone Output](https://nextjs.org/docs/pages/api-reference/next-config-js/output#automatically-copying-traced-files).\n1. Setup [AWS Cloud Development Kit](https://docs.aws.amazon.com/cdk/v2/guide/home.html) app.\n1. Install the construct package: `npm install cdk-nextjs`\n1. `cdk deploy`\n1. Visit URL printed in terminal (CloudFormation Output) to view your Next.js app!\n\n## Basic Example CDK App\n\n```ts\nimport { App, Stack, StackProps } from \"aws-cdk-lib\";\nimport { Construct } from \"constructs\";\nimport { fileURLToPath } from \"node:url\";\nimport { NextjsGlobalFunctions } from \"cdk-nextjs\";\n\nclass NextjsStack extends Stack {\n constructor(scope: Construct, id: string, props: StackProps = {}) {\n super(scope, id, props);\n new NextjsGlobalFunctions(this, \"Nextjs\", {\n healthCheckPath: \"/api/health\",\n buildContext: fileURLToPath(new URL(\"..\", import.meta.url)),\n });\n }\n}\n\nconst app = new App();\n\nnew NextjsStack(app, \"nextjs\");\n```\n\nSee [examples/](./examples/) for more usage examples.\n\n## Architecture\n\n### `NextjsGlobalFunctions`\n\nArchitecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this construct when you have unpredictable traffic, can afford occasional latency (i.e. cold starts - [typically 1% of production traffic](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/)), and/or want the most granular pricing model. ([code](./src/root-constructs/nextjs-global-functions.ts#L81))\n\n![NextjsGlobalFunctions](./docs/cdk-nextjs-NextjsGlobalFunctions.png)\n\n### `NextjsGlobalContainers`\n\nArchitecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this option when you have predictable traffic, need the lowest latency, and/or can afford a less granular pricing model. ([code](./src/root-constructs/nextjs-global-containers.ts#L76))\n\n![NextjsGlobalContainers](./docs/cdk-nextjs-NextjsGlobalContainers.png)\n\n### `NextjsRegionalContainers`\n\nArchitecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) to regionally serve requests. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-containers.ts#L41))\n\n![NextjsRegionalContainers](./docs/cdk-nextjs-NextjsRegionalContainers.png)\n\n## Why\n\nThe simplest path to deploy Next.js is on [Vercel](https://vercel.com/) - the Platform-as-a-Service company behind Next.js. However, deploying to Vercel can be expensive and some developers want all of their workloads running _directly_ on AWS. Developers can deploy Next.js on AWS through [AWS Amplify Hosting](https://docs.aws.amazon.com/amplify/latest/userguide/ssr-Amplifysupport.html), but Amplify does not support all Next.js features and manages AWS resources for you so they cannot be customized. If Amplify meets your requirements we recommend you use it, but if you want to use all Next.js features or want more visibility into the AWS resources then this construct is for you.\n\n## Design Principles\n\n- Treat Next.js as black box. Minimize reliance on Next.js internal APIs to reduce chance of incompatibility between this construct and future versions of Next.js.\n- Security first.\n- One architecture does not fit all.\n- Enable customization everywhere.\n\n## Limitations\n\n- If using `NextjsGlobalFunctions` or `NextjsGlobalContainers` (which use CloudFront), the number of top level files/directories cannot exceed 25, the max number of behaviors a CloudFront Distrubtion supports. We recommend you put all of your public assets into one top level directory (i.e. public/static) so you don't reach this limit. See [CloudFront Quotas](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html) for more information.\n- If using `NextjsGlobalFunctions`, when [revalidating data in Next.js](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation) (i.e. [revalidatePath](https://nextjs.org/docs/app/api-reference/functions/revalidatePath)), the CloudFront Cache will still hold stale data. You'll need to use AWS SDK JS V3 [CreateInvalidationCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-cloudfront/Class/CreateInvalidationCommand/) to manually invalidate the path in CloudFront. See more [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html).\n- If using `NextjsGlobalFunctions`, setting an Authorization header won't work by default because of Lambda Function URL with IAM Auth is already using the Authorization header. You can use the `AWS_LWA_AUTHORIZATION_SOURCE` environment variable of [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter) to set an alternative Authorization header in the client which will then be set to the Authorization header when it reaches your app.\n\n## Additional Security Recommendations\n\nThis construct by default implements all AWS security best practices that a CDK construct library reasonably can considering cost and complexity. Below are additional security practices we recommend you implement within your CDK app. Please see them below:\n\n- [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html). See [examples/](./examples) for sample implementation.\n- [Scan ECR Images For Vulnerabilities](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html).\n- For `NextjsGlobalFunctions` and `NextjsGlobalContainers`, [CloudFront Access Logs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html). See [examples/](./examples) for sample implementation.\n- For `NextjsGlobalContainers` and `NextjsRegionalContainers`, [ALB HTTPS Listener](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html)\n\n## Estimated Costs\n\nWIP\n\n## Contributing\n\nSteps to build locally:\n\n1. `git clone https://github.com/cdklabs/cdk-nextjs.git`\n2. `cd cdk-nextjs`\n3. `pnpm i && pnpm compile && pnpm build`\n\nThis project uses Projen, so make sure to not edit [Projen](https://projen.io/) created files and only edit .projenrc.ts.\n\n## FAQ\n\nQ: How does this compare to [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs)?\nA: cdk-nextjs-standalone relies on [OpenNext](https://github.com/sst/open-next). OpenNext injects custom code to interact with private Next.js APIs. While OpenNext is able to make some optimizations that are great for serverless environments, this comes at an increase maintenance cost and increased chances for breaking changes. A goal of cdk-nextjs is to customize Next.js as little as possible to reduce the maintenance burden and decrease chances of breaking changes.\n\nQ: Why not offer API Gateway version of construct?\nA: API Gateway does not support streaming.\n\nQ: Why EFS instead of S3?\nA: Next.js has 3 types of server caching that are persisted to disk: [Data Cache](https://nextjs.org/docs/app/building-your-application/caching#data-cache), [Full Route Cache](https://nextjs.org/docs/app/building-your-application/caching#full-route-cache), and [Image Optimization](https://nextjs.org/docs/pages/building-your-application/optimizing/images). Cached data is persisted at .next/cache/fetch-cache, cached full routes are persisted at .next/server/app, and optimized images are persisted at .next/cache/images. Next.js provides a way to customize where cached data or cached full routes are persisted through the [Custom Next.js Cache Handler](https://nextjs.org/docs/app/api-reference/next-config-js/incrementalCacheHandlerPath), but there currently is no way to persist optimized images. Therefore, we need a way to persist cached data at the file system level which is transparent to Next.js. To do this, we use [Amazon Elastic File System (EFS)](https://aws.amazon.com/efs/). Benefits of EFS include being able to cache any Next.js data persisted to disk and therefore being flexible to adapt to Next.js as the framework evolves caching additional types of data. One exception to not using the Custom Next.js Cache Handler is to support [Data Cache Time-based Revalidation](https://nextjs.org/docs/app/building-your-application/caching#time-based-revalidation) when using AWS Lambda functions. Functions only run when they are responding to a request preventing time-based revalidation unlike containers with AWS Fargate which run continually. For functions, an [Amazon SQS Queue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) and consuming function that will make a HEAD request with x-prerender-revalidate header needed for Next.js to update cache.\n\nQ: How customizable is the `cdk-nextjs` package for different use cases?\nA: The `cdk-nextjs` package offers deep customization through _prop-based_ overrides. These can be accessed in the construct props, allowing you to override settings like VPC configurations, CloudFront distribution, and ECS/Fargate setup. For example, you can modify `nextjsBuildProps` to customize the build process or use `nextjsDistributionProps` to adjust how CloudFront handles caching and routing. This level of control makes it easy to adapt the infrastructure to your application’s specific performance, networking, or deployment needs.\n\nQ: How can I use a custom domain with `cdk-nextjs`?\nA: See [low-cost example](./examples/low-cost/app.ts).\n\nQ: What is difference between `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` and `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps`\nA: `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` allows you to customize any construct's props _within_ `NextjsDistribution` and is likely what you want whereas `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps` allows you to customize the props passed into the construct: `NextjsDistribution`. This principle also applies to other similarly named overrides.\n\n## Acknowledgements\n\nThis construct was built on the shoulders of giants. Thank you to the contributors of [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs) and [open-next](https://github.com/sst/open-next).\n\n## 🥂 Thanks Contributors\n\nThank you for helping other developers deploy Next.js apps on AWS\n\n<a href=\"https://github.com/cdklabs/cdk-nextjs/graphs/contributors\">\n <img src=\"https://contrib.rocks/image?repo=cdklabs/cdk-nextjs\" />\n</a>\n"
3961
+ "markdown": "![Version](https://img.shields.io/github/v/release/cdklabs/cdk-nextjs)\n[![npm version](https://img.shields.io/npm/v/cdk-nextjs.svg?style=flat-square)](https://www.npmjs.org/package/cdk-nextjs)\n![License](https://img.shields.io/github/license/cdklabs/cdk-nextjs)\n\n# CDK Next.js Construct Library\n\n<!--BEGIN STABILITY BANNER-->\n\n---\n\n![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge)\n\n> The APIs of higher level constructs in this module are experimental and under active development.\n> They are subject to non-backward compatible changes or removal in any future version. These are\n> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be\n> announced in the release notes. This means that while you may use them, you may need to update\n> your source code when upgrading to a newer version of this package.\n\n---\n\n<!--END STABILITY BANNER-->\n\nDeploy [Next.js](https://nextjs.org/) apps on [AWS](https://aws.amazon.com/) with the [AWS CDK](https://aws.amazon.com/cdk/).\n\n## Features\n\n- Supports all features of Next.js App and Pages Router for [Node.js Runtime](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes#nodejs-runtime)\n- Choose your AWS architecture for Next.js with the supported constructs: `NextjsGlobalFunctions`, `NextjsGlobalContainers`, `NextjsRegionalContainers`.\n- Global Content Delivery Network (CDN) built with [Amazon CloudFront](https://aws.amazon.com/cloudfront/) to deliver content with low latency and high transfer speeds.\n- Serverless functions powered by [AWS Lambda](https://aws.amazon.com/lambda/) or serverless containers powered by [AWS Fargate](https://aws.amazon.com/fargate/).\n- Static assets (JS, CSS, public folder) are stored and served from [Amazon Simple Storage Service (S3)](https://aws.amazon.com/s3/) for global constructs to decrease latency and reduce compute costs.\n- [Optimized images](https://nextjs.org/docs/pages/building-your-application/optimizing/images), [data cache](https://nextjs.org/docs/app/building-your-application/caching#data-cache), and [full route cache](https://nextjs.org/docs/app/building-your-application/caching#full-route-cache) are shared across compute with [Amazon Elastic File System (EFS)](https://aws.amazon.com/efs/).\n- Customize every construct via `overrides`.\n- WIP: When using AWS Lambda for compute, async revalidation is supported with [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/).\n- AWS security and operational best practices are utilized, guided by [cdk-nag](https://github.com/cdklabs/cdk-nag).\n- First class support for [monorepos](https://monorepo.tools/).\n- [AWS GovCloud (US)](https://aws.amazon.com/govcloud-us) compatible (with `NextjsRegionalContainers`).\n\n## Getting Started\n\n1. If you don’t have a Next.js project yet, follow [these steps](https://nextjs.org/docs/getting-started) to create one.\n1. Install [Docker](https://www.docker.com/). We recommend [Rancher Desktop](https://rancherdesktop.io/) with dockerd (moby) container engine enabled.\n1. Install [Node.js](https://nodejs.org/en). We recommend the long term support (LTS) version.\n1. Set your [next.config.js](https://nextjs.org/docs/pages/api-reference/next-config-js) [output](https://nextjs.org/docs/pages/api-reference/next-config-js/output) key to `\"standalone\"`. Learn more here about [Standalone Output](https://nextjs.org/docs/pages/api-reference/next-config-js/output#automatically-copying-traced-files).\n1. Setup [AWS Cloud Development Kit](https://docs.aws.amazon.com/cdk/v2/guide/home.html) app.\n1. Install the construct package: `npm install cdk-nextjs`\n1. `cdk deploy`\n1. Visit URL printed in terminal (CloudFormation Output) to view your Next.js app!\n\n## Basic Example CDK App\n\n```ts\nimport { App, Stack, StackProps } from \"aws-cdk-lib\";\nimport { Construct } from \"constructs\";\nimport { fileURLToPath } from \"node:url\";\nimport { NextjsGlobalFunctions } from \"cdk-nextjs\";\n\nclass NextjsStack extends Stack {\n constructor(scope: Construct, id: string, props: StackProps = {}) {\n super(scope, id, props);\n new NextjsGlobalFunctions(this, \"Nextjs\", {\n healthCheckPath: \"/api/health\",\n buildContext: fileURLToPath(new URL(\"..\", import.meta.url)),\n });\n }\n}\n\nconst app = new App();\n\nnew NextjsStack(app, \"nextjs\");\n```\n\nSee [examples/](./examples/) for more usage examples.\n\n## Architecture\n\n### `NextjsGlobalFunctions`\n\nArchitecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this construct when you have unpredictable traffic, can afford occasional latency (i.e. cold starts - [typically 1% of production traffic](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/)), and/or want the most granular pricing model. ([code](./src/root-constructs/nextjs-global-functions.ts#L81))\n\n![NextjsGlobalFunctions](./docs/cdk-nextjs-NextjsGlobalFunctions.png)\n\n### `NextjsGlobalContainers`\n\nArchitecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this option when you have predictable traffic, need the lowest latency, and/or can afford a less granular pricing model. ([code](./src/root-constructs/nextjs-global-containers.ts#L76))\n\n![NextjsGlobalContainers](./docs/cdk-nextjs-NextjsGlobalContainers.png)\n\n### `NextjsRegionalContainers`\n\nArchitecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) to regionally serve requests. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-containers.ts#L41))\n\n![NextjsRegionalContainers](./docs/cdk-nextjs-NextjsRegionalContainers.png)\n\n## Why\n\nThe simplest path to deploy Next.js is on [Vercel](https://vercel.com/) - the Platform-as-a-Service company behind Next.js. However, deploying to Vercel can be expensive and some developers want all of their workloads running _directly_ on AWS. Developers can deploy Next.js on AWS through [AWS Amplify Hosting](https://docs.aws.amazon.com/amplify/latest/userguide/ssr-Amplifysupport.html), but Amplify does not support all Next.js features and manages AWS resources for you so they cannot be customized. If Amplify meets your requirements we recommend you use it, but if you want to use all Next.js features or want more visibility into the AWS resources then this construct is for you.\n\n## Design Principles\n\n- Treat Next.js as black box. Minimize reliance on Next.js internal APIs to reduce chance of incompatibility between this construct and future versions of Next.js.\n- Security first.\n- One architecture does not fit all.\n- Enable customization everywhere.\n\n## Limitations\n\n- If using `NextjsGlobalFunctions` or `NextjsGlobalContainers` (which use CloudFront), the number of top level files/directories cannot exceed 25, the max number of behaviors a CloudFront Distrubtion supports. We recommend you put all of your public assets into one top level directory (i.e. public/static) so you don't reach this limit. See [CloudFront Quotas](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html) for more information.\n- If using `NextjsGlobalFunctions`, when [revalidating data in Next.js](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation) (i.e. [revalidatePath](https://nextjs.org/docs/app/api-reference/functions/revalidatePath)), the CloudFront Cache will still hold stale data. You'll need to use AWS SDK JS V3 [CreateInvalidationCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-cloudfront/Class/CreateInvalidationCommand/) to manually invalidate the path in CloudFront. See more [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html).\n- If using `NextjsGlobalFunctions`, setting an Authorization header won't work by default because of Lambda Function URL with IAM Auth is already using the Authorization header. You can use the `AWS_LWA_AUTHORIZATION_SOURCE` environment variable of [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter) to set an alternative Authorization header in the client which will then be set to the Authorization header when it reaches your app.\n\n## Additional Security Recommendations\n\nThis construct by default implements all AWS security best practices that a CDK construct library reasonably can considering cost and complexity. Below are additional security practices we recommend you implement within your CDK app. Please see them below:\n\n- [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html). See [examples/](./examples) for sample implementation.\n- [Scan ECR Images For Vulnerabilities](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html).\n- For `NextjsGlobalFunctions` and `NextjsGlobalContainers`, [CloudFront Access Logs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html). See [examples/](./examples) for sample implementation.\n- For `NextjsGlobalContainers` and `NextjsRegionalContainers`, [ALB HTTPS Listener](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html)\n- If using `NextjsGlobalContainers`, enable `ReadonlyRootFilesystem`. This will remove ability to use Static On-Demand feature of Next.js so it's not enabled by default, but is recommended for security.\n\n## Estimated Costs\n\nWIP\n\n## Contributing\n\nSteps to build locally:\n\n1. `git clone https://github.com/cdklabs/cdk-nextjs.git`\n2. `cd cdk-nextjs`\n3. `pnpm i && pnpm compile && pnpm build`\n\nThis project uses Projen, so make sure to not edit [Projen](https://projen.io/) created files and only edit .projenrc.ts.\n\n## FAQ\n\nQ: How does this compare to [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs)?<br/>\nA: cdk-nextjs-standalone relies on [OpenNext](https://github.com/sst/open-next). OpenNext injects custom code to interact with private Next.js APIs. While OpenNext is able to make some optimizations that are great for serverless environments, this comes at an increase maintenance cost and increased chances for breaking changes. A goal of cdk-nextjs is to customize Next.js as little as possible to reduce the maintenance burden and decrease chances of breaking changes.\n\nQ: Why not offer API Gateway version of construct?<br/>\nA: API Gateway does not support streaming.\n\nQ: Why EFS instead of S3?<br/>\nA: Next.js has 3 types of server caching that are persisted to disk: [Data Cache](https://nextjs.org/docs/app/building-your-application/caching#data-cache), [Full Route Cache](https://nextjs.org/docs/app/building-your-application/caching#full-route-cache), and [Image Optimization](https://nextjs.org/docs/pages/building-your-application/optimizing/images). Cached data is persisted at .next/cache/fetch-cache, cached full routes are persisted at .next/server/app, and optimized images are persisted at .next/cache/images. Next.js provides a way to customize where cached data or cached full routes are persisted through the [Custom Next.js Cache Handler](https://nextjs.org/docs/app/api-reference/next-config-js/incrementalCacheHandlerPath), but there currently is no way to persist optimized images. Therefore, we need a way to persist cached data at the file system level which is transparent to Next.js. To do this, we use [Amazon Elastic File System (EFS)](https://aws.amazon.com/efs/). Benefits of EFS include being able to cache any Next.js data persisted to disk and therefore being flexible to adapt to Next.js as the framework evolves caching additional types of data. One exception to not using the Custom Next.js Cache Handler is to support [Data Cache Time-based Revalidation](https://nextjs.org/docs/app/building-your-application/caching#time-based-revalidation) when using AWS Lambda functions. Functions only run when they are responding to a request preventing time-based revalidation unlike containers with AWS Fargate which run continually. For functions, an [Amazon SQS Queue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) and consuming function that will make a HEAD request with x-prerender-revalidate header needed for Next.js to update cache.\n\nQ: How customizable is the `cdk-nextjs` package for different use cases?<br/>\nA: The `cdk-nextjs` package offers deep customization through _prop-based_ overrides. These can be accessed in the construct props, allowing you to override settings like VPC configurations, CloudFront distribution, and ECS/Fargate setup. For example, you can modify `nextjsBuildProps` to customize the build process or use `nextjsDistributionProps` to adjust how CloudFront handles caching and routing. This level of control makes it easy to adapt the infrastructure to your application’s specific performance, networking, or deployment needs.\n\nQ: How can I use a custom domain with `cdk-nextjs`?<br/>\nA: See [low-cost example](./examples/low-cost/app.ts).\n\nQ: What is difference between `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` and `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps`<br/>\nA: `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` allows you to customize any construct's props _within_ `NextjsDistribution` and is likely what you want whereas `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps` allows you to customize the props passed into the construct: `NextjsDistribution`. This principle also applies to other similarly named overrides.\n\nQ: Why use container image for `NextjsGlobalFunctions`?<br />\nA: Read [The case for containers on Lambda (with benchmarks)](https://aaronstuyvenberg.com/posts/containers-on-lambda).\n\n## Acknowledgements\n\nThis construct was built on the shoulders of giants. Thank you to the contributors of [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs) and [open-next](https://github.com/sst/open-next).\n\n## 🥂 Thanks Contributors\n\nThank you for helping other developers deploy Next.js apps on AWS\n\n<a href=\"https://github.com/cdklabs/cdk-nextjs/graphs/contributors\">\n <img src=\"https://contrib.rocks/image?repo=cdklabs/cdk-nextjs\" />\n</a>\n"
3962
3962
  },
3963
3963
  "repository": {
3964
3964
  "type": "git",
@@ -5169,7 +5169,7 @@
5169
5169
  },
5170
5170
  "locationInModule": {
5171
5171
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5172
- "line": 50
5172
+ "line": 49
5173
5173
  },
5174
5174
  "parameters": [
5175
5175
  {
@@ -5195,7 +5195,7 @@
5195
5195
  "kind": "class",
5196
5196
  "locationInModule": {
5197
5197
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5198
- "line": 43
5198
+ "line": 42
5199
5199
  },
5200
5200
  "name": "NextjsContainers",
5201
5201
  "properties": [
@@ -5205,7 +5205,7 @@
5205
5205
  },
5206
5206
  "locationInModule": {
5207
5207
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5208
- "line": 44
5208
+ "line": 43
5209
5209
  },
5210
5210
  "name": "albFargateService",
5211
5211
  "type": {
@@ -5218,7 +5218,7 @@
5218
5218
  },
5219
5219
  "locationInModule": {
5220
5220
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5221
- "line": 45
5221
+ "line": 44
5222
5222
  },
5223
5223
  "name": "ecsCluster",
5224
5224
  "type": {
@@ -5231,7 +5231,7 @@
5231
5231
  },
5232
5232
  "locationInModule": {
5233
5233
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5234
- "line": 46
5234
+ "line": 45
5235
5235
  },
5236
5236
  "name": "url",
5237
5237
  "type": {
@@ -5251,7 +5251,7 @@
5251
5251
  "kind": "interface",
5252
5252
  "locationInModule": {
5253
5253
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5254
- "line": 25
5254
+ "line": 24
5255
5255
  },
5256
5256
  "name": "NextjsContainersOverrides",
5257
5257
  "properties": [
@@ -5263,7 +5263,7 @@
5263
5263
  "immutable": true,
5264
5264
  "locationInModule": {
5265
5265
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5266
- "line": 27
5266
+ "line": 26
5267
5267
  },
5268
5268
  "name": "albFargateServiceProps",
5269
5269
  "optional": true,
@@ -5279,7 +5279,7 @@
5279
5279
  "immutable": true,
5280
5280
  "locationInModule": {
5281
5281
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5282
- "line": 26
5282
+ "line": 25
5283
5283
  },
5284
5284
  "name": "ecsClusterProps",
5285
5285
  "optional": true,
@@ -5295,7 +5295,7 @@
5295
5295
  "immutable": true,
5296
5296
  "locationInModule": {
5297
5297
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5298
- "line": 28
5298
+ "line": 27
5299
5299
  },
5300
5300
  "name": "taskImageOptions",
5301
5301
  "optional": true,
@@ -5319,7 +5319,7 @@
5319
5319
  "kind": "interface",
5320
5320
  "locationInModule": {
5321
5321
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5322
- "line": 31
5322
+ "line": 30
5323
5323
  },
5324
5324
  "name": "NextjsContainersProps",
5325
5325
  "properties": [
@@ -5331,7 +5331,7 @@
5331
5331
  "immutable": true,
5332
5332
  "locationInModule": {
5333
5333
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5334
- "line": 32
5334
+ "line": 31
5335
5335
  },
5336
5336
  "name": "dockerImageAsset",
5337
5337
  "type": {
@@ -5346,7 +5346,7 @@
5346
5346
  "immutable": true,
5347
5347
  "locationInModule": {
5348
5348
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5349
- "line": 33
5349
+ "line": 32
5350
5350
  },
5351
5351
  "name": "fileSystem",
5352
5352
  "type": {
@@ -5361,7 +5361,7 @@
5361
5361
  "immutable": true,
5362
5362
  "locationInModule": {
5363
5363
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5364
- "line": 34
5364
+ "line": 33
5365
5365
  },
5366
5366
  "name": "nextjsType",
5367
5367
  "type": {
@@ -5376,7 +5376,7 @@
5376
5376
  "immutable": true,
5377
5377
  "locationInModule": {
5378
5378
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5379
- "line": 36
5379
+ "line": 35
5380
5380
  },
5381
5381
  "name": "relativeEntrypointPath",
5382
5382
  "type": {
@@ -5391,7 +5391,7 @@
5391
5391
  "immutable": true,
5392
5392
  "locationInModule": {
5393
5393
  "filename": "src/nextjs-compute/nextjs-containers.ts",
5394
- "line": 35
5394
+ "line": 34
5395
5395
  },
5396
5396
  "name": "overrides",
5397
5397
  "optional": true,
@@ -5547,12 +5547,12 @@
5547
5547
  "immutable": true,
5548
5548
  "locationInModule": {
5549
5549
  "filename": "src/nextjs-distribution.ts",
5550
- "line": 56
5550
+ "line": 54
5551
5551
  },
5552
- "name": "dynamicLoadBalancerV2OriginProps",
5552
+ "name": "dynamicResponseHeadersPolicyProps",
5553
5553
  "optional": true,
5554
5554
  "type": {
5555
- "fqn": "aws-cdk-lib.aws_cloudfront_origins.LoadBalancerV2OriginProps"
5555
+ "fqn": "aws-cdk-lib.aws_cloudfront.ResponseHeadersPolicyProps"
5556
5556
  }
5557
5557
  },
5558
5558
  {
@@ -5563,12 +5563,12 @@
5563
5563
  "immutable": true,
5564
5564
  "locationInModule": {
5565
5565
  "filename": "src/nextjs-distribution.ts",
5566
- "line": 54
5566
+ "line": 56
5567
5567
  },
5568
- "name": "dynamicResponseHeadersPolicyProps",
5568
+ "name": "dynamicVpcOriginWithEndpointProps",
5569
5569
  "optional": true,
5570
5570
  "type": {
5571
- "fqn": "aws-cdk-lib.aws_cloudfront.ResponseHeadersPolicyProps"
5571
+ "fqn": "aws-cdk-lib.aws_cloudfront_origins.VpcOriginWithEndpointProps"
5572
5572
  }
5573
5573
  },
5574
5574
  {
@@ -5817,7 +5817,7 @@
5817
5817
  "name": "loadBalancer",
5818
5818
  "optional": true,
5819
5819
  "type": {
5820
- "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ILoadBalancerV2"
5820
+ "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer"
5821
5821
  }
5822
5822
  },
5823
5823
  {
@@ -7828,7 +7828,10 @@
7828
7828
  "assembly": "cdk-nextjs",
7829
7829
  "base": "constructs.Construct",
7830
7830
  "docs": {
7831
- "stability": "stable"
7831
+ "remarks": "Note, if you use `NextjsVpc` then the default CDK VPC will be created\nfor you with 2 AZs of all 3 types of subnets with a NAT Gateway in your\n`SubnetType.PUBLIC` subnet to allow for secure internet access from your\n`SubnetType.PRIVATE_WITH_EGRESS` subnet. This is recommended by AWS, but\nit costs $65/month for 2 AZs. See examples/low-cost for alternative.",
7832
+ "see": "https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#subnet-types",
7833
+ "stability": "stable",
7834
+ "summary": "cdk-nextjs requires a VPC because of the use of EFS but if you're building on AWS you probably already need one for other resources (i.e. RDS/Aurora). You can provide your own VPC via `overrides.nextjsVpc.vpc` but you'll be responsible for creating the VPC. All cdk-nextjs constructs require a `SubnetType.PRIVATE_ISOLATED` subnet for EFS and `SubnetType.PRIVATE_WITH_EGRESS` for compute. `NextjsRegionalContainers` requires a `SubnetType.PUBLIC` subnet for CloudFront to reach the ALB. `NextjsGlobalFunctions` and `NextjsGlobalContainers` don't require a `SubnetType.PUBLIC` subnet because CloudFront accesses their compute securely through Function URL and VPC Origin Access."
7832
7835
  },
7833
7836
  "fqn": "cdk-nextjs.NextjsVpc",
7834
7837
  "initializer": {
@@ -7837,7 +7840,7 @@
7837
7840
  },
7838
7841
  "locationInModule": {
7839
7842
  "filename": "src/nextjs-vpc.ts",
7840
- "line": 32
7843
+ "line": 52
7841
7844
  },
7842
7845
  "parameters": [
7843
7846
  {
@@ -7863,7 +7866,7 @@
7863
7866
  "kind": "class",
7864
7867
  "locationInModule": {
7865
7868
  "filename": "src/nextjs-vpc.ts",
7866
- "line": 27
7869
+ "line": 47
7867
7870
  },
7868
7871
  "name": "NextjsVpc",
7869
7872
  "properties": [
@@ -7873,7 +7876,7 @@
7873
7876
  },
7874
7877
  "locationInModule": {
7875
7878
  "filename": "src/nextjs-vpc.ts",
7876
- "line": 28
7879
+ "line": 48
7877
7880
  },
7878
7881
  "name": "vpc",
7879
7882
  "type": {
@@ -12960,7 +12963,7 @@
12960
12963
  "name": "loadBalancer",
12961
12964
  "optional": true,
12962
12965
  "type": {
12963
- "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ILoadBalancerV2"
12966
+ "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer"
12964
12967
  }
12965
12968
  },
12966
12969
  {
@@ -13861,6 +13864,6 @@
13861
13864
  "symbolId": "src/nextjs-build/nextjs-build:PublicDirEntry"
13862
13865
  }
13863
13866
  },
13864
- "version": "0.2.7",
13865
- "fingerprint": "3gw5cIGGqj+6DoX7Nu/KAXaT/dwdPcU89pXcdZos070="
13867
+ "version": "0.3.1",
13868
+ "fingerprint": "H8T5zcnqOXrojpKPy2qS3qPIRjA9+Bblr64DcM9VQNg="
13866
13869
  }
package/API.md CHANGED
@@ -1742,6 +1742,16 @@ public readonly bucket: Bucket;
1742
1742
 
1743
1743
  ### NextjsVpc <a name="NextjsVpc" id="cdk-nextjs.NextjsVpc"></a>
1744
1744
 
1745
+ cdk-nextjs requires a VPC because of the use of EFS but if you're building on AWS you probably already need one for other resources (i.e. RDS/Aurora). You can provide your own VPC via `overrides.nextjsVpc.vpc` but you'll be responsible for creating the VPC. All cdk-nextjs constructs require a `SubnetType.PRIVATE_ISOLATED` subnet for EFS and `SubnetType.PRIVATE_WITH_EGRESS` for compute. `NextjsRegionalContainers` requires a `SubnetType.PUBLIC` subnet for CloudFront to reach the ALB. `NextjsGlobalFunctions` and `NextjsGlobalContainers` don't require a `SubnetType.PUBLIC` subnet because CloudFront accesses their compute securely through Function URL and VPC Origin Access.
1746
+
1747
+ Note, if you use `NextjsVpc` then the default CDK VPC will be created
1748
+ for you with 2 AZs of all 3 types of subnets with a NAT Gateway in your
1749
+ `SubnetType.PUBLIC` subnet to allow for secure internet access from your
1750
+ `SubnetType.PRIVATE_WITH_EGRESS` subnet. This is recommended by AWS, but
1751
+ it costs $65/month for 2 AZs. See examples/low-cost for alternative.
1752
+
1753
+ > [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#subnet-types](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#subnet-types)
1754
+
1745
1755
  #### Initializers <a name="Initializers" id="cdk-nextjs.NextjsVpc.Initializer"></a>
1746
1756
 
1747
1757
  ```typescript
@@ -2818,8 +2828,8 @@ const nextjsDistributionOverrides: NextjsDistributionOverrides = { ... }
2818
2828
  | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.dynamicBehaviorOptions">dynamicBehaviorOptions</a></code> | <code>aws-cdk-lib.aws_cloudfront.AddBehaviorOptions</code> | *No description.* |
2819
2829
  | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.dynamicCachePolicyProps">dynamicCachePolicyProps</a></code> | <code>aws-cdk-lib.aws_cloudfront.CachePolicyProps</code> | *No description.* |
2820
2830
  | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.dynamicFunctionUrlOriginWithOACProps">dynamicFunctionUrlOriginWithOACProps</a></code> | <code>aws-cdk-lib.aws_cloudfront_origins.FunctionUrlOriginWithOACProps</code> | *No description.* |
2821
- | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.dynamicLoadBalancerV2OriginProps">dynamicLoadBalancerV2OriginProps</a></code> | <code>aws-cdk-lib.aws_cloudfront_origins.LoadBalancerV2OriginProps</code> | *No description.* |
2822
2831
  | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.dynamicResponseHeadersPolicyProps">dynamicResponseHeadersPolicyProps</a></code> | <code>aws-cdk-lib.aws_cloudfront.ResponseHeadersPolicyProps</code> | *No description.* |
2832
+ | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.dynamicVpcOriginWithEndpointProps">dynamicVpcOriginWithEndpointProps</a></code> | <code>aws-cdk-lib.aws_cloudfront_origins.VpcOriginWithEndpointProps</code> | *No description.* |
2823
2833
  | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.imageBehaviorOptions">imageBehaviorOptions</a></code> | <code>aws-cdk-lib.aws_cloudfront.AddBehaviorOptions</code> | *No description.* |
2824
2834
  | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.imageCachePolicyProps">imageCachePolicyProps</a></code> | <code>aws-cdk-lib.aws_cloudfront.CachePolicyProps</code> | *No description.* |
2825
2835
  | <code><a href="#cdk-nextjs.NextjsDistributionOverrides.property.imageResponseHeadersPolicyProps">imageResponseHeadersPolicyProps</a></code> | <code>aws-cdk-lib.aws_cloudfront.ResponseHeadersPolicyProps</code> | *No description.* |
@@ -2869,23 +2879,23 @@ public readonly dynamicFunctionUrlOriginWithOACProps: FunctionUrlOriginWithOACPr
2869
2879
 
2870
2880
  ---
2871
2881
 
2872
- ##### `dynamicLoadBalancerV2OriginProps`<sup>Optional</sup> <a name="dynamicLoadBalancerV2OriginProps" id="cdk-nextjs.NextjsDistributionOverrides.property.dynamicLoadBalancerV2OriginProps"></a>
2882
+ ##### `dynamicResponseHeadersPolicyProps`<sup>Optional</sup> <a name="dynamicResponseHeadersPolicyProps" id="cdk-nextjs.NextjsDistributionOverrides.property.dynamicResponseHeadersPolicyProps"></a>
2873
2883
 
2874
2884
  ```typescript
2875
- public readonly dynamicLoadBalancerV2OriginProps: LoadBalancerV2OriginProps;
2885
+ public readonly dynamicResponseHeadersPolicyProps: ResponseHeadersPolicyProps;
2876
2886
  ```
2877
2887
 
2878
- - *Type:* aws-cdk-lib.aws_cloudfront_origins.LoadBalancerV2OriginProps
2888
+ - *Type:* aws-cdk-lib.aws_cloudfront.ResponseHeadersPolicyProps
2879
2889
 
2880
2890
  ---
2881
2891
 
2882
- ##### `dynamicResponseHeadersPolicyProps`<sup>Optional</sup> <a name="dynamicResponseHeadersPolicyProps" id="cdk-nextjs.NextjsDistributionOverrides.property.dynamicResponseHeadersPolicyProps"></a>
2892
+ ##### `dynamicVpcOriginWithEndpointProps`<sup>Optional</sup> <a name="dynamicVpcOriginWithEndpointProps" id="cdk-nextjs.NextjsDistributionOverrides.property.dynamicVpcOriginWithEndpointProps"></a>
2883
2893
 
2884
2894
  ```typescript
2885
- public readonly dynamicResponseHeadersPolicyProps: ResponseHeadersPolicyProps;
2895
+ public readonly dynamicVpcOriginWithEndpointProps: VpcOriginWithEndpointProps;
2886
2896
  ```
2887
2897
 
2888
- - *Type:* aws-cdk-lib.aws_cloudfront.ResponseHeadersPolicyProps
2898
+ - *Type:* aws-cdk-lib.aws_cloudfront_origins.VpcOriginWithEndpointProps
2889
2899
 
2890
2900
  ---
2891
2901
 
@@ -2970,7 +2980,7 @@ const nextjsDistributionProps: NextjsDistributionProps = { ... }
2970
2980
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.certificate">certificate</a></code> | <code>aws-cdk-lib.aws_certificatemanager.ICertificate</code> | Optional but only applicable for `NextjsType.GLOBAL_CONTAINERS`. |
2971
2981
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.distribution">distribution</a></code> | <code>aws-cdk-lib.aws_cloudfront.Distribution</code> | *No description.* |
2972
2982
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.functionUrl">functionUrl</a></code> | <code>aws-cdk-lib.aws_lambda.IFunctionUrl</code> | Required if `NextjsType.GLOBAL_FUNCTIONS`. |
2973
- | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.loadBalancer">loadBalancer</a></code> | <code>aws-cdk-lib.aws_elasticloadbalancingv2.ILoadBalancerV2</code> | Required if `NextjsType.GLOBAL_CONTAINERS` or `NextjsType.REGIONAL_CONTAINERS`. |
2983
+ | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.loadBalancer">loadBalancer</a></code> | <code>aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer</code> | Required if `NextjsType.GLOBAL_CONTAINERS` or `NextjsType.REGIONAL_CONTAINERS`. |
2974
2984
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.overrides">overrides</a></code> | <code><a href="#cdk-nextjs.NextjsDistributionOverrides">NextjsDistributionOverrides</a></code> | Override props for every construct. |
2975
2985
 
2976
2986
  ---
@@ -3058,10 +3068,10 @@ Required if `NextjsType.GLOBAL_FUNCTIONS`.
3058
3068
  ##### `loadBalancer`<sup>Optional</sup> <a name="loadBalancer" id="cdk-nextjs.NextjsDistributionProps.property.loadBalancer"></a>
3059
3069
 
3060
3070
  ```typescript
3061
- public readonly loadBalancer: ILoadBalancerV2;
3071
+ public readonly loadBalancer: ApplicationLoadBalancer;
3062
3072
  ```
3063
3073
 
3064
- - *Type:* aws-cdk-lib.aws_elasticloadbalancingv2.ILoadBalancerV2
3074
+ - *Type:* aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer
3065
3075
 
3066
3076
  Required if `NextjsType.GLOBAL_CONTAINERS` or `NextjsType.REGIONAL_CONTAINERS`.
3067
3077
 
@@ -8814,7 +8824,7 @@ const optionalNextjsDistributionProps: OptionalNextjsDistributionProps = { ... }
8814
8824
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.certificate">certificate</a></code> | <code>aws-cdk-lib.aws_certificatemanager.ICertificate</code> | Optional but only applicable for `NextjsType.GLOBAL_CONTAINERS`. |
8815
8825
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.distribution">distribution</a></code> | <code>aws-cdk-lib.aws_cloudfront.Distribution</code> | *No description.* |
8816
8826
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.functionUrl">functionUrl</a></code> | <code>aws-cdk-lib.aws_lambda.IFunctionUrl</code> | Required if `NextjsType.GLOBAL_FUNCTIONS`. |
8817
- | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.loadBalancer">loadBalancer</a></code> | <code>aws-cdk-lib.aws_elasticloadbalancingv2.ILoadBalancerV2</code> | Required if `NextjsType.GLOBAL_CONTAINERS` or `NextjsType.REGIONAL_CONTAINERS`. |
8827
+ | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.loadBalancer">loadBalancer</a></code> | <code>aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer</code> | Required if `NextjsType.GLOBAL_CONTAINERS` or `NextjsType.REGIONAL_CONTAINERS`. |
8818
8828
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.nextjsType">nextjsType</a></code> | <code><a href="#cdk-nextjs.NextjsType">NextjsType</a></code> | *No description.* |
8819
8829
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.publicDirEntries">publicDirEntries</a></code> | <code><a href="#cdk-nextjs.PublicDirEntry">PublicDirEntry</a>[]</code> | Path to directory of Next.js app's public directory. Used to add static behaviors to distribution. |
8820
8830
 
@@ -8881,10 +8891,10 @@ Required if `NextjsType.GLOBAL_FUNCTIONS`.
8881
8891
  ##### `loadBalancer`<sup>Optional</sup> <a name="loadBalancer" id="cdk-nextjs.OptionalNextjsDistributionProps.property.loadBalancer"></a>
8882
8892
 
8883
8893
  ```typescript
8884
- public readonly loadBalancer: ILoadBalancerV2;
8894
+ public readonly loadBalancer: ApplicationLoadBalancer;
8885
8895
  ```
8886
8896
 
8887
- - *Type:* aws-cdk-lib.aws_elasticloadbalancingv2.ILoadBalancerV2
8897
+ - *Type:* aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer
8888
8898
 
8889
8899
  Required if `NextjsType.GLOBAL_CONTAINERS` or `NextjsType.REGIONAL_CONTAINERS`.
8890
8900
 
package/README.md CHANGED
@@ -117,6 +117,7 @@ This construct by default implements all AWS security best practices that a CDK
117
117
  - [Scan ECR Images For Vulnerabilities](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html).
118
118
  - For `NextjsGlobalFunctions` and `NextjsGlobalContainers`, [CloudFront Access Logs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html). See [examples/](./examples) for sample implementation.
119
119
  - For `NextjsGlobalContainers` and `NextjsRegionalContainers`, [ALB HTTPS Listener](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html)
120
+ - If using `NextjsGlobalContainers`, enable `ReadonlyRootFilesystem`. This will remove ability to use Static On-Demand feature of Next.js so it's not enabled by default, but is recommended for security.
120
121
 
121
122
  ## Estimated Costs
122
123
 
@@ -134,24 +135,27 @@ This project uses Projen, so make sure to not edit [Projen](https://projen.io/)
134
135
 
135
136
  ## FAQ
136
137
 
137
- Q: How does this compare to [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs)?
138
+ Q: How does this compare to [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs)?<br/>
138
139
  A: cdk-nextjs-standalone relies on [OpenNext](https://github.com/sst/open-next). OpenNext injects custom code to interact with private Next.js APIs. While OpenNext is able to make some optimizations that are great for serverless environments, this comes at an increase maintenance cost and increased chances for breaking changes. A goal of cdk-nextjs is to customize Next.js as little as possible to reduce the maintenance burden and decrease chances of breaking changes.
139
140
 
140
- Q: Why not offer API Gateway version of construct?
141
+ Q: Why not offer API Gateway version of construct?<br/>
141
142
  A: API Gateway does not support streaming.
142
143
 
143
- Q: Why EFS instead of S3?
144
+ Q: Why EFS instead of S3?<br/>
144
145
  A: Next.js has 3 types of server caching that are persisted to disk: [Data Cache](https://nextjs.org/docs/app/building-your-application/caching#data-cache), [Full Route Cache](https://nextjs.org/docs/app/building-your-application/caching#full-route-cache), and [Image Optimization](https://nextjs.org/docs/pages/building-your-application/optimizing/images). Cached data is persisted at .next/cache/fetch-cache, cached full routes are persisted at .next/server/app, and optimized images are persisted at .next/cache/images. Next.js provides a way to customize where cached data or cached full routes are persisted through the [Custom Next.js Cache Handler](https://nextjs.org/docs/app/api-reference/next-config-js/incrementalCacheHandlerPath), but there currently is no way to persist optimized images. Therefore, we need a way to persist cached data at the file system level which is transparent to Next.js. To do this, we use [Amazon Elastic File System (EFS)](https://aws.amazon.com/efs/). Benefits of EFS include being able to cache any Next.js data persisted to disk and therefore being flexible to adapt to Next.js as the framework evolves caching additional types of data. One exception to not using the Custom Next.js Cache Handler is to support [Data Cache Time-based Revalidation](https://nextjs.org/docs/app/building-your-application/caching#time-based-revalidation) when using AWS Lambda functions. Functions only run when they are responding to a request preventing time-based revalidation unlike containers with AWS Fargate which run continually. For functions, an [Amazon SQS Queue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) and consuming function that will make a HEAD request with x-prerender-revalidate header needed for Next.js to update cache.
145
146
 
146
- Q: How customizable is the `cdk-nextjs` package for different use cases?
147
+ Q: How customizable is the `cdk-nextjs` package for different use cases?<br/>
147
148
  A: The `cdk-nextjs` package offers deep customization through _prop-based_ overrides. These can be accessed in the construct props, allowing you to override settings like VPC configurations, CloudFront distribution, and ECS/Fargate setup. For example, you can modify `nextjsBuildProps` to customize the build process or use `nextjsDistributionProps` to adjust how CloudFront handles caching and routing. This level of control makes it easy to adapt the infrastructure to your application’s specific performance, networking, or deployment needs.
148
149
 
149
- Q: How can I use a custom domain with `cdk-nextjs`?
150
+ Q: How can I use a custom domain with `cdk-nextjs`?<br/>
150
151
  A: See [low-cost example](./examples/low-cost/app.ts).
151
152
 
152
- Q: What is difference between `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` and `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps`
153
+ Q: What is difference between `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` and `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps`<br/>
153
154
  A: `NextjsGlobalFunctionsProps.overrides.nextjsDistribution` allows you to customize any construct's props _within_ `NextjsDistribution` and is likely what you want whereas `NextjsGlobalFunctionsProps.overrides.nextjsGlobalFunctions.nextjsDistributionProps` allows you to customize the props passed into the construct: `NextjsDistribution`. This principle also applies to other similarly named overrides.
154
155
 
156
+ Q: Why use container image for `NextjsGlobalFunctions`?<br />
157
+ A: Read [The case for containers on Lambda (with benchmarks)](https://aaronstuyvenberg.com/posts/containers-on-lambda).
158
+
155
159
  ## Acknowledgements
156
160
 
157
161
  This construct was built on the shoulders of giants. Thank you to the contributors of [cdk-nextjs-standalone](https://github.com/jetbridge/cdk-nextjs) and [open-next](https://github.com/sst/open-next).
@@ -8739,7 +8739,7 @@ async function fsToS3(props, nextjsType) {
8739
8739
  const mainAppFileContent = (0, import_node_fs3.readFileSync)(path);
8740
8740
  const patchFetchContent = (0, import_node_fs3.readFileSync)(
8741
8741
  (0, import_node_path2.join)(__dirname, "patch-fetch.js")
8742
- );
8742
+ ).toString().replace('"use strict";', "");
8743
8743
  body = patchFetchContent + "\n" + mainAppFileContent;
8744
8744
  } else {
8745
8745
  body = (0, import_node_fs3.createReadStream)(path);
@@ -1,5 +1,11 @@
1
1
  # Breaking Changes
2
2
 
3
+ ## 0.3.0
4
+
5
+ - Change `NextjsDistributionProps.loadBalancer` type from `ILoadBalancerV2` to `ApplicationLoadBalancer`
6
+ - Remove `NextjsDistributionOverrides.dynamicLoadBalancerV2OriginProps` (replaced with `NextjsDistributionOverrides.dynamicVpcOriginWithEndpointProps`)
7
+ - `NextjsGlobalContainers` will now deploy ALB in PrivateWithEgress subnet. Previously these ALBs were created in Public subnet but with more secure CloudFront VPC Origin Access now available in CDK we can put ALB in PrivateWithEgressSubnet. This change requires replacement of the AWS::ElasticLoadBalancingV2::LoadBalancer. Because the target groups are not directly linked to the load balancer (so they're not replaced too), you'll get the error: `The following target groups cannot be associated with more than one load balancer`. To work around this issue, please see AWS re:Post solution: [Error: TargetGroup cannot be associated with more than one load balancer](https://repost.aws/questions/QUY2sMSJyDTL-vNbR4Agm0Yw/error-targetgroup-cannot-be-associated-with-more-than-one-load-balancer) for workaround. Alternatively, you can simply destroy and re-deploy the stack.
8
+
3
9
  ## 0.2.0
4
10
 
5
11
  - Removed Lambda@Edge Function from `NextjsGlobalFunctions`