Skip to content

Commit e852f99

Browse files
committed
perf(gatsby-adapter-netlify): improve adapt() performance (#38988)
* test: add ssg specific headers * fix: headers rule matching with path prefix * test: add NODE_NO_WARNING, axios seems to use fetch now under the hood causing fetch warning on node 18 impacting some logs assertions * perf: don't recreate headers from headerRoutes for each static route in route manifest * test: apply NODE_NO_WARNINGS env in correct place (cherry picked from commit ec77bed)
1 parent 6c63350 commit e852f99

File tree

14 files changed

+109
-34
lines changed

14 files changed

+109
-34
lines changed

.circleci/config.yml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ executors:
1515
environment:
1616
GATSBY_CPU_COUNT: 2
1717
COMPILER_OPTIONS: GATSBY_MAJOR=<< parameters.gatsby_major >>
18+
NODE_NO_WARNINGS: 1
1819

1920
aliases:
2021
e2e-executor-env: &e2e-executor-env

e2e-tests/adapters/cypress/e2e/headers.cy.ts

+20
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ describe("Headers", () => {
7676

7777
beforeEach(() => {
7878
cy.intercept(PATH_PREFIX + "/", WorkaroundCachedResponse).as("index")
79+
cy.intercept(
80+
PATH_PREFIX + "/routes/ssg/static",
81+
WorkaroundCachedResponse
82+
).as("ssg")
7983
cy.intercept(
8084
PATH_PREFIX + "/routes/ssr/static",
8185
WorkaroundCachedResponse
@@ -128,6 +132,22 @@ describe("Headers", () => {
128132
checkHeaders("@js")
129133
})
130134

135+
it("should contain correct headers for ssg page", () => {
136+
cy.visit("routes/ssg/static").waitForRouteChange()
137+
138+
checkHeaders("@ssg", {
139+
...defaultHeaders,
140+
"x-custom-header": "my custom header value",
141+
"x-ssg-header": "my custom header value",
142+
"cache-control": "public,max-age=0,must-revalidate",
143+
})
144+
145+
checkHeaders("@app-data")
146+
checkHeaders("@page-data")
147+
checkHeaders("@slice-data")
148+
checkHeaders("@static-query-result")
149+
})
150+
131151
it("should contain correct headers for ssr page", () => {
132152
cy.visit("routes/ssr/static").waitForRouteChange()
133153

e2e-tests/adapters/cypress/e2e/remote-file.cy.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ const PATH_PREFIX = Cypress.env(`PATH_PREFIX`) || ``
1818
const configs = [
1919
{
2020
title: `remote-file (SSG, Page Query)`,
21-
pagePath: `/routes/remote-file/`,
21+
pagePath: `/routes/ssg/remote-file/`,
2222
placeholders: true,
2323
},
2424
{
2525
title: `remote-file (SSG, Page Context)`,
26-
pagePath: `/routes/remote-file-data-from-context/`,
26+
pagePath: `/routes/ssg/remote-file-data-from-context/`,
2727
placeholders: true,
2828
},
2929
{
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { assertPageVisits } from "../utils/assert-page-visits"
22
import { applyTrailingSlashOption } from "../../utils"
33

4-
Cypress.on("uncaught:exception", (err) => {
4+
Cypress.on("uncaught:exception", err => {
55
if (err.message.includes("Minified React error")) {
66
return false
77
}
@@ -12,38 +12,62 @@ const TRAILING_SLASH = Cypress.env(`TRAILING_SLASH`) || `never`
1212
describe("trailingSlash", () => {
1313
describe(TRAILING_SLASH, () => {
1414
it("should work when using Gatsby Link (without slash)", () => {
15-
cy.visit('/').waitForRouteChange()
15+
cy.visit("/").waitForRouteChange()
1616

17-
cy.get(`[data-testid="static-without-slash"]`).click().waitForRouteChange().assertRoute(applyTrailingSlashOption(`/routes/static`, TRAILING_SLASH))
17+
cy.get(`[data-testid="static-without-slash"]`)
18+
.click()
19+
.waitForRouteChange()
20+
.assertRoute(
21+
applyTrailingSlashOption(`/routes/ssg/static`, TRAILING_SLASH)
22+
)
1823
})
1924
it("should work when using Gatsby Link (with slash)", () => {
20-
cy.visit('/').waitForRouteChange()
25+
cy.visit("/").waitForRouteChange()
2126

22-
cy.get(`[data-testid="static-with-slash"]`).click().waitForRouteChange().assertRoute(applyTrailingSlashOption(`/routes/static`, TRAILING_SLASH))
27+
cy.get(`[data-testid="static-with-slash"]`)
28+
.click()
29+
.waitForRouteChange()
30+
.assertRoute(
31+
applyTrailingSlashOption(`/routes/ssg/static`, TRAILING_SLASH)
32+
)
2333
})
2434
it("should work on direct visit (with other setting)", () => {
25-
const destination = applyTrailingSlashOption("/routes/static", TRAILING_SLASH)
26-
const inverse = TRAILING_SLASH === `always` ? "/routes/static" : "/routes/static/"
35+
const destination = applyTrailingSlashOption(
36+
"/routes/ssg/static",
37+
TRAILING_SLASH
38+
)
39+
const inverse =
40+
TRAILING_SLASH === `always`
41+
? "/routes/ssg/static"
42+
: "/routes/ssg/static/"
2743

2844
assertPageVisits([
2945
{
3046
path: destination,
3147
status: 200,
3248
},
33-
{ path: inverse, status: 301, destinationPath: destination }
49+
{ path: inverse, status: 301, destinationPath: destination },
3450
])
3551

36-
cy.visit(inverse).waitForRouteChange().assertRoute(applyTrailingSlashOption(`/routes/static`, TRAILING_SLASH))
52+
cy.visit(inverse)
53+
.waitForRouteChange()
54+
.assertRoute(
55+
applyTrailingSlashOption(`/routes/ssg/static`, TRAILING_SLASH)
56+
)
3757
})
3858
it("should work on direct visit (with current setting)", () => {
3959
assertPageVisits([
4060
{
41-
path: applyTrailingSlashOption("/routes/static", TRAILING_SLASH),
61+
path: applyTrailingSlashOption("/routes/ssg/static", TRAILING_SLASH),
4262
status: 200,
4363
},
4464
])
4565

46-
cy.visit(applyTrailingSlashOption("/routes/static", TRAILING_SLASH)).waitForRouteChange().assertRoute(applyTrailingSlashOption(`/routes/static`, TRAILING_SLASH))
66+
cy.visit(applyTrailingSlashOption("/routes/ssg/static", TRAILING_SLASH))
67+
.waitForRouteChange()
68+
.assertRoute(
69+
applyTrailingSlashOption(`/routes/ssg/static`, TRAILING_SLASH)
70+
)
4771
})
4872
})
4973
})

e2e-tests/adapters/gatsby-config.ts

+9
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ const config: GatsbyConfig = {
7777
},
7878
],
7979
},
80+
{
81+
source: `routes/ssg/*`,
82+
headers: [
83+
{
84+
key: "x-ssg-header",
85+
value: "my custom header value",
86+
},
87+
],
88+
},
8089
],
8190
...configOverrides,
8291
}

e2e-tests/adapters/gatsby-node.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export const createPages: GatsbyNode["createPages"] = async ({
5555

5656
createPage({
5757
path: applyTrailingSlashOption(
58-
`/routes/remote-file-data-from-context/`,
58+
`/routes/ssg/remote-file-data-from-context/`,
5959
TRAILING_SLASH
6060
),
6161
component: path.resolve(`./src/templates/remote-file-from-context.jsx`),

e2e-tests/adapters/src/pages/index.jsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import "./index.css"
77
const routes = [
88
{
99
text: "Static",
10-
url: "/routes/static",
10+
url: "/routes/ssg/static",
1111
id: "static-without-slash",
1212
},
1313
{
1414
text: "Static (With Slash)",
15-
url: "/routes/static/",
15+
url: "/routes/ssg/static/",
1616
id: "static-with-slash",
1717
},
1818
{
@@ -41,11 +41,11 @@ const routes = [
4141
},
4242
{
4343
text: "RemoteFile (ImageCDN and FileCDN) (SSG, Page Query)",
44-
url: "/routes/remote-file",
44+
url: "/routes/ssg/remote-file",
4545
},
4646
{
4747
text: "RemoteFile (ImageCDN and FileCDN) (SSG, Page Context)",
48-
url: "/routes/remote-file-data-from-context",
48+
url: "/routes/ssg/remote-file-data-from-context",
4949
},
5050
{
5151
text: "RemoteFile (ImageCDN and FileCDN) (SSR, Page Query)",

e2e-tests/adapters/src/pages/routes/remote-file.jsx renamed to e2e-tests/adapters/src/pages/routes/ssg/remote-file.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { graphql } from "gatsby"
22
import React from "react"
33

44
import { GatsbyImage } from "gatsby-plugin-image"
5-
import Layout from "../../components/layout"
5+
import Layout from "../../../components/layout"
66

77
const RemoteFile = ({ data }) => {
88
return (

e2e-tests/adapters/src/pages/routes/static.jsx renamed to e2e-tests/adapters/src/pages/routes/ssg/static.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from "react"
2-
import Layout from "../../components/layout"
2+
import Layout from "../../../components/layout"
33

44
const StaticPage = () => {
55
return (
@@ -11,4 +11,4 @@ const StaticPage = () => {
1111

1212
export default StaticPage
1313

14-
export const Head = () => <title>Static</title>
14+
export const Head = () => <title>Static</title>

packages/gatsby-adapter-netlify/src/route-handler.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,13 @@ export function processRoutesManifest(
236236
_headers += buildHeaderString(route.path, route.headers)
237237
}
238238
}
239+
}
239240

240-
if (headerRoutes) {
241-
_headers = headerRoutes.reduce((acc, curr) => {
242-
acc += buildHeaderString(curr.path, curr.headers)
243-
return acc
244-
}, ``)
245-
}
241+
if (headerRoutes) {
242+
_headers = headerRoutes.reduce((acc, curr) => {
243+
acc += buildHeaderString(curr.path, curr.headers)
244+
return acc
245+
}, ``)
246246
}
247247

248248
return {

packages/gatsby/src/utils/adapter/create-headers.ts

+24-5
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,17 @@ const normalizePath = (input: string): string =>
1212
input.endsWith(`/`) ? input : `${input}/`
1313

1414
export const createHeadersMatcher = (
15-
headers: Array<IHeader> | undefined
15+
headers: Array<IHeader> | undefined,
16+
pathPrefix: string
1617
): ((path: string, defaultHeaders: Headers) => Headers) => {
18+
function stripPathPrefix(path: string): string {
19+
if (pathPrefix && path.startsWith(pathPrefix)) {
20+
path = path.slice(pathPrefix.length)
21+
}
22+
23+
return path
24+
}
25+
1726
// Split the incoming user headers into two buckets:
1827
// - dynamicHeaders: Headers with dynamic paths (e.g. /* or /:tests)
1928
// - staticHeaders: Headers with fully static paths (e.g. /static/)
@@ -27,13 +36,21 @@ export const createHeadersMatcher = (
2736
}
2837

2938
for (const header of headers) {
30-
if (header.source.includes(`:`) || header.source.includes(`*`)) {
39+
const source = stripPathPrefix(header.source)
40+
if (source.includes(`:`) || source.includes(`*`)) {
3141
// rankRoute is the internal function that also "match" uses
32-
const score = rankRoute(header.source)
42+
const score = rankRoute(source)
3343

34-
dynamicHeaders.push({ ...header, score })
44+
dynamicHeaders.push({
45+
...header,
46+
score,
47+
source,
48+
})
3549
} else {
36-
staticHeaders.set(normalizePath(header.source), header)
50+
staticHeaders.set(normalizePath(source), {
51+
...header,
52+
source,
53+
})
3754
}
3855
}
3956

@@ -48,6 +65,8 @@ export const createHeadersMatcher = (
4865
})
4966

5067
return (path: string, defaultHeaders: Headers): Headers => {
68+
path = stripPathPrefix(path)
69+
5170
// Create a map of headers for the given path
5271
// The key will be the header key. Since a key may only appear once in a map, the last header with the same key will win
5372
const uniqueHeaders: Map<string, string> = new Map()

packages/gatsby/src/utils/adapter/manager.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,10 @@ function getRoutesManifest(): {
342342
} {
343343
const routes: Array<RouteWithScore> = []
344344
const state = store.getState()
345-
const createHeaders = createHeadersMatcher(state.config.headers)
346345
const pathPrefix = state.program.prefixPaths
347346
? state.config.pathPrefix ?? ``
348347
: ``
348+
const createHeaders = createHeadersMatcher(state.config.headers, pathPrefix)
349349

350350
const headerRoutes: HeaderRoutes = [...getDefaultHeaderRoutes(pathPrefix)]
351351

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

+1
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ export async function createPageSSRBundle({
230230
)
231231
: ``
232232
),
233+
PATH_PREFIX: JSON.stringify(pathPrefix),
233234
// eslint-disable-next-line @typescript-eslint/naming-convention
234235
"process.env.GATSBY_LOGGER": JSON.stringify(`yurnalist`),
235236
// eslint-disable-next-line @typescript-eslint/naming-convention

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ declare global {
7575
const WEBPACK_COMPILATION_HASH: string
7676
const GATSBY_SLICES_SCRIPT: string
7777
const GATSBY_PAGES: Array<[string, EnginePage]>
78+
const PATH_PREFIX: string
7879
}
7980

8081
const tracerReadyPromise = initTracer(
@@ -85,7 +86,7 @@ type MaybePhantomActivity =
8586
| ReturnType<typeof reporter.phantomActivity>
8687
| undefined
8788

88-
const createHeaders = createHeadersMatcher(INLINED_HEADERS_CONFIG)
89+
const createHeaders = createHeadersMatcher(INLINED_HEADERS_CONFIG, PATH_PREFIX)
8990

9091
interface IGetDataBaseArgs {
9192
pathName: string

0 commit comments

Comments
 (0)