1
+ /* eslint-disable max-lines */
1
2
import { NetlifyConfig , NetlifyPluginConstants } from '@netlify/build'
2
3
import { copy , copyFile , ensureDir , existsSync , rm , writeFile } from 'fs-extra'
3
4
import { resolve , join , relative } from 'pathe'
4
5
5
6
import { makeApiHandler , makeHandler } from '../templates/handlers'
6
7
7
8
import { getGatsbyRoot } from './config'
9
+ import {
10
+ ImageCdnImplementation ,
11
+ ImageCdnUrlSyntax ,
12
+ type PrepareImageCdnResult ,
13
+ } from './image_cdn'
8
14
9
15
export type FunctionList = Array < 'API' | 'SSR' | 'DSG' >
10
16
@@ -37,16 +43,20 @@ export const writeFunctions = async ({
37
43
constants,
38
44
netlifyConfig,
39
45
neededFunctions,
46
+ prepareImageCdnResult,
40
47
} : {
41
48
constants : NetlifyPluginConstants
42
49
netlifyConfig : NetlifyConfig
43
50
neededFunctions : FunctionList
51
+ prepareImageCdnResult ?: PrepareImageCdnResult
44
52
} ) : Promise < void > => {
45
53
const { PUBLISH_DIR , INTERNAL_FUNCTIONS_SRC } = constants
46
54
const siteRoot = getGatsbyRoot ( PUBLISH_DIR )
47
55
const functionDir = resolve ( INTERNAL_FUNCTIONS_SRC , '__api' )
48
56
const appDir = relative ( functionDir , siteRoot )
49
57
58
+ await ensureDir ( INTERNAL_FUNCTIONS_SRC )
59
+
50
60
if ( neededFunctions . includes ( 'SSR' ) ) {
51
61
await writeFunction ( {
52
62
renderMode : 'SSR' ,
@@ -65,97 +75,158 @@ export const writeFunctions = async ({
65
75
} )
66
76
}
67
77
68
- await setupImageCdn ( { constants, netlifyConfig } )
78
+ if (
79
+ prepareImageCdnResult &&
80
+ prepareImageCdnResult . imageCDNImplementation !== 'NONE'
81
+ ) {
82
+ await setupImageCdn ( { constants, netlifyConfig, prepareImageCdnResult } )
83
+ }
69
84
70
85
if ( neededFunctions . includes ( 'API' ) ) {
71
86
await writeApiFunction ( { appDir, functionDir } )
72
87
}
73
88
}
74
89
90
+ // eslint-disable-next-line max-lines-per-function, complexity
75
91
export const setupImageCdn = async ( {
76
92
constants,
77
93
netlifyConfig,
94
+ prepareImageCdnResult,
78
95
} : {
79
96
constants : NetlifyPluginConstants
80
97
netlifyConfig : NetlifyConfig
98
+ prepareImageCdnResult : PrepareImageCdnResult
81
99
} ) => {
82
- const { GATSBY_CLOUD_IMAGE_CDN , NETLIFY_IMAGE_CDN } =
83
- netlifyConfig . build . environment
84
-
85
- if (
86
- NETLIFY_IMAGE_CDN !== `true` &&
87
- GATSBY_CLOUD_IMAGE_CDN !== '1' &&
88
- GATSBY_CLOUD_IMAGE_CDN !== 'true'
89
- ) {
90
- return
91
- }
92
-
93
- await ensureDir ( constants . INTERNAL_FUNCTIONS_SRC )
94
-
95
- await copyFile (
100
+ await ensureDir ( join ( constants . INTERNAL_FUNCTIONS_SRC , '_ipx' ) )
101
+ await copy (
96
102
join ( __dirname , '..' , '..' , 'src' , 'templates' , 'ipx.ts' ) ,
97
- join ( constants . INTERNAL_FUNCTIONS_SRC , '_ipx.ts' ) ,
103
+ join ( constants . INTERNAL_FUNCTIONS_SRC , '_ipx' , '_ipx.ts' ) ,
104
+ { overwrite : true } ,
98
105
)
99
106
100
- if ( NETLIFY_IMAGE_CDN === `true` ) {
107
+ await writeFile (
108
+ join ( constants . INTERNAL_FUNCTIONS_SRC , '_ipx' , 'config.ts' ) ,
109
+ `exports.config = ${ JSON . stringify ( prepareImageCdnResult . imageCDNConfig ) } ` ,
110
+ )
111
+
112
+ if (
113
+ prepareImageCdnResult . imageCDNImplementation ===
114
+ ImageCdnImplementation . NETLIFY_IMAGE_CDN
115
+ ) {
101
116
await copyFile (
102
117
join ( __dirname , '..' , '..' , 'src' , 'templates' , 'image.ts' ) ,
103
118
join ( constants . INTERNAL_FUNCTIONS_SRC , '__image.ts' ) ,
104
119
)
105
120
106
121
netlifyConfig . redirects . push (
107
- {
108
- from : '/_gatsby/image/:unused/:unused2/:filename' ,
109
- // eslint-disable-next-line id-length
110
- query : { u : ':url' , a : ':args' , cd : ':cd' } ,
111
- to : '/.netlify/functions/__image/image_query_compat?url=:url&args=:args&cd=:cd' ,
112
- status : 301 ,
113
- force : true ,
114
- } ,
115
- {
116
- from : '/_gatsby/image/*' ,
117
- to : '/.netlify/functions/__image' ,
118
- status : 200 ,
119
- force : true ,
120
- } ,
122
+ ...[
123
+ // QUERY_WITH_ENCRYPTED_URL is forcefully disable when using Netlify Image CDN
124
+ // so we don't need to handle it here
125
+ prepareImageCdnResult . imageCDNConfig . enabledUrlPatterns . includes (
126
+ ImageCdnUrlSyntax . QUERY ,
127
+ )
128
+ ? {
129
+ from : '/_gatsby/image/:unused/:unused2/:filename' ,
130
+ // eslint-disable-next-line id-length
131
+ query : { u : ':url' , a : ':args' , cd : ':cd' } ,
132
+ to : '/.netlify/functions/__image/image_query_compat?url=:url&args=:args&cd=:cd' ,
133
+ status : 301 ,
134
+ force : true ,
135
+ }
136
+ : undefined ,
137
+ prepareImageCdnResult . imageCDNConfig . enabledUrlPatterns . includes (
138
+ ImageCdnUrlSyntax . BASE64 ,
139
+ )
140
+ ? {
141
+ from : '/_gatsby/image/*' ,
142
+ to : '/.netlify/functions/__image' ,
143
+ status : 200 ,
144
+ force : true ,
145
+ }
146
+ : undefined ,
147
+ ] . filter ( Boolean ) ,
121
148
)
122
149
} else if (
123
- GATSBY_CLOUD_IMAGE_CDN === '1' ||
124
- GATSBY_CLOUD_IMAGE_CDN === 'true'
150
+ prepareImageCdnResult . imageCDNImplementation === ImageCdnImplementation . IPX
125
151
) {
126
152
netlifyConfig . redirects . push (
127
- {
128
- from : `/_gatsby/image/:unused/:unused2/:filename` ,
129
- // eslint-disable-next-line id-length
130
- query : { u : ':url' , a : ':args' } ,
131
- to : `/.netlify/builders/_ipx/image_query_compat/:args/:url/:filename` ,
132
- status : 301 ,
133
- force : true ,
134
- } ,
135
- {
136
- from : '/_gatsby/image/*' ,
137
- to : '/.netlify/builders/_ipx' ,
138
- status : 200 ,
139
- force : true ,
140
- } ,
153
+ // eslint-disable-next-line no-sparse-arrays
154
+ ...[
155
+ prepareImageCdnResult . imageCDNConfig . enabledUrlPatterns . includes (
156
+ ImageCdnUrlSyntax . QUERY_WITH_ENCRYPTED_URL ,
157
+ )
158
+ ? {
159
+ from : `/_gatsby/image/:unused/:unused2/:filename` ,
160
+ // eslint-disable-next-line id-length
161
+ query : { eu : ':encrypted_url' , a : ':args' } ,
162
+ to : `/.netlify/builders/_ipx/image_query_compat_eu/:args/:encrypted_url/:filename` ,
163
+ status : 301 ,
164
+ force : true ,
165
+ }
166
+ : undefined ,
167
+ prepareImageCdnResult . imageCDNConfig . enabledUrlPatterns . includes (
168
+ ImageCdnUrlSyntax . QUERY ,
169
+ )
170
+ ? {
171
+ from : `/_gatsby/image/:unused/:unused2/:filename` ,
172
+ // eslint-disable-next-line id-length
173
+ query : { u : ':url' , a : ':args' } ,
174
+ to : `/.netlify/builders/_ipx/image_query_compat/:args/:url/:filename` ,
175
+ status : 301 ,
176
+ force : true ,
177
+ }
178
+ : undefined ,
179
+ prepareImageCdnResult . imageCDNConfig . enabledUrlPatterns . includes (
180
+ ImageCdnUrlSyntax . BASE64 ,
181
+ )
182
+ ? {
183
+ from : '/_gatsby/image/*' ,
184
+ to : '/.netlify/builders/_ipx' ,
185
+ status : 200 ,
186
+ force : true ,
187
+ }
188
+ : undefined ,
189
+ ,
190
+ ] . filter ( Boolean ) ,
141
191
)
142
192
}
143
193
144
194
netlifyConfig . redirects . push (
145
- {
146
- from : `/_gatsby/file/:unused/:filename` ,
147
- // eslint-disable-next-line id-length
148
- query : { u : ':url' } ,
149
- to : `/.netlify/functions/_ipx/file_query_compat/:url/:filename` ,
150
- status : 301 ,
151
- force : true ,
152
- } ,
153
- {
154
- from : '/_gatsby/file/*' ,
155
- to : '/.netlify/functions/_ipx' ,
156
- status : 200 ,
157
- force : true ,
158
- } ,
195
+ ...[
196
+ prepareImageCdnResult . imageCDNConfig . enabledUrlPatterns . includes (
197
+ ImageCdnUrlSyntax . QUERY_WITH_ENCRYPTED_URL ,
198
+ )
199
+ ? {
200
+ from : `/_gatsby/file/:unused/:filename` ,
201
+ query : { eu : ':encrypted_url' } ,
202
+ to : `/.netlify/functions/_ipx/file_query_compat_eu/:encrypted_url/:filename` ,
203
+ status : 301 ,
204
+ force : true ,
205
+ }
206
+ : undefined ,
207
+ prepareImageCdnResult . imageCDNConfig . enabledUrlPatterns . includes (
208
+ ImageCdnUrlSyntax . QUERY ,
209
+ )
210
+ ? {
211
+ from : `/_gatsby/file/:unused/:filename` ,
212
+ // eslint-disable-next-line id-length
213
+ query : { u : ':url' } ,
214
+ to : `/.netlify/functions/_ipx/file_query_compat/:url/:filename` ,
215
+ status : 301 ,
216
+ force : true ,
217
+ }
218
+ : undefined ,
219
+ prepareImageCdnResult . imageCDNConfig . enabledUrlPatterns . includes (
220
+ ImageCdnUrlSyntax . BASE64 ,
221
+ )
222
+ ? {
223
+ from : '/_gatsby/file/*' ,
224
+ to : '/.netlify/functions/_ipx' ,
225
+ status : 200 ,
226
+ force : true ,
227
+ }
228
+ : undefined ,
229
+ ] . filter ( Boolean ) ,
159
230
)
160
231
}
161
232
@@ -169,3 +240,4 @@ export const deleteFunctions = async ({
169
240
}
170
241
}
171
242
}
243
+ /* eslint-enable max-lines */
0 commit comments