Skip to content

Commit c172324

Browse files
salzhranigregberge
authored andcommitted
feat(server): support function in attributes (#277)
1 parent 79133eb commit c172324

File tree

3 files changed

+159
-38
lines changed

3 files changed

+159
-38
lines changed

packages/server/src/ChunkExtractor.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@ function getAssets(chunks, getAsset) {
2020
return _.uniqBy(_.flatMap(chunks, chunk => getAsset(chunk)), 'url')
2121
}
2222

23-
function extraPropsToString(extraProps) {
24-
return Object.keys(extraProps).reduce(
25-
(acc, key) => `${acc} ${key}="${extraProps[key]}"`,
23+
function handleExtraProps(asset, extraProps) {
24+
return typeof extraProps === 'function' ? extraProps(asset) : extraProps
25+
}
26+
27+
function extraPropsToString(asset, extraProps) {
28+
return Object.entries(handleExtraProps(asset, extraProps)).reduce(
29+
(acc, [key, value]) => `${acc} ${key}="${value}"`,
2630
'',
2731
)
2832
}
2933

3034
function assetToScriptTag(asset, extraProps) {
3135
return `<script async data-chunk="${asset.chunk}" src="${
3236
asset.url
33-
}"${extraPropsToString(extraProps)}></script>`
37+
}"${extraPropsToString(asset, extraProps)}></script>`
3438
}
3539

3640
function assetToScriptElement(asset, extraProps) {
@@ -40,7 +44,7 @@ function assetToScriptElement(asset, extraProps) {
4044
async
4145
data-chunk={asset.chunk}
4246
src={asset.url}
43-
{...extraProps}
47+
{...handleExtraProps(asset, extraProps)}
4448
/>
4549
)
4650
}
@@ -60,7 +64,7 @@ function assetToStyleString(asset) {
6064
function assetToStyleTag(asset, extraProps) {
6165
return `<link data-chunk="${asset.chunk}" rel="stylesheet" href="${
6266
asset.url
63-
}"${extraPropsToString(extraProps)}>`
67+
}"${extraPropsToString(asset, extraProps)}>`
6468
}
6569

6670
function assetToStyleTagInline(asset, extraProps) {
@@ -72,6 +76,7 @@ function assetToStyleTagInline(asset, extraProps) {
7276
}
7377
resolve(
7478
`<style type="text/css" data-chunk="${asset.chunk}"${extraPropsToString(
79+
asset,
7580
extraProps,
7681
)}>
7782
${data}
@@ -88,7 +93,7 @@ function assetToStyleElement(asset, extraProps) {
8893
data-chunk={asset.chunk}
8994
rel="stylesheet"
9095
href={asset.url}
91-
{...extraProps}
96+
{...handleExtraProps(asset, extraProps)}
9297
/>
9398
)
9499
}
@@ -105,7 +110,7 @@ function assetToStyleElementInline(asset, extraProps) {
105110
key={asset.url}
106111
data-chunk={asset.chunk}
107112
dangerouslySetInnerHTML={{ __html: data }}
108-
{...extraProps}
113+
{...handleExtraProps(asset, extraProps)}
109114
/>,
110115
)
111116
})
@@ -121,7 +126,7 @@ function assetToLinkTag(asset, extraProps) {
121126
const hint = LINK_ASSET_HINTS[asset.type]
122127
return `<link ${hint}="${asset.chunk}" rel="${asset.linkType}" as="${
123128
asset.scriptType
124-
}" href="${asset.url}"${extraPropsToString(extraProps)}>`
129+
}" href="${asset.url}"${extraPropsToString(asset, extraProps)}>`
125130
}
126131

127132
function assetToLinkElement(asset, extraProps) {
@@ -132,7 +137,7 @@ function assetToLinkElement(asset, extraProps) {
132137
rel: asset.linkType,
133138
as: asset.scriptType,
134139
href: asset.url,
135-
...extraProps,
140+
...handleExtraProps(asset, extraProps),
136141
}
137142
return <link {...props} />
138143
}
@@ -248,6 +253,7 @@ class ChunkExtractor {
248253

249254
getRequiredChunksScriptTag(extraProps) {
250255
return `<script id="${LOADABLE_REQUIRED_CHUNKS_KEY}" type="application/json"${extraPropsToString(
256+
null,
251257
extraProps,
252258
)}>${this.getRequiredChunksScriptContent()}</script>`
253259
}
@@ -261,7 +267,7 @@ class ChunkExtractor {
261267
dangerouslySetInnerHTML={{
262268
__html: this.getRequiredChunksScriptContent(),
263269
}}
264-
{...extraProps}
270+
{...handleExtraProps(null, extraProps)}
265271
/>
266272
)
267273
}

packages/server/src/ChunkExtractor.test.js

Lines changed: 121 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,26 @@ describe('ChunkExtrator', () => {
6666
`)
6767
})
6868

69-
it('should add extra props if specified', () => {
69+
it('should add extra props if specified - object argument', () => {
7070
extractor.addChunk('letters-A')
7171
expect(extractor.getScriptTags({ nonce: 'testnonce' }))
7272
.toMatchInlineSnapshot(`
7373
"<script id=\\"__LOADABLE_REQUIRED_CHUNKS__\\" type=\\"application/json\\" nonce=\\"testnonce\\">[\\"letters-A\\"]</script>
7474
<script async data-chunk=\\"main\\" src=\\"/dist/node/main.js\\" nonce=\\"testnonce\\"></script>
7575
<script async data-chunk=\\"letters-A\\" src=\\"/dist/node/letters-A.js\\" nonce=\\"testnonce\\"></script>"
76+
`)
77+
})
78+
79+
it('should add extra props if specified - function argument', () => {
80+
extractor.addChunk('letters-A')
81+
expect(
82+
extractor.getScriptTags(asset => {
83+
return { nonce: asset ? asset.chunk : 'anonymous' }
84+
}),
85+
).toMatchInlineSnapshot(`
86+
"<script id=\\"__LOADABLE_REQUIRED_CHUNKS__\\" type=\\"application/json\\" nonce=\\"anonymous\\">[\\"letters-A\\"]</script>
87+
<script async data-chunk=\\"main\\" src=\\"/dist/node/main.js\\" nonce=\\"main\\"></script>
88+
<script async data-chunk=\\"letters-A\\" src=\\"/dist/node/letters-A.js\\" nonce=\\"letters-A\\"></script>"
7689
`)
7790
})
7891
})
@@ -153,7 +166,7 @@ Array [
153166
`)
154167
})
155168

