Skip to content

Commit

Permalink
feat(server): support function in attributes (#277)
Browse files Browse the repository at this point in the history
  • Loading branch information
salzhrani authored and gregberge committed Apr 3, 2019
1 parent 79133eb commit c172324
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 38 deletions.
28 changes: 17 additions & 11 deletions packages/server/src/ChunkExtractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@ function getAssets(chunks, getAsset) {
return _.uniqBy(_.flatMap(chunks, chunk => getAsset(chunk)), 'url')
}

function extraPropsToString(extraProps) {
return Object.keys(extraProps).reduce(
(acc, key) => `${acc} ${key}="${extraProps[key]}"`,
function handleExtraProps(asset, extraProps) {
return typeof extraProps === 'function' ? extraProps(asset) : extraProps
}

function extraPropsToString(asset, extraProps) {
return Object.entries(handleExtraProps(asset, extraProps)).reduce(
(acc, [key, value]) => `${acc} ${key}="${value}"`,
'',
)
}

function assetToScriptTag(asset, extraProps) {
return `<script async data-chunk="${asset.chunk}" src="${
asset.url
}"${extraPropsToString(extraProps)}></script>`
}"${extraPropsToString(asset, extraProps)}></script>`
}

function assetToScriptElement(asset, extraProps) {
Expand All @@ -40,7 +44,7 @@ function assetToScriptElement(asset, extraProps) {
async
data-chunk={asset.chunk}
src={asset.url}
{...extraProps}
{...handleExtraProps(asset, extraProps)}
/>
)
}
Expand All @@ -60,7 +64,7 @@ function assetToStyleString(asset) {
function assetToStyleTag(asset, extraProps) {
return `<link data-chunk="${asset.chunk}" rel="stylesheet" href="${
asset.url
}"${extraPropsToString(extraProps)}>`
}"${extraPropsToString(asset, extraProps)}>`
}

function assetToStyleTagInline(asset, extraProps) {
Expand All @@ -72,6 +76,7 @@ function assetToStyleTagInline(asset, extraProps) {
}
resolve(
`<style type="text/css" data-chunk="${asset.chunk}"${extraPropsToString(
asset,
extraProps,
)}>
${data}
Expand All @@ -88,7 +93,7 @@ function assetToStyleElement(asset, extraProps) {
data-chunk={asset.chunk}
rel="stylesheet"
href={asset.url}
{...extraProps}
{...handleExtraProps(asset, extraProps)}
/>
)
}
Expand All @@ -105,7 +110,7 @@ function assetToStyleElementInline(asset, extraProps) {
key={asset.url}
data-chunk={asset.chunk}
dangerouslySetInnerHTML={{ __html: data }}
{...extraProps}
{...handleExtraProps(asset, extraProps)}
/>,
)
})
Expand All @@ -121,7 +126,7 @@ function assetToLinkTag(asset, extraProps) {
const hint = LINK_ASSET_HINTS[asset.type]
return `<link ${hint}="${asset.chunk}" rel="${asset.linkType}" as="${
asset.scriptType
}" href="${asset.url}"${extraPropsToString(extraProps)}>`
}" href="${asset.url}"${extraPropsToString(asset, extraProps)}>`
}

function assetToLinkElement(asset, extraProps) {
Expand All @@ -132,7 +137,7 @@ function assetToLinkElement(asset, extraProps) {
rel: asset.linkType,
as: asset.scriptType,
href: asset.url,
...extraProps,
...handleExtraProps(asset, extraProps),
}
return <link {...props} />
}
Expand Down Expand Up @@ -248,6 +253,7 @@ class ChunkExtractor {

getRequiredChunksScriptTag(extraProps) {
return `<script id="${LOADABLE_REQUIRED_CHUNKS_KEY}" type="application/json"${extraPropsToString(
null,
extraProps,
)}>${this.getRequiredChunksScriptContent()}</script>`
}
Expand All @@ -261,7 +267,7 @@ class ChunkExtractor {
dangerouslySetInnerHTML={{
__html: this.getRequiredChunksScriptContent(),
}}
{...extraProps}
{...handleExtraProps(null, extraProps)}
/>
)
}
Expand Down
127 changes: 121 additions & 6 deletions packages/server/src/ChunkExtractor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,26 @@ describe('ChunkExtrator', () => {
`)
})

it('should add extra props if specified', () => {
it('should add extra props if specified - object argument', () => {
extractor.addChunk('letters-A')
expect(extractor.getScriptTags({ nonce: 'testnonce' }))
.toMatchInlineSnapshot(`
"<script id=\\"__LOADABLE_REQUIRED_CHUNKS__\\" type=\\"application/json\\" nonce=\\"testnonce\\">[\\"letters-A\\"]</script>
<script async data-chunk=\\"main\\" src=\\"/dist/node/main.js\\" nonce=\\"testnonce\\"></script>
<script async data-chunk=\\"letters-A\\" src=\\"/dist/node/letters-A.js\\" nonce=\\"testnonce\\"></script>"
`)
})

it('should add extra props if specified - function argument', () => {
extractor.addChunk('letters-A')
expect(
extractor.getScriptTags(asset => {
return { nonce: asset ? asset.chunk : 'anonymous' }
}),
).toMatchInlineSnapshot(`
"<script id=\\"__LOADABLE_REQUIRED_CHUNKS__\\" type=\\"application/json\\" nonce=\\"anonymous\\">[\\"letters-A\\"]</script>
<script async data-chunk=\\"main\\" src=\\"/dist/node/main.js\\" nonce=\\"main\\"></script>
<script async data-chunk=\\"letters-A\\" src=\\"/dist/node/letters-A.js\\" nonce=\\"letters-A\\"></script>"
`)
})
})
Expand Down Expand Up @@ -153,7 +166,7 @@ Array [
`)
})

