diff --git a/README.md b/README.md index 891b8fe5ca..06c203d4f8 100644 --- a/README.md +++ b/README.md @@ -147,26 +147,36 @@ myNextApplication: ] # this is the cache behaviour for next.js api pages api: - ttl: 10 + minTTL: 10 + maxTTL: 10 + defaultTTL: 10 # you can set other cache behaviours like "defaults" above that can handle server side rendering # but more specific for a subset of your next.js pages /blog/*: - ttl: 1000 + minTTL: 1000 + maxTTL: 1000 + defaultTTL: 1000 forward: cookies: "all" queryString: false /about: - ttl: 3000 + minTTL: 3000 + maxTTL: 3000 + defaultTTL: 3000 # you can add custom origins to the cloudfront distribution origins: - url: /static pathPatterns: /wp-content/*: - ttl: 10 + minTTL: 10 + maxTTL: 10 + defaultTTL: 10 - url: https://old-static.com pathPatterns: /old-static/*: - ttl: 10 + minTTL: 10 + maxTTL: 10 + defaultTTL: 10 priceClass: "PriceClass_100" ``` diff --git a/packages/libs/s3-static-assets/src/index.ts b/packages/libs/s3-static-assets/src/index.ts index 7d965ab8ba..22e304aa99 100644 --- a/packages/libs/s3-static-assets/src/index.ts +++ b/packages/libs/s3-static-assets/src/index.ts @@ -111,7 +111,8 @@ const uploadStaticAssets = async ( s3Key: pathToPosix( withBasePath(prerenderManifest.routes[key].dataRoute.slice(1)) ), - filePath: pageFilePath + filePath: pageFilePath, + cacheControl: SERVER_CACHE_CONTROL_HEADER }); }); diff --git a/packages/libs/s3-static-assets/tests/upload-assets.test.ts b/packages/libs/s3-static-assets/tests/upload-assets.test.ts index c95dc18d9c..394a0b3465 100644 --- a/packages/libs/s3-static-assets/tests/upload-assets.test.ts +++ b/packages/libs/s3-static-assets/tests/upload-assets.test.ts @@ -171,7 +171,7 @@ describe.each` expect.objectContaining({ Key: "_next/data/zsWqBqLjpgRmswfQomanp/index.json", ContentType: "application/json", - CacheControl: undefined + CacheControl: SERVER_CACHE_CONTROL_HEADER }) ); @@ -179,7 +179,7 @@ describe.each` expect.objectContaining({ Key: "_next/data/zsWqBqLjpgRmswfQomanp/todos/terms/a.json", ContentType: "application/json", - CacheControl: undefined + CacheControl: SERVER_CACHE_CONTROL_HEADER }) ); @@ -187,7 +187,7 @@ describe.each` expect.objectContaining({ Key: "_next/data/zsWqBqLjpgRmswfQomanp/todos/terms/b.json", ContentType: "application/json", - CacheControl: undefined + CacheControl: SERVER_CACHE_CONTROL_HEADER }) ); }); diff --git a/packages/serverless-components/aws-cloudfront/__tests__/cache-behavior-options.test.js b/packages/serverless-components/aws-cloudfront/__tests__/cache-behavior-options.test.js index 8fc9f82f5b..2d72897c25 100644 --- a/packages/serverless-components/aws-cloudfront/__tests__/cache-behavior-options.test.js +++ b/packages/serverless-components/aws-cloudfront/__tests__/cache-behavior-options.test.js @@ -23,7 +23,9 @@ describe("Input origin as a custom url", () => { it("creates distribution with custom default behavior options", async () => { await component.default({ defaults: { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, forward: { headers: ["Accept", "Accept-Language"], cookies: "all", @@ -53,14 +55,18 @@ describe("Input origin as a custom url", () => { it("creates distribution with custom behavior options", async () => { await component.default({ defaults: { - ttl: 0 + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000 }, origins: [ { url: "https://mycustomorigin.com", pathPatterns: { "/sample/path": { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 0, forward: { headers: "all", cookies: ["auth-token"], diff --git a/packages/serverless-components/aws-cloudfront/__tests__/custom-url-origin.test.js b/packages/serverless-components/aws-cloudfront/__tests__/custom-url-origin.test.js index 614d777892..9634869152 100644 --- a/packages/serverless-components/aws-cloudfront/__tests__/custom-url-origin.test.js +++ b/packages/serverless-components/aws-cloudfront/__tests__/custom-url-origin.test.js @@ -35,7 +35,9 @@ describe("Input origin as a custom url", () => { "PUT", "PATCH" ], - ttl: 10, + minTTL: 0, + defaultTTL: 10, + maxTTL: 31536000, "lambda@edge": { "origin-request": "arn:aws:lambda:us-east-1:123:function:originRequestFunction" diff --git a/packages/serverless-components/aws-cloudfront/__tests__/existing-distribution.test.js b/packages/serverless-components/aws-cloudfront/__tests__/existing-distribution.test.js index ac49105b86..7f3d3aebc2 100644 --- a/packages/serverless-components/aws-cloudfront/__tests__/existing-distribution.test.js +++ b/packages/serverless-components/aws-cloudfront/__tests__/existing-distribution.test.js @@ -113,7 +113,9 @@ describe("Working with an existing distribution", () => { url: "https://existingorigin2.com", pathPatterns: { "/some/path": { - ttl: 10 + minTTL: 10, + defaultTTL: 10, + maxTTL: 10 } } } diff --git a/packages/serverless-components/aws-cloudfront/__tests__/lambda-at-edge.test.js b/packages/serverless-components/aws-cloudfront/__tests__/lambda-at-edge.test.js index 076f5d0049..268a937b2f 100644 --- a/packages/serverless-components/aws-cloudfront/__tests__/lambda-at-edge.test.js +++ b/packages/serverless-components/aws-cloudfront/__tests__/lambda-at-edge.test.js @@ -27,7 +27,9 @@ describe("Input origin as a custom url", () => { url: "https://exampleorigin.com", pathPatterns: { "/some/path": { - ttl: 10, + minTTL: 10, + defaultTTL: 10, + maxTTL: 10, "lambda@edge": { "viewer-request": "arn:aws:lambda:us-east-1:123:function:viewerRequestFunction", @@ -88,7 +90,9 @@ describe("Input origin as a custom url", () => { url: "https://exampleorigin.com", pathPatterns: { "/some/path": { - ttl: 10, + minTTL: 10, + defaultTTL: 10, + maxTTL: 10, "lambda@edge": { "invalid-eventtype": "arn:aws:lambda:us-east-1:123:function:viewerRequestFunction" diff --git a/packages/serverless-components/aws-cloudfront/__tests__/origin-with-path-pattern.test.js b/packages/serverless-components/aws-cloudfront/__tests__/origin-with-path-pattern.test.js index 6f38d5fc99..a5b907b460 100644 --- a/packages/serverless-components/aws-cloudfront/__tests__/origin-with-path-pattern.test.js +++ b/packages/serverless-components/aws-cloudfront/__tests__/origin-with-path-pattern.test.js @@ -34,7 +34,9 @@ describe("Input origin with path pattern", () => { url: "https://exampleorigin.com", pathPatterns: { "/some/path": { - ttl: 10, + minTTL: 10, + defaultTTL: 10, + maxTTL: 10, allowedHttpMethods: ["GET", "HEAD", "POST"] } } @@ -78,7 +80,9 @@ describe("Input origin with path pattern", () => { url: "https://exampleorigin.com", pathPatterns: { "/some/path": { - ttl: 10 + minTTL: 10, + defaultTTL: 10, + maxTTL: 10 } } } @@ -91,7 +95,9 @@ describe("Input origin with path pattern", () => { url: "https://exampleorigin.com", pathPatterns: { "/some/other/path": { - ttl: 10 + minTTL: 10, + defaultTTL: 10, + maxTTL: 10 } } } diff --git a/packages/serverless-components/aws-cloudfront/lib/getCacheBehavior.js b/packages/serverless-components/aws-cloudfront/lib/getCacheBehavior.js index 61375d7c7a..eaa2cb54ac 100644 --- a/packages/serverless-components/aws-cloudfront/lib/getCacheBehavior.js +++ b/packages/serverless-components/aws-cloudfront/lib/getCacheBehavior.js @@ -3,7 +3,9 @@ const { getForwardedValues } = require("./cacheBahaviorUtils"); module.exports = (pathPattern, pathPatternConfig, originId) => { const { allowedHttpMethods = ["GET", "HEAD"], - ttl, + minTTL, + defaultTTL, + maxTTL, compress = true, smoothStreaming = false, viewerProtocolPolicy = "https-only", @@ -15,7 +17,7 @@ module.exports = (pathPattern, pathPatternConfig, originId) => { cookies: "all", queryString: true }), - MinTTL: ttl, + MinTTL: minTTL, PathPattern: pathPattern, TargetOriginId: originId, TrustedSigners: { @@ -33,8 +35,8 @@ module.exports = (pathPattern, pathPatternConfig, originId) => { }, Compress: compress, SmoothStreaming: smoothStreaming, - DefaultTTL: ttl, - MaxTTL: ttl, + DefaultTTL: defaultTTL, + MaxTTL: maxTTL, FieldLevelEncryptionId: fieldLevelEncryptionId, LambdaFunctionAssociations: { Quantity: 0, diff --git a/packages/serverless-components/aws-cloudfront/lib/getDefaultCacheBehavior.js b/packages/serverless-components/aws-cloudfront/lib/getDefaultCacheBehavior.js index 10aa27085c..c0ba12372c 100644 --- a/packages/serverless-components/aws-cloudfront/lib/getDefaultCacheBehavior.js +++ b/packages/serverless-components/aws-cloudfront/lib/getDefaultCacheBehavior.js @@ -5,7 +5,9 @@ module.exports = (originId, defaults = {}) => { const { allowedHttpMethods = ["HEAD", "GET"], forward = {}, - ttl = 86400, + minTTL = 0, + defaultTTL = 86400, + maxTTL = 31536000, compress = false, smoothStreaming = false, viewerProtocolPolicy = "redirect-to-https", @@ -21,7 +23,7 @@ module.exports = (originId, defaults = {}) => { Items: [] }, ViewerProtocolPolicy: viewerProtocolPolicy, - MinTTL: 0, + MinTTL: minTTL, AllowedMethods: { Quantity: allowedHttpMethods.length, Items: allowedHttpMethods, @@ -31,8 +33,8 @@ module.exports = (originId, defaults = {}) => { } }, SmoothStreaming: smoothStreaming, - DefaultTTL: ttl, - MaxTTL: 31536000, + DefaultTTL: defaultTTL, + MaxTTL: maxTTL, Compress: compress, LambdaFunctionAssociations: { Quantity: 0, diff --git a/packages/serverless-components/nextjs-component/__tests__/custom-inputs.test.ts b/packages/serverless-components/nextjs-component/__tests__/custom-inputs.test.ts index 86e7353ba6..5086ff9211 100644 --- a/packages/serverless-components/nextjs-component/__tests__/custom-inputs.test.ts +++ b/packages/serverless-components/nextjs-component/__tests__/custom-inputs.test.ts @@ -486,20 +486,24 @@ describe("Custom inputs", () => { [ { defaults: { - ttl: 500, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, "lambda@edge": { "origin-request": "ignored", "origin-response": "also ignored" } } }, - { defaults: { ttl: 500 } } + { defaults: { minTTL: 0, defaultTTL: 0, maxTTL: 31536000 } } ], // allow lamdba@edge triggers other than origin-request and origin-response [ { defaults: { - ttl: 500, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, "lambda@edge": { "viewer-request": "used value" } @@ -507,7 +511,9 @@ describe("Custom inputs", () => { }, { defaults: { - ttl: 500, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, "lambda@edge": { "viewer-request": "used value" } } } @@ -528,23 +534,29 @@ describe("Custom inputs", () => { [ { "api/*": { - ttl: 500, + minTTL: 500, + defaultTTL: 500, + maxTTL: 500, "lambda@edge": { "origin-request": "ignored value" } } }, - { "api/*": { ttl: 500 } } + { "api/*": { minTTL: 500, defaultTTL: 500, maxTTL: 500 } } ], // allow other lambda@edge triggers on the api cache behaviour [ { "api/*": { - ttl: 500, + minTTL: 500, + defaultTTL: 500, + maxTTL: 500, "lambda@edge": { "origin-response": "used value" } } }, { "api/*": { - ttl: 500, + minTTL: 500, + defaultTTL: 500, + maxTTL: 500, "lambda@edge": { "origin-response": "used value" } } } @@ -581,7 +593,9 @@ describe("Custom inputs", () => { [ { "/terms": { - ttl: 5500, + minTTL: 5500, + defaultTTL: 5500, + maxTTL: 5500, "misc-param": "misc-value", "lambda@edge": { "origin-request": "ignored value" @@ -590,7 +604,9 @@ describe("Custom inputs", () => { }, { "/terms": { - ttl: 5500, + minTTL: 5500, + defaultTTL: 5500, + maxTTL: 5500, "misc-param": "misc-value" } } @@ -598,12 +614,16 @@ describe("Custom inputs", () => { [ { "/customers/stan-sack": { - ttl: 5500 + minTTL: 5500, + defaultTTL: 5500, + maxTTL: 5500 } }, { "/customers/stan-sack": { - ttl: 5500 + minTTL: 5500, + defaultTTL: 5500, + maxTTL: 5500 } } ] @@ -661,7 +681,9 @@ describe("Custom inputs", () => { const cloudfrontConfig = { defaults: { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, allowedHttpMethods: ["HEAD", "GET"], forward: { cookies: "all", @@ -676,7 +698,9 @@ describe("Custom inputs", () => { ...customPageCacheBehaviours, "_next/static/*": { ...customPageCacheBehaviours["_next/static/*"], - ttl: 86400, + minTTL: 0, + defaultTTL: 86400, + maxTTL: 31536000, forward: { headers: "none", cookies: "none", @@ -684,7 +708,9 @@ describe("Custom inputs", () => { } }, "_next/data/*": { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, allowedHttpMethods: ["HEAD", "GET"], "lambda@edge": { "origin-request": @@ -694,12 +720,16 @@ describe("Custom inputs", () => { } }, "api/*": { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, ...expectedApiCacheBehaviour }, "static/*": { ...customPageCacheBehaviours["static/*"], - ttl: 86400, + minTTL: 0, + defaultTTL: 86400, + maxTTL: 31536000, forward: { headers: "none", cookies: "none", diff --git a/packages/serverless-components/nextjs-component/__tests__/deploy.test.ts b/packages/serverless-components/nextjs-component/__tests__/deploy.test.ts index 1af26a1e08..a6f0d96800 100644 --- a/packages/serverless-components/nextjs-component/__tests__/deploy.test.ts +++ b/packages/serverless-components/nextjs-component/__tests__/deploy.test.ts @@ -153,7 +153,9 @@ describe("deploy tests", () => { queryString: true, cookies: "all" }, - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, "lambda@edge": { "origin-request": "arn:aws:lambda:us-east-1:123456789012:function:default-cachebehavior-func:v1", @@ -168,7 +170,9 @@ describe("deploy tests", () => { private: true, pathPatterns: { "_next/static/*": { - ttl: 86400, + minTTL: 0, + defaultTTL: 86400, + maxTTL: 31536000, forward: { headers: "none", cookies: "none", @@ -176,7 +180,9 @@ describe("deploy tests", () => { } }, "_next/data/*": { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, allowedHttpMethods: ["HEAD", "GET"], "lambda@edge": { "origin-request": @@ -186,7 +192,9 @@ describe("deploy tests", () => { } }, "static/*": { - ttl: 86400, + minTTL: 0, + defaultTTL: 86400, + maxTTL: 31536000, forward: { headers: "none", cookies: "none", @@ -194,7 +202,9 @@ describe("deploy tests", () => { } }, "api/*": { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, "lambda@edge": { "origin-request": "arn:aws:lambda:us-east-1:123456789012:function:api-cachebehavior-func:v1" diff --git a/packages/serverless-components/nextjs-component/src/component.ts b/packages/serverless-components/nextjs-component/src/component.ts index 5aedcf2c0b..bbc1c22be8 100644 --- a/packages/serverless-components/nextjs-component/src/component.ts +++ b/packages/serverless-components/nextjs-component/src/component.ts @@ -289,7 +289,9 @@ class NextjsComponent extends Component { cloudFrontOrigins[0].pathPatterns[ this.pathPattern("_next/static/*", routesManifest) ] = { - ttl: 86400, + minTTL: 0, + defaultTTL: 86400, + maxTTL: 31536000, forward: { headers: "none", cookies: "none", @@ -300,7 +302,9 @@ class NextjsComponent extends Component { cloudFrontOrigins[0].pathPatterns[ this.pathPattern("static/*", routesManifest) ] = { - ttl: 86400, + minTTL: 0, + defaultTTL: 86400, + maxTTL: 31536000, forward: { headers: "none", cookies: "none", @@ -390,7 +394,9 @@ class NextjsComponent extends Component { cloudFrontOrigins[0].pathPatterns[ this.pathPattern("api/*", routesManifest) ] = { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, allowedHttpMethods: [ "HEAD", "DELETE", @@ -479,7 +485,9 @@ class NextjsComponent extends Component { cloudFrontOrigins[0].pathPatterns[ this.pathPattern("_next/data/*", routesManifest) ] = { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, allowedHttpMethods: ["HEAD", "GET"], "lambda@edge": { "origin-response": `${defaultEdgeLambdaOutputs.arn}:${defaultEdgeLambdaPublishOutputs.version}`, @@ -498,7 +506,9 @@ class NextjsComponent extends Component { const cloudFrontOutputs = await cloudFront({ defaults: { - ttl: 0, + minTTL: 0, + defaultTTL: 0, + maxTTL: 31536000, ...cloudFrontDefaults, forward: { cookies: "all",