156-
it('should add extra props if specified', () => {
169+
it('should add extra props if specified - object argument', () => {
157170
extractor.addChunk('letters-A')
158171
expect(extractor.getScriptElements({ nonce: 'testnonce' }))
159172
.toMatchInlineSnapshot(`
@@ -181,6 +194,40 @@ Array [
181194
src="/dist/node/letters-A.js"
182195
/>,
183196
]
197+
`)
198+
})
199+
200+
it('should add extra props if specified - function argument', () => {
201+
extractor.addChunk('letters-A')
202+
expect(
203+
extractor.getScriptElements(asset => {
204+
return { nonce: asset ? asset.chunk : 'anonymous' }
205+
}),
206+
).toMatchInlineSnapshot(`
207+
Array [
208+
<script
209+
dangerouslySetInnerHTML={
210+
Object {
211+
"__html": "[\\"letters-A\\"]",
212+
}
213+
}
214+
id="__LOADABLE_REQUIRED_CHUNKS__"
215+
nonce="anonymous"
216+
type="application/json"
217+
/>,
218+
<script
219+
async={true}
220+
data-chunk="main"
221+
nonce="main"
222+
src="/dist/node/main.js"
223+
/>,
224+
<script
225+
async={true}
226+
data-chunk="letters-A"
227+
nonce="letters-A"
228+
src="/dist/node/letters-A.js"
229+
/>,
230+
]
184231
`)
185232
})
186233
})
@@ -208,12 +255,24 @@ Array [
208255
`)
209256
})
210257

211-
it('should add extraProps if specified', () => {
258+
it('should add extraProps if specified - object argument', () => {
212259
extractor.addChunk('letters-A')
213260
expect(extractor.getStyleTags({ nonce: 'testnonce' }))
214261
.toMatchInlineSnapshot(`
215262
"<link data-chunk=\\"main\\" rel=\\"stylesheet\\" href=\\"/dist/node/main.css\\" nonce=\\"testnonce\\">
216263
<link data-chunk=\\"letters-A\\" rel=\\"stylesheet\\" href=\\"/dist/node/letters-A.css\\" nonce=\\"testnonce\\">"
264+
`)
265+
})
266+
267+
it('should add extraProps if specified - function argument', () => {
268+
extractor.addChunk('letters-A')
269+
expect(
270+
extractor.getStyleTags(asset => ({
271+
nonce: asset ? asset.chunk : 'anonymous',
272+
})),
273+
).toMatchInlineSnapshot(`
274+
"<link data-chunk=\\"main\\" rel=\\"stylesheet\\" href=\\"/dist/node/main.css\\" nonce=\\"main\\">
275+
<link data-chunk=\\"letters-A\\" rel=\\"stylesheet\\" href=\\"/dist/node/letters-A.css\\" nonce=\\"letters-A\\">"
217276
`)
218277
})
219278
})
@@ -239,7 +298,7 @@ body {
239298
)
240299
})
241300

242-
it('should add extraProps if specified', () => {
301+
it('should add extraProps if specified - object argument', () => {
243302
extractor.addChunk('letters-A')
244303
expect.assertions(1)
245304
return extractor.getInlineStyleTags({ nonce: 'testnonce' }).then(data =>
@@ -258,6 +317,28 @@ body {
258317
`),
259318
)
260319
})
320+
321+
it('should add extraProps if specified - function argument', () => {
322+
extractor.addChunk('letters-A')
323+
expect.assertions(1)
324+
return extractor
325+
.getInlineStyleTags(asset => ({ nonce: asset.chunk }))
326+
.then(data =>
327+
expect(data).toMatchInlineSnapshot(`
328+
"<style type=\\"text/css\\" data-chunk=\\"main\\" nonce=\\"main\\">
329+
h1 {
330+
color: cyan;
331+
}
332+
</style>
333+
<style type=\\"text/css\\" data-chunk=\\"letters-A\\" nonce=\\"letters-A\\">
334+
body {
335+
background: pink;
336+
}
337+
338+
</style>"
339+
`),
340+
)
341+
})
261342
})
262343