it('should add extra props if specified', () => {
it('should add extra props if specified - object argument', () => {
extractor.addChunk('letters-A')
expect(extractor.getScriptElements({ nonce: 'testnonce' }))
.toMatchInlineSnapshot(`
Expand Down Expand Up @@ -181,6 +194,40 @@ Array [
src="/dist/node/letters-A.js"
/>,
]
`)
})

it('should add extra props if specified - function argument', () => {
extractor.addChunk('letters-A')
expect(
extractor.getScriptElements(asset => {
return { nonce: asset ? asset.chunk : 'anonymous' }
}),
).toMatchInlineSnapshot(`
Array [
<script
dangerouslySetInnerHTML={
Object {
"__html": "[\\"letters-A\\"]",
}
}
id="__LOADABLE_REQUIRED_CHUNKS__"
nonce="anonymous"
type="application/json"
/>,
<script
async={true}
data-chunk="main"
nonce="main"
src="/dist/node/main.js"
/>,
<script
async={true}
data-chunk="letters-A"
nonce="letters-A"
src="/dist/node/letters-A.js"
/>,
]
`)
})
})
Expand Down Expand Up @@ -208,12 +255,24 @@ Array [
`)
})

it('should add extraProps if specified', () => {
it('should add extraProps if specified - object argument', () => {
extractor.addChunk('letters-A')
expect(extractor.getStyleTags({ nonce: 'testnonce' }))
.toMatchInlineSnapshot(`
"<link data-chunk=\\"main\\" rel=\\"stylesheet\\" href=\\"/dist/node/main.css\\" nonce=\\"testnonce\\">
<link data-chunk=\\"letters-A\\" rel=\\"stylesheet\\" href=\\"/dist/node/letters-A.css\\" nonce=\\"testnonce\\">"
`)
})

it('should add extraProps if specified - function argument', () => {
extractor.addChunk('letters-A')
expect(
extractor.getStyleTags(asset => ({
nonce: asset ? asset.chunk : 'anonymous',
})),
).toMatchInlineSnapshot(`
"<link data-chunk=\\"main\\" rel=\\"stylesheet\\" href=\\"/dist/node/main.css\\" nonce=\\"main\\">
<link data-chunk=\\"letters-A\\" rel=\\"stylesheet\\" href=\\"/dist/node/letters-A.css\\" nonce=\\"letters-A\\">"
`)
})
})
Expand All @@ -239,7 +298,7 @@ body {
)
})

it('should add extraProps if specified', () => {
it('should add extraProps if specified - object argument', () => {
extractor.addChunk('letters-A')
expect.assertions(1)
return extractor.getInlineStyleTags({ nonce: 'testnonce' }).then(data =>
Expand All @@ -258,6 +317,28 @@ body {
`),
)
})

