-
-
Notifications
You must be signed in to change notification settings - Fork 461
Incremental static regeneration #1028
Changes from 2 commits
31f313c
35cf5ff
65ba637
0ee2f55
6f1ce93
fc8bd38
8a0d5ff
67cda68
16fe62b
26ed898
ef7d03b
f4548b3
b52d762
3dc480f
127698b
7eb5bb4
a3eb635
30d0e51
c03105f
6adf890
9dbfb27
f0650f2
57b403b
43f064a
db31e75
6f0f45c
26c8449
f397f50
631d8c0
5fc9807
b8cb485
99ec48c
93a0826
10f9f67
cb5ad0b
f9806d2
3552751
09f739f
41202f3
d9417b8
1f757d1
fbe017e
027e9c1
855fc88
436b584
90ce486
d546e02
a3c3e36
738335e
bf8038a
e49eac4
b13cb05
aaa0916
f104d19
bf6ceed
200f195
e2cae31
f4e5218
2cde26b
3c37c3f
7586260
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import lambdaAtEdgeCompat from "@sls-next/next-aws-cloudfront"; | ||
import { OriginRequestDefaultHandlerManifest } from "./types"; | ||
import { S3Client } from "@aws-sdk/client-s3"; | ||
import { buildS3RetryStrategy } from "./s3/s3RetryStrategy"; | ||
|
||
export const handler: AWSLambda.SQSHandler = async (event) => { | ||
await Promise.all( | ||
event.Records.map(async (record) => { | ||
const bucketName = record.messageAttributes.BucketName?.stringValue; | ||
const bucketRegion = record.messageAttributes.BucketRegion?.stringValue; | ||
const manifestString = record.messageAttributes.Manifest?.stringValue; | ||
const basePath = record.messageAttributes.BasePath?.stringValue; | ||
const cloudFrontEventRequestString = | ||
record.messageAttributes.CloudFrontEventRequest?.stringValue; | ||
if ( | ||
!bucketName || | ||
!bucketRegion || | ||
!cloudFrontEventRequestString || | ||
!manifestString | ||
) { | ||
throw new Error( | ||
"Expected BucketName, BucketRegion, CloudFrontEventRequest & EnableHTTPCompression message attributes" | ||
); | ||
} | ||
const cloudFrontEventRequest: AWSLambda.CloudFrontRequest = JSON.parse( | ||
cloudFrontEventRequestString | ||
); | ||
const manifest: OriginRequestDefaultHandlerManifest = JSON.parse( | ||
manifestString | ||
); | ||
|
||
const s3 = new S3Client({ | ||
kirkness marked this conversation as resolved.
Show resolved
Hide resolved
|
||
region: cloudFrontEventRequest.origin?.s3?.region, | ||
maxAttempts: 3, | ||
retryStrategy: await buildS3RetryStrategy() | ||
}); | ||
|
||
const { req, res } = lambdaAtEdgeCompat( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks to be just regular Lambda, so this should not be needed, right? You can just create a Node req, res in that case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct! Good catch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On second thought, the reason this is here is due to the fact that the original CloudFront event is actually passed through the queue to this lambda (the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea, makes sense for now. I think it would be good to have a generic event since in the future this can be used for regular Lambda traffic (and maybe other providers) |
||
{ request: cloudFrontEventRequest }, | ||
{ enableHTTPCompression: manifest.enableHTTPCompression } | ||
); | ||
|
||
const baseKey = cloudFrontEventRequest.uri | ||
.replace(/^\//, "") | ||
.replace(/\.(json|html)$/, "") | ||
.replace(/^_next\/data\/[^\/]*\//, ""); | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const page = require(`./pages/${baseKey}`); | ||
|
||
const jsonKey = `_next/data/${manifest.buildId}/${baseKey}.json`; | ||
const htmlKey = `static-pages/${manifest.buildId}/${baseKey}.html`; | ||
|
||
const { renderOpts, html } = await page.renderReqToHTML( | ||
req, | ||
res, | ||
"passthrough" | ||
); | ||
|
||
const s3BasePath = basePath ? `${basePath.replace(/^\//, "")}/` : ""; | ||
const s3JsonParams = { | ||
Bucket: bucketName, | ||
Key: `${s3BasePath}${jsonKey}`, | ||
Body: JSON.stringify(renderOpts.pageData), | ||
ContentType: "application/json", | ||
CacheControl: "public, max-age=0, s-maxage=2678400, must-revalidate" | ||
}; | ||
|
||
const s3HtmlParams = { | ||
Bucket: bucketName, | ||
Key: `${s3BasePath}${htmlKey}`, | ||
Body: html, | ||
ContentType: "text/html", | ||
CacheControl: "public, max-age=0, s-maxage=2678400, must-revalidate" | ||
}; | ||
|
||
const { PutObjectCommand } = await import( | ||
"@aws-sdk/client-s3/commands/PutObjectCommand" | ||
); | ||
await Promise.all([ | ||
s3.send(new PutObjectCommand(s3JsonParams)), | ||
s3.send(new PutObjectCommand(s3HtmlParams)) | ||
]); | ||
}) | ||
); | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.