Skip to content

Commit 8a3d067

Browse files
nchauletgregberge
authored andcommitted
feat: allow to specify extra attributes in getScriptTags & others (#210)
1 parent 210b1ef commit 8a3d067

File tree

2 files changed

+123
-27
lines changed

2 files changed

+123
-27
lines changed

packages/server/src/ChunkExtractor.js

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

23-
function assetToScriptTag(asset) {
23+
function extraPropsToString(extraProps) {
24+
return Object.keys(extraProps).reduce((acc, key) => `${acc} ${key}="${extraProps[key]}"`, '');
25+
}
26+
27+
function assetToScriptTag(asset, extraProps) {
2428
return `<script async data-chunk="${asset.chunk}" src="${
2529
asset.url
26-
}"></script>`
30+
}"${extraPropsToString(extraProps)}></script>`
2731
}
2832

29-
function assetToScriptElement(asset) {
33+
function assetToScriptElement(asset, extraProps) {
3034
return (
31-
<script key={asset.url} async data-chunk={asset.chunk} src={asset.url} />
35+
<script key={asset.url} async data-chunk={asset.chunk} src={asset.url} {...extraProps} />
3236
)
3337
}
3438

@@ -44,40 +48,41 @@ function assetToStyleString(asset) {
4448
})
4549
}
4650

47-
function assetToStyleTag(asset) {
51+
function assetToStyleTag(asset, extraProps) {
4852
return `<link data-chunk="${asset.chunk}" rel="stylesheet" href="${
4953
asset.url
50-
}">`
54+
}"${extraPropsToString(extraProps)}>`
5155
}
5256