it('should add extraProps if specified - function argument', () => {
extractor.addChunk('letters-A')
expect.assertions(1)
return extractor
.getInlineStyleTags(asset => ({ nonce: asset.chunk }))
.then(data =>
expect(data).toMatchInlineSnapshot(`
"<style type=\\"text/css\\" data-chunk=\\"main\\" nonce=\\"main\\">
h1 {
color: cyan;
}
</style>
<style type=\\"text/css\\" data-chunk=\\"letters-A\\" nonce=\\"letters-A\\">
body {
background: pink;
}
</style>"
`),
)
})
})

describe('#getStyleElements', () => {
Expand Down Expand Up @@ -309,7 +390,7 @@ Array [
`)
})

it('should add extraProps if specified', () => {
it('should add extraProps if specified - object argument', () => {
extractor.addChunk('letters-A')
expect(extractor.getStyleElements({ nonce: 'testnonce' }))
.toMatchInlineSnapshot(`
Expand All @@ -327,6 +408,27 @@ Array [
rel="stylesheet"
/>,
]
`)
})

it('should add extraProps if specified - function argument', () => {
extractor.addChunk('letters-A')
expect(extractor.getStyleElements(asset => ({ nonce: asset.chunk })))
.toMatchInlineSnapshot(`
Array [
<link
data-chunk="main"
href="/dist/node/main.css"
nonce="main"
rel="stylesheet"
/>,
<link
data-chunk="letters-A"
href="/dist/node/letters-A.css"
nonce="letters-A"
rel="stylesheet"
/>,
]
`)
})
})
Expand Down Expand Up @@ -417,7 +519,7 @@ body {
`)
})

it('should add extraProps if specified', () => {
it('should add extraProps if specified - object argument', () => {
extractor.addChunk('letters-A')
expect(extractor.getLinkTags({ nonce: 'testnonce' }))
.toMatchInlineSnapshot(`
Expand All @@ -427,6 +529,19 @@ body {
<link data-chunk=\\"letters-A\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/letters-A.js\\" nonce=\\"testnonce\\">
<link data-parent-chunk=\\"main\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/letters-C.js\\" nonce=\\"testnonce\\">
<link data-parent-chunk=\\"main\\" rel=\\"prefetch\\" as=\\"script\\" href=\\"/dist/node/letters-D.js\\" nonce=\\"testnonce\\">"
`)
})

it('should add extraProps if specified - function argument', () => {
extractor.addChunk('letters-A')
expect(extractor.getLinkTags(asset => ({ nonce: asset.chunk })))
.toMatchInlineSnapshot(`
"<link data-chunk=\\"main\\" rel=\\"preload\\" as=\\"style\\" href=\\"/dist/node/main.css\\" nonce=\\"main\\">
<link data-chunk=\\"main\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/main.js\\" nonce=\\"main\\">
<link data-chunk=\\"letters-A\\" rel=\\"preload\\" as=\\"style\\" href=\\"/dist/node/letters-A.css\\" nonce=\\"letters-A\\">
<link data-chunk=\\"letters-A\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/letters-A.js\\" nonce=\\"letters-A\\">
<link data-parent-chunk=\\"main\\" rel=\\"preload\\" as=\\"script\\" href=\\"/dist/node/letters-C.js\\" nonce=\\"main\\">
<link data-parent-chunk=\\"main\\" rel=\\"prefetch\\" as=\\"script\\" href=\\"/dist/node/letters-D.js\\" nonce=\\"main\\">"
`)
})
})
Expand Down
Loading

0 comments on commit c172324

Please sign in to comment.