From 59473c5c4ce21523061c47b9acbeec29b244b30f Mon Sep 17 00:00:00 2001 From: magnus Date: Sun, 9 Jun 2024 18:55:28 +0200 Subject: [PATCH] docs: remove v3 folder and add general requirements into main components overview --- .../inner_workings/components/overview.mdx | 50 +- docs/pages/v3/_meta.json | 7 - docs/pages/v3/config.mdx | 69 --- docs/pages/v3/index.mdx | 67 --- docs/pages/v3/override.mdx | 74 --- docs/pages/v3/reference-implementation.mdx | 435 ------------------ docs/pages/v3/requirements.mdx | 59 --- 7 files changed, 30 insertions(+), 731 deletions(-) delete mode 100644 docs/pages/v3/_meta.json delete mode 100644 docs/pages/v3/config.mdx delete mode 100644 docs/pages/v3/index.mdx delete mode 100644 docs/pages/v3/override.mdx delete mode 100644 docs/pages/v3/reference-implementation.mdx delete mode 100644 docs/pages/v3/requirements.mdx diff --git a/docs/pages/inner_workings/components/overview.mdx b/docs/pages/inner_workings/components/overview.mdx index 20517c538..aa040fcf1 100644 --- a/docs/pages/inner_workings/components/overview.mdx +++ b/docs/pages/inner_workings/components/overview.mdx @@ -1,20 +1,28 @@ -import { Callout } from 'nextra/components' +import { Callout } from 'nextra/components'; This documentation is still a work in progress. Some parts might be missing or incomplete. - This is also mostly for advanced use cases (Overriding some default, provide support for another Cloud provider, creating your own IAC component ...), most people won't need to use this. +This is also mostly for advanced use cases (Overriding some default, provide support for another Cloud provider, creating your own IAC component ...), most people won't need to use this. + +## General + +- For the node runtime, you need at least Node 18. +- For the edge runtime, you can use both Node 18+ or cloudflare workers with `node_compat` flag enabled (Cloudflare workers support is experimental) +- Open-next doesn't work well on Windows. We recommend using WSL2 or a Linux VM. + ## Backends Every backend is a separate module. The following backends are available: - - Servers (Node or Edge runtime) - - Middleware (If manually set to external) - - Image Optimization - - Revalidation - - Warmer - - Initializer + +- Servers (Node or Edge runtime) +- Middleware (If manually set to external) +- Image Optimization +- Revalidation +- Warmer +- Initializer All these backends can be overrided to fit your needs. They share some common ground for the configuration and the way they are used. @@ -56,10 +64,11 @@ export type Wrapper< The `handler` is the original handler that is being wrapped. The `converter` is the converter that is being used to convert the event and the result. Here is a list of the provided wrappers: - - `aws-lambda` - The default AWS Lambda wrapper - It is the default wrapper - - `aws-lambda-streaming` - The AWS Lambda wrapper with streaming support - - `node` - The Node wrapper - Create a node server, not suitable for serverless - - `cloudflare` - The Cloudflare wrapper - For Cloudflare Worker + +- `aws-lambda` - The default AWS Lambda wrapper - It is the default wrapper +- `aws-lambda-streaming` - The AWS Lambda wrapper with streaming support +- `node` - The Node wrapper - Create a node server, not suitable for serverless +- `cloudflare` - The Cloudflare wrapper - For Cloudflare Worker ##### Aws Lambda streaming @@ -84,11 +93,12 @@ export type Converter< The `convertFrom` method is used to convert the event to the internal event used by the backend internal handler. The `convertTo` method is used to convert the result to the expected result. `convertTo` can usually be ignored when using streaming as the result is being streamed directly. -Here is a list of the provided converters: - - `aws-apigw-v2` - The default AWS API Gateway v2 converter - It is the default converter - - `aws-apigw-v1` - The AWS API Gateway v1 converter - - `aws-cloudfront` - The AWS CloudFront converter - Used for lambda@edge - - `edge` - The Edge converter - Converts from `Request` and to `Response` - - `node` - The Node converter - Converts from `IncomingMessage` and to `ServerResponse` - - `sqs-revalidate` - The SQS Revalidate converter - Used by default for the revalidation backend - - `dummy` - The Dummy converter - Does nothing \ No newline at end of file +Here is a list of the provided converters: + +- `aws-apigw-v2` - The default AWS API Gateway v2 converter - It is the default converter +- `aws-apigw-v1` - The AWS API Gateway v1 converter +- `aws-cloudfront` - The AWS CloudFront converter - Used for lambda@edge +- `edge` - The Edge converter - Converts from `Request` and to `Response` +- `node` - The Node converter - Converts from `IncomingMessage` and to `ServerResponse` +- `sqs-revalidate` - The SQS Revalidate converter - Used by default for the revalidation backend +- `dummy` - The Dummy converter - Does nothing diff --git a/docs/pages/v3/_meta.json b/docs/pages/v3/_meta.json deleted file mode 100644 index caefcec50..000000000 --- a/docs/pages/v3/_meta.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "index": "What's new", - "config": "Configuration file", - "reference-implementation": "Reference Construct", - "requirements": "Requirements", - "override": "Advanced - Create your own override" -} \ No newline at end of file diff --git a/docs/pages/v3/config.mdx b/docs/pages/v3/config.mdx deleted file mode 100644 index 56ee0ba5a..000000000 --- a/docs/pages/v3/config.mdx +++ /dev/null @@ -1,69 +0,0 @@ -Here is a simple example of an `open-next.config.ts` file: -This file need to be at the same place as your `next.config.js` file - -`server` in here could refer to a lambda function, a docker container, a node server or whatever that can support running nodejs code. (Even cloudflare workers in the future) - -For more information about the options here, just look at the source file - -```ts -import type { OpenNextConfig } from 'open-next/types/open-next' -const config = { - default: { // This is the default server, similar to the server-function in open-next v2 - // You don't have to provide the below, by default it will generate an output - // for normal lambda as in open-next v2 - override: { - wrapper: "aws-lambda-streaming", // This is necessary to enable lambda streaming - // You can override any part that is a `LazyLoadedOverride` this way - queue: () => Promise.resolve({ - send: async (message) => { - //Your custom code here - } - }) - }, - }, - // Below we define the functions that we want to deploy in a different server - functions: { - ssr: { - routes: [ - "app/api/isr/route", "app/api/sse/route", "app/api/revalidateTag/route", // app dir Api routes - "app/route1/page", "app/route2/page", // app dir pages - "pages/route3" // page dir pages - ], // For app dir, you need to include route|page, no need to include layout or loading - patterns: ['api/*', 'route1', 'route2', 'route3'], // patterns needs to be in a cloudfront compatible format, this will be used to generate the output - override: { - wrapper: "aws-lambda-streaming", - }, - experimentalBundledNextServer: true // This enables the bundled next server which is faster and reduce the size of the server - }, - pageSsr: { - routes: ["pages/pageSsr"], // For page dir routes should be in the form `pages/${route}` without the extension, it should match the filesystem - patterns: [ 'pageSsr', "_next/data/BUILD_ID/pageSsr.json"], - override: { - wrapper: "node", - converter: "node", - // This is necessary to generate the dockerfile and for the implementation to know that it needs to deploy on docker - generateDockerfile: true, - }, - }, - edge: { - runtime: "edge", - routes: ["app/ssr/page"], - patterns: ["ssr"], - override: {} - } - }, - // By setting this, it will create another bundle for the middleware, - // and the middleware will be deployed in a separate server. - // If not set middleware will be bundled inside the servers - // It could be in lambda@edge, cloudflare workers, or anywhere else - // By default it uses lambda@edge - // This is not implemented in the reference construct implementation. - middleware: { - external: true - } - buildCommand: "echo 'hello world'", -} satisfies OpenNextConfig - -export default config; -export type Config = typeof config -``` \ No newline at end of file diff --git a/docs/pages/v3/index.mdx b/docs/pages/v3/index.mdx deleted file mode 100644 index db0161e60..000000000 --- a/docs/pages/v3/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ -import { Callout } from 'nextra/components' - - - -`open-next@3.0.0-rc.3` is here!!! Please report any issues you find on [discord](https://discord.com/channels/983865673656705025/1164872233223729152) or on the github [PR](https://github.com/sst/open-next/pull/327) - - This is a release candidate, it is mostly ready for production (You might still experience some quirks). We are looking for feedback on this release, so please try it out and let us know what you think. See [getting started](#get-started) to quickly test it. - - It also requires an updated version of the IAC tools that you use, see the sst PR [here](https://github.com/sst/sst/pull/3567) for more information. - - You could also use SST Ion which should support it out of the box pretty soon. See [here for more info](https://github.com/sst/ion) or in the [ion discord](https://discord.com/channels/983865673656705025/1177071497974648952). - - -## What's new in V3? - -- Rewritten server (We moved from the serverless-http `ServerResponse` into our own version which respect nodejs stream) -- A new `open-next.config.ts` file to configure your project -- Native support for aws lambda, aws lambda streaming, lambda@edge, node and docker -- In this `open-next.config.ts` you can now override a lot of things which allow for more customization: - - Wrapper component - - Converter component - - Incremental Cache - - Tag Cache - - Queue - - Custom warmer function - - Custom revalidation function - - Custom loader for image optimization - - Custom initialization function - -- Allow for splitting, you can now split your next app into multiple servers, which could each have their own configuration -- Allow to move the middleware/routing part in a separate lambda or cloudflare workers in front of your server functions -- An experimental bundled `NextServer` could be used which can reduce the size of your lambda by up to 24 MB -- Experimental support for the `edge` runtime of next with some limitations: - - Only app router for now - - Only 1 route per function - - Works fine in node, only for api route in cloudflare workers - - No support for `revalidateTag` or `revalidatePath` for now - -## Get started - -The easiest way to get started is to use the [reference implementation construct](/v3/reference-implementation). Copy this reference implementation into your project and then use it like that in your sst or cdk project: - -```ts -import { OpenNextCdkReferenceImplementation } from "path/to/reference-implementation" - -const site = new OpenNextCdkReferenceImplementation(stack, "site", { - openNextPath: ".open-next", -}) -``` - -You also need to create an `open-next.config.ts` file in your project root, you can find more info [here](/v3/config). - -A very simple example of this file could be: - -```ts -import type { OpenNextConfig } from 'open-next/types/open-next' -const config = { - default: { - - } -} -export default config; -``` - -Then you need to run `npx open-next@3.0.0-rc.3 build` to build your project before running the `sst deploy` or `cdk deploy` command to deploy your project. - -In V3 `open-next build` don't accept any arguments, all the args are passed in the `open-next.config.ts` file. \ No newline at end of file diff --git a/docs/pages/v3/override.mdx b/docs/pages/v3/override.mdx deleted file mode 100644 index 2cb1af3a8..000000000 --- a/docs/pages/v3/override.mdx +++ /dev/null @@ -1,74 +0,0 @@ -In this version of open-next, you could override a lot of the default behaviour. - -For some real example of how to override each behaviour: -- [Wrapper](https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/wrappers/aws-lambda.ts) -- [Converter](https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/converters/aws-apigw-v2.ts) -- [IncrementalCache](https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/cache/incremental/s3.ts) -- [TagCache]( - https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/cache/tag/dynamoDb.ts -) -- [Queue]( - https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/queue/sqs.ts -) - -This means it could allow people to write their own custom open-next. -For example you could create a custom `withGcp` plugin to allow to deploy open-next on GCP functions - -A boilerplate for such a plugin could look like this (This is not real code): - -```ts - -import { OpenNextConfig } from "open-next/types/open-next"; - -function withGcp(config: TrimmedDownConfig): OpenNextConfig { - return { - default: { - override: { - wrapper: async () => (await import("./gcp-wrapper")).default, - converter: async () => (await import("./gcp-converter")).default, - incrementalCache: async () => (await import("./gcp-incremental-cache")).default, - tagCache: async () => (await import("./gcp-tag-cache")).default, - queue: async () => (await import("./gcp-queue")).default, - }, - ...config.default, - }, - functions: { - // Same as default but for each splitted function - //... - } - warmer: { - override: { - wrapper: async () => (await import("./gcp-wrapper")).default, - converter: async () => (await import("./gcp-converter")).default, - }, - invokeFunction: async () => (await import("./gcp-invoke-function")).default, - }, - revalidate: { - override: { - wrapper: async () => (await import("./gcp-wrapper")).default, - converter: async () => (await import("./gcp-queue-converter")).default, - }, - }, - imageOptimization: { - override: { - wrapper: async () => (await import("./gcp-wrapper")).default, - converter: async () => (await import("./gcp-converter")).default, - }, - loader: async () => (await import("./gcp-object-loader")).default, - }, - } -} -``` - -Using this plugin would look like this inside `open-next.config.ts`: - -```ts -import { withGcp } from "./with-gcp"; -const config = withGcp({ - default: { - // ... - }, -}); - -export default config; -``` \ No newline at end of file diff --git a/docs/pages/v3/reference-implementation.mdx b/docs/pages/v3/reference-implementation.mdx deleted file mode 100644 index 02d213fb5..000000000 --- a/docs/pages/v3/reference-implementation.mdx +++ /dev/null @@ -1,435 +0,0 @@ -import { Callout } from 'nextra/components' - -In order to help testing the rc release, we created a simple reference implementation using aws-cdk. - -If you wish to use it, just copy the code for the construct below. If you use it inside sst, make sure to use the same version of aws-cdk as sst. - - - - This is a reference implementation, and it is not meant to be used in production. - - The goal is to help with the adoption of the rc release, and to gather feedback from the community. - It also serves as a good example of how to use the new features. - - There is some features that are not implemented like the warmer function, or everything related to lambda@edge(It requires inserting env variables which is out of scope of this implementation). - - -```ts -import { Construct } from "constructs"; -import { readFileSync } from "fs"; -import path from "path"; -import { BlockPublicAccess, Bucket } from "aws-cdk-lib/aws-s3"; -import { BucketDeployment, Source } from "aws-cdk-lib/aws-s3-deployment"; -import { - CustomResource, - Duration, - Fn, - RemovalPolicy, - Stack, -} from "aws-cdk-lib/core"; -import { - AllowedMethods, - BehaviorOptions, - CacheCookieBehavior, - CacheHeaderBehavior, - CachePolicy, - CacheQueryStringBehavior, - CachedMethods, - Distribution, - ICachePolicy, - ViewerProtocolPolicy, - FunctionEventType, - OriginRequestPolicy, - Function as CloudfrontFunction, - FunctionCode, -} from "aws-cdk-lib/aws-cloudfront"; -import { HttpOrigin, S3Origin } from "aws-cdk-lib/aws-cloudfront-origins"; -import { - Code, - Function as CdkFunction, - FunctionUrlAuthType, - InvokeMode, - Runtime, -} from "aws-cdk-lib/aws-lambda"; -import { - TableV2 as Table, - AttributeType, - Billing, -} from "aws-cdk-lib/aws-dynamodb"; -import { - Service, - Source as AppRunnerSource, - Memory, - HealthCheck, - Cpu, -} from "@aws-cdk/aws-apprunner-alpha"; -import { DockerImageAsset } from "aws-cdk-lib/aws-ecr-assets"; -import { Queue } from "aws-cdk-lib/aws-sqs"; -import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources"; -import { IGrantable } from "aws-cdk-lib/aws-iam"; -import { Provider } from "aws-cdk-lib/custom-resources"; -import { RetentionDays } from "aws-cdk-lib/aws-logs"; - -type BaseFunction = { - handler: string; - bundle: string; -}; - -type OpenNextFunctionOrigin = { - type: "function"; - streaming?: boolean; -} & BaseFunction; - -type OpenNextECSOrigin = { - type: "ecs"; - bundle: string; - dockerfile: string; -}; - -type OpenNextS3Origin = { - type: "s3"; - originPath: string; - copy: { - from: string; - to: string; - cached: boolean; - versionedSubDir?: string; - }[]; -}; - -type OpenNextOrigins = - | OpenNextFunctionOrigin - | OpenNextECSOrigin - | OpenNextS3Origin; - -interface OpenNextOutput { - edgeFunctions: { - [key: string]: BaseFunction; - }; - origins: { - s3: OpenNextS3Origin; - default: OpenNextFunctionOrigin | OpenNextECSOrigin; - imageOptimizer: OpenNextFunctionOrigin | OpenNextECSOrigin; - [key: string]: OpenNextOrigins; - }; - behaviors: { - pattern: string; - origin?: string; - edgeFunction?: string; - }[]; - additionalProps?: { - disableIncrementalCache?: boolean; - disableTagCache?: boolean; - initializationFunction?: BaseFunction; - warmer?: BaseFunction; - revalidationFunction?: BaseFunction; - }; -} - -interface OpenNextCdkReferenceImplementationProps { - openNextPath: string; -} - -export class OpenNextCdkReferenceImplementation extends Construct { - private openNextOutput: OpenNextOutput; - private bucket: Bucket; - private table: Table; - private queue: Queue; - - private staticCachePolicy: ICachePolicy; - private serverCachePolicy: CachePolicy; - - public distribution: Distribution; - - constructor( - scope: Construct, - id: string, - props: OpenNextCdkReferenceImplementationProps, - ) { - super(scope, id); - this.openNextOutput = JSON.parse( - readFileSync( - path.join(props.openNextPath, "open-next.output.json"), - "utf-8", - ), - ) as OpenNextOutput; - - this.bucket = new Bucket(this, "OpenNextBucket", { - publicReadAccess: false, - blockPublicAccess: BlockPublicAccess.BLOCK_ALL, - autoDeleteObjects: true, - removalPolicy: RemovalPolicy.DESTROY, - enforceSSL: true, - }); - this.table = this.createRevalidationTable(); - this.queue = this.createRevalidationQueue(); - - const origins = this.createOrigins(); - this.serverCachePolicy = this.createServerCachePolicy(); - this.staticCachePolicy = this.createStaticCachePolicy(); - this.distribution = this.createDistribution(origins); - } - - private createRevalidationTable() { - const table = new Table(this, "RevalidationTable", { - partitionKey: { name: "tag", type: AttributeType.STRING }, - sortKey: { name: "path", type: AttributeType.STRING }, - pointInTimeRecovery: true, - billing: Billing.onDemand(), - globalSecondaryIndexes: [ - { - indexName: "revalidate", - partitionKey: { name: "path", type: AttributeType.STRING }, - sortKey: { name: "revalidatedAt", type: AttributeType.NUMBER }, - }, - ], - removalPolicy: RemovalPolicy.DESTROY, - }); - - const initFn = this.openNextOutput.additionalProps?.initializationFunction; - - const insertFn = new CdkFunction(this, "RevalidationInsertFunction", { - description: "Next.js revalidation data insert", - handler: initFn?.handler ?? "index.handler", - // code: Code.fromAsset(initFn?.bundle ?? ""), - code: Code.fromAsset(".open-next/dynamodb-provider"), - runtime: Runtime.NODEJS_18_X, - timeout: Duration.minutes(15), - memorySize: 128, - environment: { - CACHE_DYNAMO_TABLE: table.tableName, - }, - }); - - const provider = new Provider(this, "RevalidationProvider", { - onEventHandler: insertFn, - logRetention: RetentionDays.ONE_DAY, - }); - - new CustomResource(this, "RevalidationResource", { - serviceToken: provider.serviceToken, - properties: { - version: Date.now().toString(), - }, - }); - - return table; - } - - private createOrigins() { - const { - s3: s3Origin, - default: defaultOrigin, - imageOptimizer: imageOrigin, - ...restOrigins - } = this.openNextOutput.origins; - const s3 = new S3Origin(this.bucket, { - originPath: s3Origin.originPath, - }); - for (const copy of s3Origin.copy) { - new BucketDeployment(this, `OpenNextBucketDeployment${copy.from}`, { - sources: [Source.asset(copy.from)], - destinationBucket: this.bucket, - destinationKeyPrefix: copy.to, - prune: false, - }); - } - const origins = { - s3: new S3Origin(this.bucket, { - originPath: s3Origin.originPath, - originAccessIdentity: undefined, - }), - default: - defaultOrigin.type === "function" - ? this.createFunctionOrigin("default", defaultOrigin) - : this.createAppRunnerOrigin("default", defaultOrigin), - imageOptimizer: - imageOrigin.type === "function" - ? this.createFunctionOrigin("imageOptimizer", imageOrigin) - : this.createAppRunnerOrigin("imageOptimizer", imageOrigin), - ...Object.entries(restOrigins).reduce( - (acc, [key, value]) => { - if (value.type === "function") { - acc[key] = this.createFunctionOrigin(key, value); - } else if (value.type === "ecs") { - acc[key] = this.createAppRunnerOrigin(key, value); - } - return acc; - }, - {} as Record, - ), - }; - return origins; - } - - private createRevalidationQueue() { - const queue = new Queue(this, "RevalidationQueue", { - fifo: true, - receiveMessageWaitTime: Duration.seconds(20), - }); - const consumer = new CdkFunction(this, "RevalidationFunction", { - description: "Next.js revalidator", - handler: "index.handler", - code: Code.fromAsset( - this.openNextOutput.additionalProps?.revalidationFunction?.bundle ?? "", - ), - runtime: Runtime.NODEJS_18_X, - timeout: Duration.seconds(30), - }); - consumer.addEventSource(new SqsEventSource(queue, { batchSize: 5 })); - return queue; - } - - private getEnvironment() { - return { - CACHE_BUCKET_NAME: this.bucket.bucketName, - CACHE_BUCKET_KEY_PREFIX: "_cache", - CACHE_BUCKET_REGION: Stack.of(this).region, - REVALIDATION_QUEUE_URL: this.queue.queueUrl, - REVALIDATION_QUEUE_REGION: Stack.of(this).region, - CACHE_DYNAMO_TABLE: this.table.tableName, - // Those 2 are used only for image optimizer - BUCKET_NAME: this.bucket.bucketName, - BUCKET_KEY_PREFIX: "_assets", - }; - } - - private grantPermissions(grantable: IGrantable) { - this.bucket.grantReadWrite(grantable); - this.table.grantReadWriteData(grantable); - this.queue.grantSendMessages(grantable); - } - - private createFunctionOrigin(key: string, origin: OpenNextFunctionOrigin) { - const environment = this.getEnvironment(); - const fn = new CdkFunction(this, `${key}Function`, { - runtime: Runtime.NODEJS_18_X, - handler: origin.handler, - code: Code.fromAsset(origin.bundle), - environment, - memorySize: 1024, - }); - const fnUrl = fn.addFunctionUrl({ - authType: FunctionUrlAuthType.NONE, - invokeMode: origin.streaming - ? InvokeMode.RESPONSE_STREAM - : InvokeMode.BUFFERED, - }); - this.grantPermissions(fn); - return new HttpOrigin(Fn.parseDomainName(fnUrl.url)); - } - - // We are using AppRunner because it is the easiest way to demonstrate the new feature. - // You can use any other container service like ECS, EKS, Fargate, etc. - private createAppRunnerOrigin( - key: string, - origin: OpenNextECSOrigin, - ): HttpOrigin { - const imageAsset = new DockerImageAsset(this, `${key}ImageAsset`, { - directory: origin.bundle, - // file: origin.dockerfile, - }); - const service = new Service(this, `${key}Service`, { - source: AppRunnerSource.fromAsset({ - asset: imageAsset, - - imageConfiguration: { - port: 3000, - environmentVariables: this.getEnvironment(), - }, - }), - serviceName: key, - autoDeploymentsEnabled: false, - cpu: Cpu.HALF_VCPU, - memory: Memory.ONE_GB, - healthCheck: HealthCheck.http({ - path: "/__health", - }), - }); - this.grantPermissions(service); - return new HttpOrigin(service.serviceUrl); - } - - private createDistribution(origins: Record) { - const cloudfrontFunction = new CloudfrontFunction(this, 'OpenNextCfFunction', { - code: FunctionCode.fromInline(` - function handler(event) { - var request = event.request; - request.headers["x-forwarded-host"] = request.headers.host; - return request; - } - `) - }) - const fnAssociations = [ - { - function: cloudfrontFunction , - eventType: FunctionEventType.VIEWER_REQUEST, - }, - ] - - const distribution = new Distribution(this, "OpenNextDistribution", { - defaultBehavior: { - origin: origins.default, - viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS, - allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS, - cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS, - cachePolicy: this.serverCachePolicy, - originRequestPolicy: OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER, - functionAssociations: fnAssociations - }, - additionalBehaviors: this.openNextOutput.behaviors - .filter((b) => b.pattern !== "*") - .reduce( - (acc, behavior) => { - return { - ...acc, - [behavior.pattern]: { - origin: behavior.origin - ? origins[behavior.origin] - : origins.default, - viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS, - allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS, - cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS, - cachePolicy: - behavior.origin === "s3" - ? this.staticCachePolicy - : this.serverCachePolicy, - originRequestPolicy: - behavior.origin === "s3" - ? undefined - : OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER, - functionAssociations: fnAssociations - }, - }; - }, - {} as Record, - ), - }); - return distribution; - } - - private createServerCachePolicy() { - return new CachePolicy(this, "OpenNextServerCachePolicy", { - queryStringBehavior: CacheQueryStringBehavior.all(), - headerBehavior: CacheHeaderBehavior.allowList( - "accept", - "accept-encoding", - "rsc", - "next-router-prefetch", - "next-router-state-tree", - "next-url", - "x-prerender-revalidate", - ), - cookieBehavior: CacheCookieBehavior.none(), - defaultTtl: Duration.days(0), - maxTtl: Duration.days(365), - minTtl: Duration.days(0), - }); - } - - private createStaticCachePolicy() { - return CachePolicy.CACHING_OPTIMIZED; - } -} - -``` diff --git a/docs/pages/v3/requirements.mdx b/docs/pages/v3/requirements.mdx deleted file mode 100644 index 71279afad..000000000 --- a/docs/pages/v3/requirements.mdx +++ /dev/null @@ -1,59 +0,0 @@ -There is a couple of requirements necessary for open-next V3 to work. -It will be divided by functionality. This is still WIP, feel free to open a PR if you think something is missing. - -## General -- For the node runtime, you need at least Node 18. -- For the edge runtime, you can use both Node 18+ or cloudflare workers with `node_compat` flag enabled (Cloudflare workers support is experimental) -- Open-next doesn't work well on Windows. We recommend using WSL2 or a Linux VM. - -## ISR/SSG -ISR/SSG has 2 types of cache, the Incremental Cache and the Tag Cache. To actually trigger the ISR revalidation, we use a Queue system. - -The tag cache is only used in app router. -### Incremental Cache -By default we use S3 as the incremental cache. You can override this in `open-next.config.ts`. For this to work you need to provide server functions with the following environment variables: -- CACHE_BUCKET_REGION -- CACHE_BUCKET_NAME -- CACHE_BUCKET_KEY_PREFIX - -### Tag Cache -By default we use DynamoDb as the tag cache. For this to work you need to provide server functions with the following environment variables: -- CACHE_DYNAMO_TABLE -- CACHE_BUCKET_REGION - -### Queue -By default we use SQS as the queue. fFr this to work you need to provide server functions with the following environment variables: -- REVALIDATION_QUEUE_REGION -- REVALIDATION_QUEUE_URL - -## External Middleware -If you decide to use external middleware, you need to provide the following environment variables: -- OPEN_NEXT_ORIGIN - -This env variable should contain a stringified version of this, with every key corresponding to the key used in functions inside `open-next.config.ts`: -```ts -// For cloudflare workers -// THIS IS TEMPORARY, WE WILL CHANGE THIS TO USE THE SAME FORMAT AS NODE -{ - default: "example.com", - ssr: "example2.com", - ssg: "example3.com" -} -// Or for node -{ - default: { - host: "example.com", - protocol: "https", - port: 443 // Optional - customHeaders: { - "x-custom-header": "value" - } // Optional, headers that you'd want to pass to the origin - }, - ... -} -``` - -## Image Optimization -For image optimization to work, you need to provide the following environment variables: -- BUCKET_NAME -- BUCKET_KEY_PREFIX \ No newline at end of file