Skip to content

Commit 2f3f372

Browse files
piehLekoArts
andauthored
perf: normalize engines static query context (#37764)
* perf: normalize engines static query context Co-authored-by: LekoArts <[email protected]> * drop unused * add some filtering * pass only slice static queries by template * e2e case * fix passing slice template -> sq mapping * drop debug log * add e2e case for ssg --------- Co-authored-by: LekoArts <[email protected]>
1 parent b01da02 commit 2f3f372

File tree

10 files changed

+140
-117
lines changed

10 files changed

+140
-117
lines changed

e2e-tests/production-runtime/cypress/integration/slices/slices.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,10 @@ describe(`Slices`, () => {
4141
.invoke(`text`)
4242
.should(`contain`, `2`)
4343
})
44+
45+
it(`Slice with static query works`, () => {
46+
cy.getTestElement(`footer-static-query-title`).contains(
47+
`Gatsby Default Starter`
48+
)
49+
})
4450
})

e2e-tests/production-runtime/cypress/integration/ssr.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ const paramPath = `/ssr/param-path/`
33
const wildcardPath = `/ssr/wildcard-path/`
44
const pathRaking = `/ssr/path-ranking/`
55

6-
Cypress.on('uncaught:exception', (err, runnable) => {
7-
if (err.message.includes('Minified React error #418') || err.message.includes('Minified React error #423')) {
6+
Cypress.on("uncaught:exception", (err, runnable) => {
7+
if (
8+
err.message.includes("Minified React error #418") ||
9+
err.message.includes("Minified React error #423")
10+
) {
811
return false
912
}
1013
})
@@ -50,6 +53,13 @@ describe(`Static path ('${staticPath}')`, () => {
5053
expect(win.location.search).to.equal(queryString)
5154
})
5255
})
56+
57+
it(`Slice with static query works`, () => {
58+
cy.visit(staticPath).waitForRouteChange()
59+
cy.getTestElement(`footer-static-query-title`).contains(
60+
`Gatsby Default Starter`
61+
)
62+
})
5363
})
5464

