@@ -7,19 +7,25 @@ import {
7
7
SERVER_NO_CACHE_CACHE_CONTROL_HEADER ,
8
8
SERVER_CACHE_CONTROL_HEADER
9
9
} from "./lib/constants" ;
10
+ import getPageName from "./lib/getPageName" ;
10
11
import S3ClientFactory , { Credentials } from "./lib/s3" ;
11
12
import pathToPosix from "./lib/pathToPosix" ;
12
- import { PrerenderManifest } from "next/dist/build/index" ;
13
+ import { PrerenderManifest , SsgRoute } from "next/dist/build/index" ;
13
14
import getPublicAssetCacheControl , {
14
15
PublicDirectoryCache
15
16
} from "./lib/getPublicAssetCacheControl" ;
16
17
18
+ type PrerenderRoutes = {
19
+ [ path : string ] : SsgRoute ;
20
+ } ;
21
+
17
22
type UploadStaticAssetsOptions = {
18
23
bucketName : string ;
19
24
basePath : string ;
20
25
nextConfigDir : string ;
21
26
nextStaticDir ?: string ;
22
27
credentials : Credentials ;
28
+ prerenderRoutes ?: PrerenderRoutes ;
23
29
publicDirectoryCache ?: PublicDirectoryCache ;
24
30
} ;
25
31
@@ -29,6 +35,7 @@ type AssetDirectoryFileCachePoliciesOptions = {
29
35
// .i.e. by default .serverless_nextjs
30
36
serverlessBuildOutDir : string ;
31
37
nextStaticDir ?: string ;
38
+ prerenderRoutes : PrerenderRoutes ;
32
39
publicDirectoryCache ?: PublicDirectoryCache ;
33
40
} ;
34
41
@@ -38,13 +45,19 @@ type AssetDirectoryFileCachePoliciesOptions = {
38
45
const getAssetDirectoryFileCachePolicies = (
39
46
options : AssetDirectoryFileCachePoliciesOptions
40
47
) : Array < {
41
- cacheControl : string | undefined ;
48
+ cacheControl ?: string ;
49
+ expires ?: Date ;
42
50
path : {
43
51
relative : string ;
44
52
absolute : string ;
45
53
} ;
46
54
} > => {
47
- const { basePath, publicDirectoryCache, serverlessBuildOutDir } = options ;
55
+ const {
56
+ basePath,
57
+ prerenderRoutes,
58
+ publicDirectoryCache,
59
+ serverlessBuildOutDir
60
+ } = options ;
48
61
49
62
const normalizedBasePath = basePath ? basePath . slice ( 1 ) : "" ;
50
63
@@ -75,20 +88,39 @@ const getAssetDirectoryFileCachePolicies = (
75
88
76
89
// Upload Next.js data files
77
90
78
- const nextDataFiles = readDirectoryFiles (
79
- path . join ( assetsOutputDirectory , normalizedBasePath , "_next" , "data" )
91
+ const nextDataDir = path . join (
92
+ assetsOutputDirectory ,
93
+ normalizedBasePath ,
94
+ "_next" ,
95
+ "data"
80
96
) ;
97
+ const nextDataFiles = readDirectoryFiles ( nextDataDir ) ;
81
98
82
- const nextDataFilesUploads = nextDataFiles . map ( ( fileItem ) => ( {
83
- path : fileItem . path ,
84
- cacheControl : SERVER_CACHE_CONTROL_HEADER
85
- } ) ) ;
99
+ const nextDataFilesUploads = nextDataFiles . map ( ( fileItem ) => {
100
+ const route = prerenderRoutes [ getPageName ( fileItem . path , nextDataDir ) ] ;
101
+ if ( route && route . initialRevalidateSeconds ) {
102
+ const expires = new Date (
103
+ new Date ( ) . getTime ( ) + 1000 * route . initialRevalidateSeconds
104
+ ) ;
105
+ return {
106
+ path : fileItem . path ,
107
+ expires
108
+ } ;
109
+ }
110
+ return {
111
+ path : fileItem . path ,
112
+ cacheControl : SERVER_CACHE_CONTROL_HEADER
113
+ } ;
114
+ } ) ;
86
115
87
116
// Upload Next.js HTML pages
88
117
89
- const htmlPages = readDirectoryFiles (
90
- path . join ( assetsOutputDirectory , normalizedBasePath , "static-pages" )
118
+ const htmlDir = path . join (
119
+ assetsOutputDirectory ,
120
+ normalizedBasePath ,
121
+ "static-pages"
91
122
) ;
123
+ const htmlPages = readDirectoryFiles ( htmlDir ) ;
92
124
93
125
const htmlPagesUploads = htmlPages . map ( ( fileItem ) => {
94
126
// Dynamic fallback HTML pages should never be cached as it will override actual pages once generated and stored in S3.
@@ -98,12 +130,23 @@ const getAssetDirectoryFileCachePolicies = (
98
130
path : fileItem . path ,
99
131
cacheControl : SERVER_NO_CACHE_CACHE_CONTROL_HEADER
100
132
} ;
101
- } else {
133
+ }
134
+
135
+ const route = prerenderRoutes [ getPageName ( fileItem . path , htmlDir ) ] ;
136
+ if ( route && route . initialRevalidateSeconds ) {
137
+ const expires = new Date (
138
+ new Date ( ) . getTime ( ) + 1000 * route . initialRevalidateSeconds
139
+ ) ;
102
140
return {
103
141
path : fileItem . path ,
104
- cacheControl : SERVER_CACHE_CONTROL_HEADER
142
+ expires
105
143
} ;
106
144
}
145
+
146
+ return {
147
+ path : fileItem . path ,
148
+ cacheControl : SERVER_CACHE_CONTROL_HEADER
149
+ } ;
107
150
} ) ;
108
151
109
152
// Upload user static and public files
@@ -132,14 +175,14 @@ const getAssetDirectoryFileCachePolicies = (
132
175
...htmlPagesUploads ,
133
176
...publicAndStaticUploads ,
134
177
buildIdUpload
135
- ] . map ( ( { cacheControl, path : absolutePath } ) => ( {
136
- cacheControl,
178
+ ] . map ( ( { path : absolutePath , ...rest } ) => ( {
137
179
path : {
138
180
// Path relative to the assets folder, used for the S3 upload key
139
181
relative : path . relative ( assetsOutputDirectory , absolutePath ) ,
140
182
// Absolute path of local asset
141
183
absolute : absolutePath
142
- }
184
+ } ,
185
+ ...rest
143
186
} ) ) ;
144
187
} ;
145
188
@@ -155,11 +198,14 @@ const uploadStaticAssetsFromBuild = async (
155
198
bucketName,
156
199
credentials,
157
200
basePath,
201
+ prerenderRoutes,
158
202
publicDirectoryCache,
159
203
nextConfigDir
160
204
} = options ;
205
+
161
206
const files = getAssetDirectoryFileCachePolicies ( {
162
207
basePath,
208
+ prerenderRoutes : prerenderRoutes ?? { } ,
163
209
publicDirectoryCache,
164
210
serverlessBuildOutDir : path . join ( nextConfigDir , ".serverless_nextjs" )
165
211
} ) ;
@@ -173,7 +219,8 @@ const uploadStaticAssetsFromBuild = async (
173
219
s3 . uploadFile ( {
174
220
s3Key : pathToPosix ( file . path . relative ) ,
175
221
filePath : file . path . absolute ,
176
- cacheControl : file . cacheControl
222
+ cacheControl : file . cacheControl ,
223
+ expires : file . expires
177
224
} )
178
225
)
179
226
) ;
0 commit comments