53-
function assetToStyleTagInline(asset) {
57+
function assetToStyleTagInline(asset, extraProps) {
5458
return new Promise((resolve, reject) => {
5559
fs.readFile(asset.path, 'utf8', (err, data) => {
5660
if (err) {
5761
reject(err)
5862
return
5963
}
6064
resolve(
61-
`<style type="text/css" data-chunk="${asset.chunk}">
65+
`<style type="text/css" data-chunk="${asset.chunk}"${extraPropsToString(extraProps)}>
6266
${data}
6367
</style>`,
6468
)
6569
})
6670
})
6771
}
6872

69-
function assetToStyleElement(asset) {
73+
function assetToStyleElement(asset, extraProps) {
7074
return (
7175
<link
7276
key={asset.url}
7377
data-chunk={asset.chunk}
7478
rel="stylesheet"
7579
href={asset.url}
80+
{...extraProps}
7681
/>
7782
)
7883
}
7984

80-
function assetToStyleElementInline(asset) {
85+
function assetToStyleElementInline(asset, extraProps) {
8186
return new Promise((resolve, reject) => {
8287
fs.readFile(asset.path, 'utf8', (err, data) => {
8388
if (err) {
@@ -89,6 +94,7 @@ function assetToStyleElementInline(asset) {
8994
key={asset.url}
9095
data-chunk={asset.chunk}
9196
dangerouslySetInnerHTML={{ __html: data }}
97+
{...extraProps}
9298
/>,
9399
)
94100
})
@@ -225,17 +231,18 @@ class ChunkExtractor {
225231
)};`
226232
}
227233

228-
getRequiredChunksScriptTag() {
229-
return `<script>${this.getRequiredChunksScriptContent()}</script>`
234+
getRequiredChunksScriptTag(extraProps) {
235+
return `<script${extraPropsToString(extraProps)}>${this.getRequiredChunksScriptContent()}</script>`
230236
}
231237

232-
getRequiredChunksScriptElement() {
238+
getRequiredChunksScriptElement(extraProps) {
233239
return (
234240
<script
235241
key="required"
236242
dangerouslySetInnerHTML={{
237243
__html: this.getRequiredChunksScriptContent(),
238244
}}
245+
{...extraProps}
239246
/>
240247
)
241248
}
@@ -275,18 +282,18 @@ class ChunkExtractor {
275282
return assets
276283
}
277284

278-
getScriptTags() {
279-
const requiredScriptTag = this.getRequiredChunksScriptTag()
285+
getScriptTags(extraProps = {}) {
286+
const requiredScriptTag = this.getRequiredChunksScriptTag(extraProps)
280287
const mainAssets = this.getMainAssets('script')
281-
const assetsScriptTags = mainAssets.map(asset => assetToScriptTag(asset))
288+
const assetsScriptTags = mainAssets.map(asset => assetToScriptTag(asset, extraProps))
282289
return joinTags([requiredScriptTag, ...assetsScriptTags])
283290
}
284291

285-
getScriptElements() {
286-
const requiredScriptElement = this.getRequiredChunksScriptElement()
292+
getScriptElements(extraProps = {}) {
293+
const requiredScriptElement = this.getRequiredChunksScriptElement(extraProps)
287294
const mainAssets = this.getMainAssets('script')
288295
const assetsScriptElements = mainAssets.map(asset =>
289-
assetToScriptElement(asset),
296+
assetToScriptElement(asset, extraProps),
290297
)
291298
return [requiredScriptElement, ...assetsScriptElements]
292299
}
@@ -299,28 +306,28 @@ class ChunkExtractor {
299306
return Promise.all(promises).then(results => joinTags(results))
300307
}
301308

302-
getStyleTags() {
309+
getStyleTags(extraProps = {}) {
303310
const mainAssets = this.getMainAssets('style')
304-
return joinTags(mainAssets.map(asset => assetToStyleTag(asset)))
311+
return joinTags(mainAssets.map(asset => assetToStyleTag(asset, extraProps)))
305312
}
306313

307-
getInlineStyleTags() {
314+
getInlineStyleTags(extraProps = {}) {
308315
const mainAssets = this.getMainAssets('style')
309316
const promises = mainAssets.map(asset =>
310-
assetToStyleTagInline(asset).then(data => data),
317+
assetToStyleTagInline(asset, extraProps).then(data => data),
311318
)
312319
return Promise.all(promises).then(results => joinTags(results))
313320
}
314321

315-
getStyleElements() {
322+
getStyleElements(extraProps = {}) {
316323
const mainAssets = this.getMainAssets('style')
317-
return mainAssets.map(asset => assetToStyleElement(asset))
324+
return mainAssets.map(asset => assetToStyleElement(asset, extraProps))
318325
}
319326

320-
getInlineStyleElements() {
327+
getInlineStyleElements(extraProps = {}) {
321328
const mainAssets = this.getMainAssets('style')
322329
const promises = mainAssets.map(asset =>
323-
assetToStyleElementInline(asset).then(data => data),
330+
assetToStyleElementInline(asset, extraProps).then(data => data),
324331
)
325332
return Promise.all(promises).then(results => results)
326333
}

packages/server/src/ChunkExtractor.test.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ describe('ChunkExtrator', () => {
5454
"<script>window.__LOADABLE_REQUIRED_CHUNKS__ = [\\"letters-A\\"];</script>
5555
<script async data-chunk=\\"letters-A\\" src=\\"/dist/node/letters-A.js\\"></script>
5656
<script async data-chunk=\\"main\\" src=\\"/dist/node/main.js\\"></script>"
57+
`)
58+
})
59+
60+
it('should add extra props if specified', () => {
61+
extractor.addChunk('letters-A')
62+
expect(extractor.getScriptTags({ nonce: 'testnonce' }))
63+
.toMatchInlineSnapshot(`
64+
"<script nonce=\\"testnonce\\">window.__LOADABLE_REQUIRED_CHUNKS__ = [\\"letters-A\\"];</script>
65+
<script async data-chunk=\\"letters-A\\" src=\\"/dist/node/letters-A.js\\" nonce=\\"testnonce\\"></script>
66+
<script async data-chunk=\\"main\\" src=\\"/dist/node/main.js\\" nonce=\\"testnonce\\"></script>"
5767
`)
5868
})
5969
})
@@ -100,6 +110,35 @@ Array [
100110
src="/dist/node/main.js"
101111
/>,
102112
]
113+
`)
114+
})
115+
116+
it('should add extra props if specified', () => {
117+
extractor.addChunk('letters-A')
118+
expect(extractor.getScriptElements({ nonce: 'testnonce' }))
119+
.toMatchInlineSnapshot(`
120+
Array [
121+
<script
122+
dangerouslySetInnerHTML={
123+
Object {
124+
"__html": "window.__LOADABLE_REQUIRED_CHUNKS__ = [\\"letters-A\\"];",
125+
}
126+
}
127+
nonce="testnonce"
128+
/>,
129+
<script
130+
async={true}
131+
data-chunk="letters-A"
132+
nonce="testnonce"
133+
src="/dist/node/letters-A.js"
134+
/>,
135+
<script
136+
async={true}
137+
data-chunk="main"
138+
nonce="testnonce"
139+
src="/dist/node/main.js"
140+
/>,
141+
]
103142
`)
104143
})
105144
})
@@ -116,6 +155,15 @@ Array [
116155
expect(extractor.getStyleTags()).toMatchInlineSnapshot(`
117156
"<link data-chunk=\\"letters-A\\" rel=\\"stylesheet\\" href=\\"/dist/node/letters-A.css\\">
118157
<link data-chunk=\\"main\\" rel=\\"stylesheet\\" href=\\"/dist/node/main.css\\">"
158+
`)
159+
})
160+
161+
it('should add extraProps if specified', () => {
162+
extractor.addChunk('letters-A')
163+
expect(extractor.getStyleTags({ nonce: 'testnonce' }))
164+
.toMatchInlineSnapshot(`
165+
"<link data-chunk=\\"letters-A\\" rel=\\"stylesheet\\" href=\\"/dist/node/letters-A.css\\" nonce=\\"testnonce\\">
166+
<link data-chunk=\\"main\\" rel=\\"stylesheet\\" href=\\"/dist/node/main.css\\" nonce=\\"testnonce\\">"
119167
`)
120168
})
121169
})
@@ -137,6 +185,26 @@ h1 {
137185
color: cyan;
138186
}
139187
</style>"
188+
`),
189+
)
190+
})
191+
192+
it('should add extraProps if specified', () => {
193+
extractor.addChunk('letters-A')
194+
expect.assertions(1)
195+
return extractor.getInlineStyleTags({ nonce: 'testnonce' }).then(data =>
196+
expect(data).toMatchInlineSnapshot(`
197+
"<style type=\\"text/css\\" data-chunk=\\"letters-A\\" nonce=\\"testnonce\\">
198+
body {
199+
background: pink;
200+
}
201+
202+
</style>
203+
<style type=\\"text/css\\" data-chunk=\\"main\\" nonce=\\"testnonce\\">
204+
h1 {
205+
color: cyan;
206+
}
207+
</style>"
140208
`),
141209
)
142210
})
@@ -170,6 +238,27 @@ Array [
170238
rel="stylesheet"
171239
/>,
172240
]
241+
`)
242+
})
243+
244+
it('should add extraProps if specified', () => {
245+
extractor.addChunk('letters-A')
246+
expect(extractor.getStyleElements({ nonce: 'testnonce' }))
247+
.toMatchInlineSnapshot(`
248+
Array [
249+
<link
250+
data-chunk="letters-A"
251+
href="/dist/node/letters-A.css"
252+
nonce="testnonce"
253+
rel="stylesheet"
254+
/>,
255+
<link
256+
data-chunk="main"
257+
href="/dist/node/main.css"
258+
nonce="testnonce"
259+
rel="stylesheet"
260+
/>,
261+
]
173262
`)
174263
})
175264
})

0 commit comments

Comments
 (0)