263344
describe('#getStyleElements', () => {
@@ -309,7 +390,7 @@ Array [
309390
`)
310391
})
311392

312-
it('should add extraProps if specified', () => {
393+
it('should add extraProps if specified - object argument', () => {
313394
extractor.addChunk('letters-A')
314395
expect(extractor.getStyleElements({ nonce: 'testnonce' }))
315396
.toMatchInlineSnapshot(`
@@ -327,6 +408,27 @@ Array [
327408
rel="stylesheet"
328409
/>,
329410
]
411+
`)
412+
})
413+
414+
it('should add extraProps if specified - function argument', () => {
415+
extractor.addChunk('letters-A')
416+
expect(extractor.getStyleElements(asset => ({ nonce: asset.chunk })))
417+
.toMatchInlineSnapshot(`
418+
Array [
419+
<link
420+
data-chunk="main"
421+
href="/dist/node/main.css"
422+
nonce="main"
423+
rel="stylesheet"
424+
/>,
425+
<link
426+
data-chunk="letters-A"
427+
href="/dist/node/letters-A.css"
428+
nonce="letters-A"
429+
rel="stylesheet"
430+
/>,
431+
]
330432
`)
331433
})
332434
})
@@ -417,7 +519,7 @@ body {
417519
`)
418520
})
419521

420-
it('should add extraProps if specified', () => {
522+
it('should add extraProps if specified - object argument', () => {
421523
extractor.addChunk('letters-A')
422524
expect(extractor.getLinkTags({ nonce: 'testnonce' }))
423525
.toMatchInlineSnapshot(`
@@ -427,6 +529,19 @@ body {
427529
<link data-chunk=\\"letters-A\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/letters-A.js\\" nonce=\\"testnonce\\">
428530
<link data-parent-chunk=\\"main\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/letters-C.js\\" nonce=\\"testnonce\\">
429531
<link data-parent-chunk=\\"main\\" rel=\\"prefetch\\" as=\\"script\\" href=\\"/dist/node/letters-D.js\\" nonce=\\"testnonce\\">"
532+
`)
533+
})
534+
535+
it('should add extraProps if specified - function argument', () => {
536+
extractor.addChunk('letters-A')
537+
expect(extractor.getLinkTags(asset => ({ nonce: asset.chunk })))
538+
.toMatchInlineSnapshot(`
539+
"<link data-chunk=\\"main\\" rel=\\"preload\\" as=\\"style\\" href=\\"/dist/node/main.css\\" nonce=\\"main\\">
540+
<link data-chunk=\\"main\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/main.js\\" nonce=\\"main\\">
541+
<link data-chunk=\\"letters-A\\" rel=\\"preload\\" as=\\"style\\" href=\\"/dist/node/letters-A.css\\" nonce=\\"letters-A\\">
542+
<link data-chunk=\\"letters-A\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/letters-A.js\\" nonce=\\"letters-A\\">
543+
<link data-parent-chunk=\\"main\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/letters-C.js\\" nonce=\\"main\\">
544+
<link data-parent-chunk=\\"main\\" rel=\\"prefetch\\" as=\\"script\\" href=\\"/dist/node/letters-D.js\\" nonce=\\"main\\">"
430545
`)
431546
})
432547
})

0 commit comments

Comments
 (0)