1
1
import { HttpApi } from '@aws-cdk/aws-apigatewayv2-alpha'
2
2
import { HttpLambdaIntegration } from '@aws-cdk/aws-apigatewayv2-integrations-alpha'
3
- import { AssetHashType , CfnOutput , Duration , RemovalPolicy , Stack , StackProps , SymlinkFollowMode } from 'aws-cdk-lib'
3
+ import { AssetHashType , CfnOutput , Duration , RemovalPolicy , Stack , SymlinkFollowMode } from 'aws-cdk-lib'
4
4
import { CloudFrontAllowedMethods , CloudFrontWebDistribution , ViewerCertificate } from 'aws-cdk-lib/aws-cloudfront'
5
5
import { Code , Function , LayerVersion , Runtime } from 'aws-cdk-lib/aws-lambda'
6
6
import { Bucket , BucketAccessControl } from 'aws-cdk-lib/aws-s3'
@@ -9,58 +9,77 @@ import { Construct } from 'constructs'
9
9
import packageJson from '../package.json'
10
10
11
11
import { imageHandlerZipPath , sharpLayerZipPath , nextLayerZipPath } from './consts'
12
+ import { md5FileSync } from './utils'
12
13
13
- interface NextConstructProps extends StackProps {
14
+ interface NextConstructProps {
15
+ // Required paths, output of pack CLI command.
16
+ codeZipPath : string
17
+ dependenciesZipPath : string
18
+ assetsZipPath : string
19
+ // Optional for additional customizations.
14
20
customServerHandler ?: string
15
21
customImageHandler ?: string
16
-
17
22
cfnViewerCertificate ?: ViewerCertificate
18
-
19
23
imageHandlerZipPath ?: string
20
24
sharpLayerZipPath ?: string
21
25
nextLayerZipPath ?: string
22
- codeZipPath : string
23
- dependenciesZipPath : string
24
- assetsZipPath : string
25
26
}
26
27
27
- export class NextStandaloneStack extends Stack {
28
+ export class NextStandaloneConstruct extends Construct {
28
29
private readonly cfnDistro : CloudFrontWebDistribution
29
30
private readonly serverLambda : Function
30
31
private readonly imageLambda : Function
31
32
private readonly serverApigatewayProxy : HttpApi
32
33
private readonly imageApigatewayProxy : HttpApi
34
+ private readonly region : string
33
35
34
36
constructor ( scope : Construct , id : string , props : NextConstructProps ) {
35
- super ( scope , id , props )
37
+ super ( scope , id )
38
+
39
+ const config = {
40
+ sharpLayerZipPath : sharpLayerZipPath ,
41
+ nextLayerZipPath : nextLayerZipPath ,
42
+ imageHandlerZipPath : imageHandlerZipPath ,
43
+ ...props ,
44
+ }
45
+
46
+ this . region = Stack . of ( scope ) . region
36
47
37
48
const depsLayer = new LayerVersion ( this , 'DepsLayer' , {
38
- code : Code . fromAsset ( props . dependenciesZipPath ) ,
49
+ code : Code . fromAsset ( props . dependenciesZipPath , {
50
+ assetHash : md5FileSync ( props . dependenciesZipPath ) ,
51
+ assetHashType : AssetHashType . CUSTOM ,
52
+ } ) ,
39
53
} )
40
54
41
55
const sharpLayer = new LayerVersion ( this , 'SharpLayer' , {
42
- code : Code . fromAsset ( props . sharpLayerZipPath ?? sharpLayerZipPath , {
43
- assetHash : `static-sharp- ${ packageJson . version } ` ,
56
+ code : Code . fromAsset ( config . sharpLayerZipPath , {
57
+ assetHash : md5FileSync ( config . sharpLayerZipPath ) ,
44
58
assetHashType : AssetHashType . CUSTOM ,
45
59
} ) ,
46
60
} )
47
61
48
62
const nextLayer = new LayerVersion ( this , 'NextLayer' , {
49
- code : Code . fromAsset ( props . nextLayerZipPath ?? nextLayerZipPath , {
50
- assetHash : `static-next- ${ packageJson . version } ` ,
63
+ code : Code . fromAsset ( config . nextLayerZipPath , {
64
+ assetHash : md5FileSync ( config . nextLayerZipPath ) ,
51
65
assetHashType : AssetHashType . CUSTOM ,
52
66
} ) ,
53
67
} )
54
68
55
69
const assetsBucket = new Bucket ( this , 'NextAssetsBucket' , {
70
+ // Those settings are necessary for bucket to be removed on stack removal.
71
+ removalPolicy : RemovalPolicy . DESTROY ,
72
+ autoDeleteObjects : true ,
56
73
// @NOTE : Considering not having public ACL.
57
74
publicReadAccess : true ,
58
- autoDeleteObjects : true ,
59
- removalPolicy : RemovalPolicy . DESTROY ,
60
75
} )
61
76
62
77
this . serverLambda = new Function ( this , 'DefaultNextJs' , {
63
- code : Code . fromAsset ( props . codeZipPath , { followSymlinks : SymlinkFollowMode . NEVER } ) ,
78
+ code : Code . fromAsset ( config . codeZipPath , {
79
+ followSymlinks : SymlinkFollowMode . NEVER ,
80
+ assetHash : md5FileSync ( config . codeZipPath ) ,
81
+ assetHashType : AssetHashType . CUSTOM ,
82
+ } ) ,
64
83
runtime : Runtime . NODEJS_16_X ,
65
84
handler : props . customServerHandler ?? 'handler.handler' ,
66
85
layers : [ depsLayer , nextLayer ] ,
@@ -70,7 +89,10 @@ export class NextStandaloneStack extends Stack {
70
89
} )
71
90
72
91
this . imageLambda = new Function ( this , 'ImageOptimizationNextJs' , {
73
- code : Code . fromAsset ( props . imageHandlerZipPath ?? imageHandlerZipPath ) ,
92
+ code : Code . fromAsset ( config . imageHandlerZipPath , {
93
+ assetHash : md5FileSync ( config . imageHandlerZipPath ) ,
94
+ assetHashType : AssetHashType . CUSTOM ,
95
+ } ) ,
74
96
runtime : Runtime . NODEJS_16_X ,
75
97
handler : props . customImageHandler ?? 'index.handler' ,
76
98
layers : [ sharpLayer , nextLayer ] ,
@@ -152,18 +174,24 @@ export class NextStandaloneStack extends Stack {
152
174
// This can be handled by `aws s3 sync` but we need to ensure invalidation of Cfn after deploy.
153
175
new BucketDeployment ( this , 'PublicFilesDeployment' , {
154
176
destinationBucket : assetsBucket ,
155
- sources : [ Source . asset ( props . assetsZipPath ) ] ,
156
177
accessControl : BucketAccessControl . PUBLIC_READ ,
178
+ sources : [
179
+ Source . asset ( config . assetsZipPath , {
180
+ assetHashType : AssetHashType . CUSTOM ,
181
+ assetHash : md5FileSync ( config . assetsZipPath ) ,
182
+ } ) ,
183
+ ] ,
157
184
// Invalidate all paths after deployment.
158
- distributionPaths : [ '/*' ] ,
159
185
distribution : this . cfnDistro ,
186
+ distributionPaths : [ '/*' ] ,
160
187
} )
161
188
162
189
new CfnOutput ( this , 'cfnDistroUrl' , { value : this . cfnDistro . distributionDomainName } )
163
190
new CfnOutput ( this , 'cfnDistroId' , { value : this . cfnDistro . distributionId } )
164
191
new CfnOutput ( this , 'defaultApiGwUrl' , { value : this . serverApigatewayProxy . apiEndpoint } )
165
192
new CfnOutput ( this , 'imagesApiGwUrl' , { value : this . imageApigatewayProxy . apiEndpoint } )
166
193
new CfnOutput ( this , 'assetsBucketUrl' , { value : assetsBucket . bucketDomainName } )
194
+ new CfnOutput ( this , 'nextConstructRegion' , { value : this . region } )
167
195
}
168
196
169
197
get cloudfrontDistribution ( ) {
0 commit comments