5565
describe(`Param path ('${paramPath}:param')`, () => {

e2e-tests/production-runtime/src/components/footer.js

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,42 @@
11
import React, { useContext } from "react"
2+
import { useStaticQuery, graphql } from "gatsby"
23
import { AppContext } from "../app-context"
34

45
// Use as a Slice
5-
function Footer({ framework, lang, sliceContext: { framework: frameworkViaContext }}) {
6+
function Footer({
7+
framework,
8+
lang,
9+
sliceContext: { framework: frameworkViaContext },
10+
}) {
611
const { posts } = useContext(AppContext)
712

13+
const data = useStaticQuery(graphql`
14+
{
15+
site {
16+
siteMetadata {
17+
alias: title
18+
}
19+
}
20+
}
21+
`)
22+
823
return (
924
<footer
1025
style={{
1126
marginTop: `10px`,
1227
fontSize: `12px`,
1328
}}
1429
>
15-
<span data-testid="footer-slice-context-value">{frameworkViaContext}</span>
16-
<span data-testid="footer-static-text">Built with {` `}</span>
17-
<span data-testid="footer-props">{`${framework}${lang}`}</span>
18-
{` `}Posts Count: <span data-testid="footer-context-derieved-value">{`${posts.length}`}</span>
30+
<span data-testid="footer-slice-context-value">
31+
{frameworkViaContext}
32+
</span>
33+
<span data-testid="footer-static-text">Built with {` `}</span>
34+
<span data-testid="footer-props">{`${framework}${lang}`}</span>
35+
{` `}Posts Count:{" "}
36+
<span data-testid="footer-context-derieved-value">{`${posts.length}`}</span>
37+
<span data-testid="footer-static-query-title">
38+
{data.site.siteMetadata.alias}
39+
</span>
1940
</footer>
2041
)
2142
}

e2e-tests/production-runtime/src/pages/ssr/static-path.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from "react"
2+
import { Slice } from "gatsby"
23

34
const UseEnv = ({ heading, envVar }) => (
45
<React.Fragment>
@@ -30,7 +31,7 @@ export default function StaticPath({ serverData }) {
3031
heading="process.env.FROM_COMMAND_LINE"
3132
envVar={process.env.FROM_COMMAND_LINE}
3233
/>
33-
<UseEnv
34+
<UseEnv
3435
heading="process.env.GATSBY_PREFIXED_FROM_COMMAND_LINE"
3536
envVar={process.env.GATSBY_PREFIXED_FROM_COMMAND_LINE}
3637
/>
@@ -51,10 +52,11 @@ export default function StaticPath({ serverData }) {
5152
heading="serverData.envVars.FROM_COMMAND_LINE"
5253
envVar={serverData?.envVars?.FROM_COMMAND_LINE}
5354
/>
54-
<UseEnv
55+
<UseEnv
5556
heading="serverData.envVars.GATSBY_PREFIXED_FROM_COMMAND_LINE"
5657
envVar={serverData?.envVars?.GATSBY_PREFIXED_FROM_COMMAND_LINE}
5758
/>
59+
<Slice alias="footer" framework="Gatsby" lang="js" />
5860
</div>
5961
)
6062
}
@@ -63,7 +65,8 @@ export async function getServerData(arg) {
6365
const VERY_SECRET_ALIAS_VAR = process.env.VERY_SECRET_VAR
6466
const EXISTING_VAR = process.env.EXISTING_VAR
6567
const FROM_COMMAND_LINE = process.env.FROM_COMMAND_LINE
66-
const GATSBY_PREFIXED_FROM_COMMAND_LINE = process.env.GATSBY_PREFIXED_FROM_COMMAND_LINE
68+
const GATSBY_PREFIXED_FROM_COMMAND_LINE =
69+
process.env.GATSBY_PREFIXED_FROM_COMMAND_LINE
6770

6871
return {
6972
props: {
@@ -72,7 +75,7 @@ export async function getServerData(arg) {
7275
VERY_SECRET_ALIAS_VAR,
7376
EXISTING_VAR,
7477
FROM_COMMAND_LINE,
75-
GATSBY_PREFIXED_FROM_COMMAND_LINE
78+
GATSBY_PREFIXED_FROM_COMMAND_LINE,
7679
},
7780
},
7881
}

packages/gatsby/src/commands/build-html.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,11 +778,18 @@ export async function buildSlices({
778778
try {
779779
const slices = Array.from(state.slices.entries())
780780

781+
const staticQueriesBySliceTemplate = {}
782+
for (const slice of state.slices.values()) {
783+
staticQueriesBySliceTemplate[slice.componentPath] =
784+
state.staticQueriesByTemplate.get(slice.componentPath)
785+
}
786+
781787
await workerPool.single.renderSlices({
782788
publicDir: path.join(program.directory, `public`),
783789
htmlComponentRendererPath,
784790
slices,
785791
slicesProps,
792+
staticQueriesBySliceTemplate,
786793
})
787794
} catch (err) {
788795
const prettyError = createErrorFromString(

packages/gatsby/src/commands/build.ts

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import {
5656
import { createGraphqlEngineBundle } from "../schema/graphql-engine/bundle-webpack"
5757
import {
5858
createPageSSRBundle,
59-
writeQueryContext,
59+
copyStaticQueriesToEngine,
6060
} from "../utils/page-ssr-module/bundle-webpack"
6161
import { shouldGenerateEngines } from "../utils/engines-helpers"
6262
import reporter from "gatsby-cli/lib/reporter"
@@ -379,15 +379,38 @@ module.exports = async function build(
379379
})
380380
}
381381

382-
// create scope so we don't leak state object
382+
const engineTemplatePaths = new Set<string>()
383383
{
384-
const state = store.getState()
385-
await writeQueryContext({
386-
staticQueriesByTemplate: state.staticQueriesByTemplate,
387-
components: state.components,
384+
let SSGCount = 0
385+
let DSGCount = 0
386+
let SSRCount = 0
387+
388+
for (const page of store.getState().pages.values()) {
389+
if (page.mode === `SSR`) {
390+
SSRCount++
391+
engineTemplatePaths.add(page.componentPath)
392+
} else if (page.mode === `DSG`) {
393+
DSGCount++
394+
engineTemplatePaths.add(page.componentPath)
395+
} else {
396+
SSGCount++
397+
}
398+
}
399+
400+
telemetry.addSiteMeasurement(`BUILD_END`, {
401+
totalPagesCount: store.getState().pages.size, // total number of pages
402+
SSRCount,
403+
DSGCount,
404+
SSGCount,
388405
})
389406
}
390407

408+
await copyStaticQueriesToEngine({
409+
engineTemplatePaths,
410+
staticQueriesByTemplate: store.getState().staticQueriesByTemplate,
411+
components: store.getState().components,
412+
})
413+
391414
if (!(_CFLAGS_.GATSBY_MAJOR === `5` && process.env.GATSBY_SLICES)) {
392415
if (process.send && shouldGenerateEngines()) {
393416
await waitMaterializePageMode
@@ -577,29 +600,9 @@ module.exports = async function build(
577600
}
578601
}
579602

580-
{
581-
let SSGCount = 0
582-
let DSGCount = 0
583-
let SSRCount = 0
584-
for (const page of store.getState().pages.values()) {
585-
if (page.mode === `SSR`) {
586-
SSRCount++
587-
} else if (page.mode === `DSG`) {
588-
DSGCount++
589-
} else {
590-
SSGCount++
591-
}
592-
}
593-
594-
telemetry.addSiteMeasurement(`BUILD_END`, {
595-
pagesCount: toRegenerate.length, // number of html files that will be written
596-
totalPagesCount: store.getState().pages.size, // total number of pages
597-
SSRCount,
598-
DSGCount,
599-
SSGCount,
600-
})
601-
}
602-
603+
telemetry.addSiteMeasurement(`BUILD_END`, {
604+
totalPagesCount: store.getState().pages.size, // total number of pages
605+
})
603606
const postBuildActivityTimer = report.activityTimer(`onPostBuild`, {
604607
parentSpan: buildSpan,
605608
})

packages/gatsby/src/utils/page-ssr-module/bundle-webpack.ts

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
getScriptsAndStylesForTemplate,
1111
readWebpackStats,
1212
} from "../client-assets-for-template"
13-
import { writeStaticQueryContext } from "../static-query-utils"
1413
import { IGatsbyState } from "../../redux/types"
1514
import { store } from "../../redux"
1615

@@ -20,27 +19,45 @@ const extensions = [`.mjs`, `.js`, `.json`, `.node`, `.ts`, `.tsx`]
2019
const outputDir = path.join(process.cwd(), `.cache`, `page-ssr`)
2120
const cacheLocation = path.join(process.cwd(), `.cache`, `webpack`, `page-ssr`)
2221

23-
export async function writeQueryContext({
24-
staticQueriesByTemplate,
22+
export async function copyStaticQueriesToEngine({
23+
engineTemplatePaths,
2524
components,
25+
staticQueriesByTemplate,
2626
}: {
27-
staticQueriesByTemplate: IGatsbyState["staticQueriesByTemplate"]
27+
engineTemplatePaths: Set<string>
2828
components: IGatsbyState["components"]
29+
staticQueriesByTemplate: IGatsbyState["staticQueriesByTemplate"]
2930
}): Promise<void> {
30-
const waitingForWrites: Array<Promise<unknown>> = []
31-
for (const pageTemplate of components.values()) {
32-
const staticQueryHashes =
33-
staticQueriesByTemplate.get(pageTemplate.componentPath) || []
31+
const staticQueriesToCopy = new Set<string>()
32+
33+
for (const component of components.values()) {
34+
// figuring out needed slices for each pages using componentPath is not straightforward
35+
// so for now we just collect static queries for all slices + engine templates
36+
if (component.isSlice || engineTemplatePaths.has(component.componentPath)) {
37+
const staticQueryHashes =
38+
staticQueriesByTemplate.get(component.componentPath) || []
39+
40+
for (const hash of staticQueryHashes) {
41+
staticQueriesToCopy.add(hash)
42+
}
43+
}
44+
}
45+
46+
const sourceDir = path.join(process.cwd(), `public`, `page-data`, `sq`, `d`)
47+
const destDir = path.join(outputDir, `sq`)
48+
49+
await fs.ensureDir(destDir)
50+
await fs.emptyDir(destDir)
51+
52+
const promisesToAwait: Array<Promise<void>> = []
53+
for (const hash of staticQueriesToCopy) {
54+
const sourcePath = path.join(sourceDir, `${hash}.json`)
55+
const destPath = path.join(destDir, `${hash}.json`)
3456

35-
waitingForWrites.push(
36-
writeStaticQueryContext(
37-
staticQueryHashes,
38-
pageTemplate.componentChunkName
39-
)
40-
)
57+
promisesToAwait.push(fs.copy(sourcePath, destPath))
4158
}
4259

43-
return Promise.all(waitingForWrites).then(() => {})
60+
await Promise.all(promisesToAwait)
4461
}
4562

4663
export async function createPageSSRBundle({

packages/gatsby/src/utils/page-ssr-module/entry.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -314,16 +314,10 @@ export async function renderPageData({
314314
}
315315
}
316316
}
317-
318-
const readStaticQueryContext = async (
319-
templatePath: string
317+
const readStaticQuery = async (
318+
staticQueryHash: string
320319
): Promise<Record<string, { data: unknown }>> => {
321-
const filePath = path.join(
322-
__dirname,
323-
`sq-context`,
324-
templatePath,
325-
`sq-context.json`
326-
)
320+
const filePath = path.join(__dirname, `sq`, `${staticQueryHash}.json`)
327321
const rawSQContext = await fs.readFile(filePath, `utf-8`)
328322

329323
return JSON.parse(rawSQContext)
@@ -399,20 +393,19 @@ export async function renderHTML({
399393
readStaticQueryContextActivity.start()
400394
}
401395

402-
const uniqueUsedComponentChunkNames = [data.page.componentChunkName]
396+
const staticQueryHashes = new Set<string>(pageData.staticQueryHashes)
403397
for (const singleSliceData of Object.values(sliceData)) {
404-
if (
405-
singleSliceData.componentChunkName &&
406-
!uniqueUsedComponentChunkNames.includes(
407-
singleSliceData.componentChunkName
408-
)
409-
) {
410-
uniqueUsedComponentChunkNames.push(singleSliceData.componentChunkName)
398+
for (const staticQueryHash of singleSliceData.staticQueryHashes) {
399+
staticQueryHashes.add(staticQueryHash)
411400
}
412401
}
413402

414403
const contextsToMerge = await Promise.all(
415-
uniqueUsedComponentChunkNames.map(readStaticQueryContext)
404+
Array.from(staticQueryHashes).map(async staticQueryHash => {
405+
return {
406+
[staticQueryHash]: await readStaticQuery(staticQueryHash),
407+
}
408+
})
416409
)
417410

418411
staticQueryContext = Object.assign({}, ...contextsToMerge)

packages/gatsby/src/utils/static-query-utils.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ const { join } = path.posix
55
import type { IScriptsAndStyles } from "./client-assets-for-template"
66
import { IPageDataWithQueryResult } from "./page-data"
77

8-
const outputDir = path.join(process.cwd(), `.cache`, `page-ssr`)
9-
108
export const getStaticQueryPath = (hash: string): string =>
119
join(`page-data`, `sq`, `d`, `${hash}.json`)
1210

@@ -66,24 +64,3 @@ export const getStaticQueryContext = async (
6664

6765
return { staticQueryContext }
6866
}
69-
70-
export const writeStaticQueryContext = async (
71-
staticQueryHashes: IPageDataWithQueryResult["staticQueryHashes"],
72-
templatePath: string
73-
): Promise<{
74-
staticQueryContext: IResourcesForTemplate["staticQueryContext"]
75-
}> => {
76-
const outputFilePath = path.join(
77-
outputDir,
78-
`sq-context`,
79-
templatePath,
80-
`sq-context.json`
81-
)
82-
83-
const { staticQueryContext } = await getStaticQueryContext(staticQueryHashes)
84-
85-
const stringifiedContext = JSON.stringify(staticQueryContext)
86-
await fs.outputFile(outputFilePath, stringifiedContext)
87-
88-
return { staticQueryContext }
89-
}

0 commit comments

Comments
 (0)