Skip to content

Commit

Permalink
feat: allow to specify extra attributes in getScriptTags & others (#210)
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet authored and gregberge committed Jan 22, 2019
1 parent 210b1ef commit 8a3d067
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 27 deletions.
61 changes: 34 additions & 27 deletions packages/server/src/ChunkExtractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@ function getAssets(chunks, getAsset) {
return _.uniqBy(_.flatMap(chunks, chunk => getAsset(chunk)), 'url')
}

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

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

function assetToScriptElement(asset) {
function assetToScriptElement(asset, extraProps) {
return (
<script key={asset.url} async data-chunk={asset.chunk} src={asset.url} />
<script key={asset.url} async data-chunk={asset.chunk} src={asset.url} {...extraProps} />
)
}

Expand All @@ -44,40 +48,41 @@ function assetToStyleString(asset) {
})
}

function assetToStyleTag(asset) {
function assetToStyleTag(asset, extraProps) {
return `<link data-chunk="${asset.chunk}" rel="stylesheet" href="${
asset.url
}">`
}"${extraPropsToString(extraProps)}>`
}

function assetToStyleTagInline(asset) {
function assetToStyleTagInline(asset, extraProps) {
return new Promise((resolve, reject) => {
fs.readFile(asset.path, 'utf8', (err, data) => {
if (err) {
reject(err)
return
}
resolve(
`<style type="text/css" data-chunk="${asset.chunk}">
`<style type="text/css" data-chunk="${asset.chunk}"${extraPropsToString(extraProps)}>
${data}
</style>`,
)
})
})
}

function assetToStyleElement(asset) {
function assetToStyleElement(asset, extraProps) {
return (
<link
key={asset.url}
data-chunk={asset.chunk}
rel="stylesheet"
href={asset.url}
{...extraProps}
/>
)
}

function assetToStyleElementInline(asset) {
function assetToStyleElementInline(asset, extraProps) {
return new Promise((resolve, reject) => {
fs.readFile(asset.path, 'utf8', (err, data) => {
if (err) {
Expand All @@ -89,6 +94,7 @@ function assetToStyleElementInline(asset) {
key={asset.url}
data-chunk={asset.chunk}
dangerouslySetInnerHTML={{ __html: data }}
{...extraProps}
/>,
)
})
Expand Down Expand Up @@ -225,17 +231,18 @@ class ChunkExtractor {
)};`
}

getRequiredChunksScriptTag() {
return `<script>${this.getRequiredChunksScriptContent()}</script>`
getRequiredChunksScriptTag(extraProps) {
return `<script${extraPropsToString(extraProps)}>${this.getRequiredChunksScriptContent()}</script>`
}

getRequiredChunksScriptElement() {
getRequiredChunksScriptElement(extraProps) {
return (
<script
key="required"
dangerouslySetInnerHTML={{
__html: this.getRequiredChunksScriptContent(),
}}
{...extraProps}
/>
)
}
Expand Down Expand Up @@ -275,18 +282,18 @@ class ChunkExtractor {
return assets
}

getScriptTags() {
const requiredScriptTag = this.getRequiredChunksScriptTag()
getScriptTags(extraProps = {}) {
const requiredScriptTag = this.getRequiredChunksScriptTag(extraProps)
const mainAssets = this.getMainAssets('script')
const assetsScriptTags = mainAssets.map(asset => assetToScriptTag(asset))
const assetsScriptTags = mainAssets.map(asset => assetToScriptTag(asset, extraProps))
return joinTags([requiredScriptTag, ...assetsScriptTags])
}

getScriptElements() {
const requiredScriptElement = this.getRequiredChunksScriptElement()
getScriptElements(extraProps = {}) {
const requiredScriptElement = this.getRequiredChunksScriptElement(extraProps)
const mainAssets = this.getMainAssets('script')
const assetsScriptElements = mainAssets.map(asset =>
assetToScriptElement(asset),
assetToScriptElement(asset, extraProps),
)
return [requiredScriptElement, ...assetsScriptElements]
}
Expand All @@ -299,28 +306,28 @@ class ChunkExtractor {
return Promise.all(promises).then(results => joinTags(results))
}

getStyleTags() {
getStyleTags(extraProps = {}) {
const mainAssets = this.getMainAssets('style')
return joinTags(mainAssets.map(asset => assetToStyleTag(asset)))
return joinTags(mainAssets.map(asset => assetToStyleTag(asset, extraProps)))
}

getInlineStyleTags() {
getInlineStyleTags(extraProps = {}) {
const mainAssets = this.getMainAssets('style')
const promises = mainAssets.map(asset =>
assetToStyleTagInline(asset).then(data => data),
assetToStyleTagInline(asset, extraProps).then(data => data),
)
return Promise.all(promises).then(results => joinTags(results))
}

getStyleElements() {
getStyleElements(extraProps = {}) {
const mainAssets = this.getMainAssets('style')
return mainAssets.map(asset => assetToStyleElement(asset))
return mainAssets.map(asset => assetToStyleElement(asset, extraProps))
}

getInlineStyleElements() {
getInlineStyleElements(extraProps = {}) {
const mainAssets = this.getMainAssets('style')
const promises = mainAssets.map(asset =>
assetToStyleElementInline(asset).then(data => data),
assetToStyleElementInline(asset, extraProps).then(data => data),
)
return Promise.all(promises).then(results => results)
}
Expand Down
89 changes: 89 additions & 0 deletions packages/server/src/ChunkExtractor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ describe('ChunkExtrator', () => {
"<script>window.__LOADABLE_REQUIRED_CHUNKS__ = [\\"letters-A\\"];</script>
<script async data-chunk=\\"letters-A\\" src=\\"/dist/node/letters-A.js\\"></script>
<script async data-chunk=\\"main\\" src=\\"/dist/node/main.js\\"></script>"
`)
})

it('should add extra props if specified', () => {
extractor.addChunk('letters-A')
expect(extractor.getScriptTags({ nonce: 'testnonce' }))
.toMatchInlineSnapshot(`
"<script nonce=\\"testnonce\\">window.__LOADABLE_REQUIRED_CHUNKS__ = [\\"letters-A\\"];</script>
<script async data-chunk=\\"letters-A\\" src=\\"/dist/node/letters-A.js\\" nonce=\\"testnonce\\"></script>
<script async data-chunk=\\"main\\" src=\\"/dist/node/main.js\\" nonce=\\"testnonce\\"></script>"
`)
})
})
Expand Down Expand Up @@ -100,6 +110,35 @@ Array [
src="/dist/node/main.js"
/>,
]
`)
})

it('should add extra props if specified', () => {
extractor.addChunk('letters-A')
expect(extractor.getScriptElements({ nonce: 'testnonce' }))
.toMatchInlineSnapshot(`
Array [
<script
dangerouslySetInnerHTML={
Object {
"__html": "window.__LOADABLE_REQUIRED_CHUNKS__ = [\\"letters-A\\"];",
}
}
nonce="testnonce"
/>,
<script
async={true}
data-chunk="letters-A"
nonce="testnonce"
src="/dist/node/letters-A.js"
/>,
<script
async={true}
data-chunk="main"
nonce="testnonce"
src="/dist/node/main.js"
/>,
]
`)
})
})
Expand All @@ -116,6 +155,15 @@ Array [
expect(extractor.getStyleTags()).toMatchInlineSnapshot(`
"<link data-chunk=\\"letters-A\\" rel=\\"stylesheet\\" href=\\"/dist/node/letters-A.css\\">
<link data-chunk=\\"main\\" rel=\\"stylesheet\\" href=\\"/dist/node/main.css\\">"
`)
})

it('should add extraProps if specified', () => {
extractor.addChunk('letters-A')
expect(extractor.getStyleTags({ nonce: 'testnonce' }))
.toMatchInlineSnapshot(`
"<link data-chunk=\\"letters-A\\" rel=\\"stylesheet\\" href=\\"/dist/node/letters-A.css\\" nonce=\\"testnonce\\">
<link data-chunk=\\"main\\" rel=\\"stylesheet\\" href=\\"/dist/node/main.css\\" nonce=\\"testnonce\\">"
`)
})
})
Expand All @@ -137,6 +185,26 @@ h1 {
color: cyan;
}
</style>"
`),
)
})

it('should add extraProps if specified', () => {
extractor.addChunk('letters-A')
expect.assertions(1)
return extractor.getInlineStyleTags({ nonce: 'testnonce' }).then(data =>
expect(data).toMatchInlineSnapshot(`
"<style type=\\"text/css\\" data-chunk=\\"letters-A\\" nonce=\\"testnonce\\">
body {
background: pink;
}
</style>
<style type=\\"text/css\\" data-chunk=\\"main\\" nonce=\\"testnonce\\">
h1 {
color: cyan;
}
</style>"
`),
)
})
Expand Down Expand Up @@ -170,6 +238,27 @@ Array [
rel="stylesheet"
/>,
]
`)
})

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

0 comments on commit 8a3d067

Please sign in to comment.