diff --git a/packages/gatsby/cache-dir/__tests__/__snapshots__/static-entry.js.snap b/packages/gatsby/cache-dir/__tests__/__snapshots__/static-entry.js.snap
index 603e8dfc70d86..2137dd0c59a58 100644
--- a/packages/gatsby/cache-dir/__tests__/__snapshots__/static-entry.js.snap
+++ b/packages/gatsby/cache-dir/__tests__/__snapshots__/static-entry.js.snap
@@ -1,13 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`develop-static-entry onPreRenderHTML can be used to replace headComponents 1`] = `"
This app works best with JavaScript enabled.
"`;
+exports[`develop-static-entry onPreRenderHTML can be used to replace headComponents 1`] = `"This app works best with JavaScript enabled.
"`;
-exports[`develop-static-entry onPreRenderHTML can be used to replace postBodyComponents 1`] = `"This app works best with JavaScript enabled.
div3
div2
div1
"`;
+exports[`develop-static-entry onPreRenderHTML can be used to replace postBodyComponents 1`] = `"This app works best with JavaScript enabled.
div3
div2
div1
"`;
-exports[`develop-static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `"div3
div2
div1
This app works best with JavaScript enabled.
"`;
+exports[`develop-static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `" div3
div2
div1
This app works best with JavaScript enabled.
"`;
-exports[`static-entry onPreRenderHTML can be used to replace headComponents 1`] = `"This app works best with JavaScript enabled. "`;
+exports[`static-entry onPreRenderHTML can be used to replace headComponents 1`] = `"This app works best with JavaScript enabled. "`;
-exports[`static-entry onPreRenderHTML can be used to replace postBodyComponents 1`] = `"This app works best with JavaScript enabled. div3
div2
div1
"`;
+exports[`static-entry onPreRenderHTML can be used to replace postBodyComponents 1`] = `"This app works best with JavaScript enabled. div3
div2
div1
"`;
-exports[`static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `"div3
div2
div1
This app works best with JavaScript enabled. "`;
+exports[`static-entry onPreRenderHTML can be used to replace preBodyComponents 1`] = `" div3
div2
div1
This app works best with JavaScript enabled. "`;
diff --git a/packages/gatsby/cache-dir/__tests__/static-entry.js b/packages/gatsby/cache-dir/__tests__/static-entry.js
index 03d857d15a1de..41edef94ab482 100644
--- a/packages/gatsby/cache-dir/__tests__/static-entry.js
+++ b/packages/gatsby/cache-dir/__tests__/static-entry.js
@@ -17,7 +17,9 @@ jest.mock(
},
}
},
- { virtual: true }
+ {
+ virtual: true,
+ }
)
jest.mock(
@@ -38,7 +40,9 @@ jest.mock(
],
}
},
- { virtual: true }
+ {
+ virtual: true,
+ }
)
const MOCK_FILE_INFO = {
@@ -61,13 +65,48 @@ const reverseHeadersPlugin = {
},
}
+const injectValuePlugin = (hookName, methodName, value) => {
+ return {
+ plugin: {
+ [hookName]: staticEntry => {
+ const method = staticEntry[methodName]
+ method(value)
+ },
+ },
+ }
+}
+
+const checkSanitized = components => {
+ expect(components.includes(null)).toBeFalsy()
+ expect(
+ components.find(val => Array.isArray(val) && val.length === 0)
+ ).toBeFalsy()
+}
+
+const checkNonEmptyHeadersPlugin = {
+ plugin: {
+ onPreRenderHTML: ({
+ getHeadComponents,
+ getPreBodyComponents,
+ getPostBodyComponents,
+ }) => {
+ const headComponents = getHeadComponents()
+ const preBodyComponents = getPreBodyComponents()
+ const postBodyComponents = getPostBodyComponents()
+ checkSanitized(headComponents)
+ checkSanitized(preBodyComponents)
+ checkSanitized(postBodyComponents)
+ },
+ },
+}
+
const fakeStylesPlugin = {
plugin: {
onRenderBody: ({ setHeadComponents }) =>
setHeadComponents([
- ,
- ,
- ,
+ ,
+ ,
+ ,
]),
},
}
@@ -89,9 +128,9 @@ const fakeComponentsPluginFactory = type => {
plugin: {
onRenderBody: props => {
props[`set${type}BodyComponents`]([
- div1
,
- div2
,
- div3
,
+ div1
,
+ div2
,
+ div3
,
])
},
},
@@ -133,6 +172,59 @@ describe(`develop-static-entry`, () => {
})
})
+describe(`static-entry sanity checks`, () => {
+ beforeEach(() => {
+ global.__PATH_PREFIX__ = ``
+ })
+
+ const methodsToCheck = [
+ `replaceHeadComponents`,
+ `replacePreBodyComponents`,
+ `replacePostBodyComponents`,
+ ]
+
+ methodsToCheck.forEach(methodName => {
+ test(`${methodName} can filter out null value`, done => {
+ const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, null)
+ global.plugins = [plugin, checkNonEmptyHeadersPlugin]
+
+ StaticEntry(`/about/`, (_, html) => {
+ done()
+ })
+ })
+
+ test(`${methodName} can filter out null values`, done => {
+ const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, [
+ null,
+ null,
+ ])
+ global.plugins = [plugin, checkNonEmptyHeadersPlugin]
+
+ StaticEntry(`/about/`, (_, html) => {
+ done()
+ })
+ })
+
+ test(`${methodName} can filter out empty array`, done => {
+ const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, [])
+ global.plugins = [plugin, checkNonEmptyHeadersPlugin]
+
+ StaticEntry(`/about/`, (_, html) => {
+ done()
+ })
+ })
+
+ test(`${methodName} can filter out empty arrays`, done => {
+ const plugin = injectValuePlugin(`onPreRenderHTML`, methodName, [[], []])
+ global.plugins = [plugin, checkNonEmptyHeadersPlugin]
+
+ StaticEntry(`/about/`, (_, html) => {
+ done()
+ })
+ })
+ })
+})
+
describe(`static-entry`, () => {
beforeEach(() => {
global.__PATH_PREFIX__ = ``
diff --git a/packages/gatsby/cache-dir/static-entry.js b/packages/gatsby/cache-dir/static-entry.js
index 3e0cb708ba184..d3fbebd1a523c 100644
--- a/packages/gatsby/cache-dir/static-entry.js
+++ b/packages/gatsby/cache-dir/static-entry.js
@@ -49,6 +49,16 @@ const getPage = path => pagesObjectMap.get(path)
const createElement = React.createElement
+const sanitizeComponents = components => {
+ if (Array.isArray(components)) {
+ // remove falsy items
+ return components.filter(val => (Array.isArray(val) ? val.length > 0 : val))
+ } else {
+ // we also accept single components, so we need to handle this case as well
+ return components ? [components] : []
+ }
+}
+
export default (pagePath, callback) => {
let bodyHtml = ``
let headComponents = [
@@ -69,7 +79,7 @@ export default (pagePath, callback) => {
}
const setHeadComponents = components => {
- headComponents = headComponents.concat(components)
+ headComponents = headComponents.concat(sanitizeComponents(components))
}
const setHtmlAttributes = attributes => {
@@ -81,11 +91,13 @@ export default (pagePath, callback) => {
}
const setPreBodyComponents = components => {
- preBodyComponents = preBodyComponents.concat(components)
+ preBodyComponents = preBodyComponents.concat(sanitizeComponents(components))
}
const setPostBodyComponents = components => {
- postBodyComponents = postBodyComponents.concat(components)
+ postBodyComponents = postBodyComponents.concat(
+ sanitizeComponents(components)
+ )
}
const setBodyProps = props => {
@@ -95,19 +107,19 @@ export default (pagePath, callback) => {
const getHeadComponents = () => headComponents
const replaceHeadComponents = components => {
- headComponents = components
+ headComponents = sanitizeComponents(components)
}
const getPreBodyComponents = () => preBodyComponents
const replacePreBodyComponents = components => {
- preBodyComponents = components
+ preBodyComponents = sanitizeComponents(components)
}
const getPostBodyComponents = () => postBodyComponents
const replacePostBodyComponents = components => {
- postBodyComponents = components
+ postBodyComponents = sanitizeComponents(components)
}
const page = getPage(pagePath)