Skip to content

Commit d1005fa

Browse files
KyleAMathewspieh
andauthored
perf(gatsby): Create page object & SitePage node in same action creator (#31104)
* feat(gatsby): don't duplicate page data into SitePage nodes * Fix lint * treat pages as actual sitePage nodes * change flag name to reflect change in strategy * fix type * Add missing field + test with LOCKED_IN * Fix bugs... maybe * fix types * fixes hopefully * Move this from reducer to action so node also gets it * Avoid calling onCreatePage if can * set pluginCreator___NODE and pluginCreatorId always, not just when flag is enabled * Early return from node API calls if there's no implementing plugins * Return something * Also always run api when deferNodeMutation is set — apparently it triggers a side effect somewhere... * Only call onCreateNode for SitePage nodes * Only start plugin runner after plugins are created so we have plugins available to reason around * Recreate pages from SitePage cache vs. persisting/restoring in seperately Saves 100mb of heap for 100k page create-pages benchmark * Maybe fix * Ignore * Revert attempt to restore page state from SitePage nodes * Remove flag * Remove unnecessary implementation of onCreatePage Drops 100k create-pages benchmark from ~8s to 4.5s as it means we don't need to invoke `onCreatePage` by default. * Remove unnecessary changes * Fix tests * fix prod-404 and webpack suspending timing (#31236) * fix 404 * drop checking defered node mutations when bailing * suspend after first compilation * actually check for plugins implementing onCreateNode Co-authored-by: Michal Piechowiak <[email protected]>
1 parent bd40048 commit d1005fa

File tree

14 files changed

+245
-169
lines changed

14 files changed

+245
-169
lines changed

benchmarks/create-pages/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
"serve": "gatsby serve"
1010
},
1111
"dependencies": {
12-
"gatsby": "^2.19.5",
13-
"react": "^16.12.0",
14-
"react-dom": "^16.12.0"
12+
"gatsby": "^3.4.0",
13+
"react": "^17.0.2",
14+
"react-dom": "^17.0.2"
1515
},
1616
"devDependencies": {
1717
"gatsby-plugin-benchmark-reporting": "*"
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
__tests__/__debug__
1+
__tests__/__debug__
2+
node_modules
3+
yarn.lock

packages/gatsby/src/bootstrap/load-plugins/__tests__/__snapshots__/load-plugins.ts.snap

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ Array [
3737
"nodeAPIs": Array [
3838
"sourceNodes",
3939
"createResolvers",
40-
"onCreatePage",
4140
],
4241
"pluginOptions": Object {
4342
"plugins": Array [],
@@ -50,9 +49,7 @@ Array [
5049
"browserAPIs": Array [],
5150
"id": "",
5251
"name": "prod-404",
53-
"nodeAPIs": Array [
54-
"onCreatePage",
55-
],
52+
"nodeAPIs": Array [],
5653
"pluginOptions": Object {
5754
"plugins": Array [],
5855
},
@@ -287,7 +284,6 @@ Array [
287284
"nodeAPIs": Array [
288285
"sourceNodes",
289286
"createResolvers",
290-
"onCreatePage",
291287
],
292288
"pluginOptions": Object {
293289
"plugins": Array [],
@@ -300,9 +296,7 @@ Array [
300296
"browserAPIs": Array [],
301297
"id": "",
302298
"name": "prod-404",
303-
"nodeAPIs": Array [
304-
"onCreatePage",
305-
],
299+
"nodeAPIs": Array [],
306300
"pluginOptions": Object {
307301
"plugins": Array [],
308302
},
@@ -567,7 +561,6 @@ Array [
567561
"nodeAPIs": Array [
568562
"sourceNodes",
569563
"createResolvers",
570-
"onCreatePage",
571564
],
572565
"pluginOptions": Object {
573566
"plugins": Array [],
@@ -580,9 +573,7 @@ Array [
580573
"browserAPIs": Array [],
581574
"id": "",
582575
"name": "prod-404",
583-
"nodeAPIs": Array [
584-
"onCreatePage",
585-
],
576+
"nodeAPIs": Array [],
586577
"pluginOptions": Object {
587578
"plugins": Array [],
588579
},

packages/gatsby/src/internal-plugins/internal-data-bridge/gatsby-node.js

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,6 @@ exports.sourceNodes = ({
5050
const { createNode, deleteNode } = actions
5151
const { program, flattenedPlugins, config } = store.getState()
5252

53-
// Add our default development page since we know it's going to
54-
// exist and we need a node to exist so its query works :-)
55-
const page = { path: `/dev-404-page/` }
56-
createNode({
57-
...page,
58-
id: createPageId(page.path),
59-
parent: null,
60-
children: [],
61-
internal: {
62-
type: `SitePage`,
63-
contentDigest: createContentDigest(page),
64-
},
65-
})
66-
6753
flattenedPlugins.forEach(plugin => {
6854
plugin.pluginFilepath = plugin.resolve
6955
createNode({
@@ -226,29 +212,8 @@ exports.createResolvers = ({ createResolvers }) => {
226212
},
227213
},
228214
}
229-
createResolvers(resolvers)
230-
}
231215

232-
exports.onCreatePage = ({ createContentDigest, page, actions }) => {
233-
const { createNode } = actions
234-
// eslint-disable-next-line
235-
const { updatedAt, ...pageWithoutUpdated } = page
236-
237-
// Add page.
238-
createNode({
239-
...pageWithoutUpdated,
240-
id: createPageId(page.path),
241-
parent: null,
242-
children: [],
243-
internal: {
244-
type: `SitePage`,
245-
contentDigest: createContentDigest(pageWithoutUpdated),
246-
description:
247-
page.pluginCreatorId === `Plugin default-site-plugin`
248-
? `Your site's "gatsby-node.js"`
249-
: page.pluginCreatorId,
250-
},
251-
})
216+
createResolvers(resolvers)
252217
}
253218

254219
// Listen for DELETE_PAGE and delete page nodes.

packages/gatsby/src/internal-plugins/prod-404/gatsby-node.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,27 @@ const { actions } = require(`../../redux/actions`)
44
const PROD_404_PAGE_PATH = `/404.html`
55

66
let page404 = null
7-
exports.onCreatePage = ({ page, store, actions }) => {
7+
emitter.on(`CREATE_PAGE`, action => {
88
// Copy /404/ to /404.html as many static site hosts expect
99
// site 404 pages to be named this.
1010
// https://www.gatsbyjs.org/docs/how-to/adding-common-features/add-404-page/
11-
if (!page404 && /^\/?404\/?$/.test(page.path)) {
12-
actions.createPage({
13-
...page,
14-
path: PROD_404_PAGE_PATH,
15-
})
16-
page404 = page
11+
if (!page404 && /^\/?404\/?$/.test(action.payload.path)) {
12+
page404 = {
13+
path: action.payload.path,
14+
component: action.payload.component,
15+
context: action.payload.context,
16+
}
17+
store.dispatch(
18+
actions.createPage(
19+
{
20+
...page404,
21+
path: PROD_404_PAGE_PATH,
22+
},
23+
action.plugin
24+
)
25+
)
1726
}
18-
}
27+
})
1928

2029
emitter.on(`DELETE_PAGE`, action => {
2130
if (page404 && action.payload.path === page404.path) {

packages/gatsby/src/redux/__tests__/index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jest.mock(`glob`, () => {
8181
function getFakeNodes() {
8282
// Set nodes to something or the cache will fail because it asserts this
8383
// Actual nodes content should match TS type; these are verified
84-
const map /* : Map<string, IReduxNode>*/ = new Map()
84+
const map /* : Map<string, IReduxNode> */ = new Map()
8585
map.set(`pageA`, {
8686
id: `pageA`,
8787
internal: {
@@ -108,10 +108,11 @@ describe(`redux db`, () => {
108108
Date.now = jest.fn(() => ++DateNowCallCount)
109109

110110
store.dispatch(
111-
(Array.isArray(pages) ? pages : [pages]).map(page =>
112-
createPage(page, {
113-
name: `default-site-plugin`,
114-
})
111+
(Array.isArray(pages) ? pages : [pages]).map(
112+
page =>
113+
createPage(page, {
114+
name: `default-site-plugin`,
115+
}).filter(a => a.type === `CREATE_PAGE`)[0]
115116
)
116117
)
117118

packages/gatsby/src/redux/__tests__/pages.ts

Lines changed: 77 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ glob.sync = jest.fn()
2424

2525
describe(`Add pages`, () => {
2626
it(`allows you to add pages`, () => {
27-
const action = actions.createPage(
28-
{
29-
path: `/hi/`,
30-
component: `/whatever/index.js`,
31-
},
32-
{ id: `test`, name: `test` }
33-
)
27+
const action = actions
28+
.createPage(
29+
{
30+
path: `/hi/`,
31+
component: `/whatever/index.js`,
32+
},
33+
{ id: `test`, name: `test` }
34+
)
35+
.filter(a => a.type === `CREATE_PAGE`)[0]
3436
const state = reducer(undefined, action)
3537
expect(action).toMatchSnapshot()
3638
expect(state).toMatchSnapshot()
@@ -83,85 +85,98 @@ describe(`Add pages`, () => {
8385
})
8486

8587
it(`adds an initial forward slash if the user doesn't`, () => {
86-
const action = actions.createPage(
88+
const actionsArray = actions.createPage(
8789
{
8890
path: `hi/`,
8991
component: `/whatever/index.js`,
9092
},
9193
{ id: `test`, name: `test` }
9294
)
95+
const action = actionsArray.filter(a => a.type === `CREATE_PAGE`)[0]
9396
const state = reducer(undefined, action)
9497
expect(Array.from(state.values())[0].path).toEqual(`/hi/`)
9598
})
9699

97100
it(`allows you to add pages with context`, () => {
98-
const action = actions.createPage(
99-
{
100-
path: `/hi/`,
101-
component: `/whatever/index.js`,
102-
context: {
103-
id: 123,
101+
const action = actions
102+
.createPage(
103+
{
104+
path: `/hi/`,
105+
component: `/whatever/index.js`,
106+
context: {
107+
id: 123,
108+
},
104109
},
105-
},
106-
{ id: `test`, name: `test` }
107-
)
110+
{ id: `test`, name: `test` }
111+
)
112+
.filter(a => a.type === `CREATE_PAGE`)[0]
108113
const state = reducer(undefined, action)
109114
expect(action).toMatchSnapshot()
110115
expect(state).toMatchSnapshot()
111116
})
112117

113118
it(`allows you to add pages with matchPath`, () => {
114-
const action = actions.createPage(
115-
{
116-
path: `/hi/`,
117-
component: `/whatever/index.js`,
118-
matchPath: `/hi-from-somewhere-else/`,
119-
},
120-
{ id: `test`, name: `test` }
121-
)
119+
const action = actions
120+
.createPage(
121+
{
122+
path: `/hi/`,
123+
component: `/whatever/index.js`,
124+
matchPath: `/hi-from-somewhere-else/`,
125+
},
126+
{ id: `test`, name: `test` }
127+
)
128+
.filter(a => a.type === `CREATE_PAGE`)[0]
122129
const state = reducer(undefined, action)
123130
expect(action).toMatchSnapshot()
124131
expect(state).toMatchSnapshot()
125132
})
126133

127134
it(`allows you to add multiple pages`, () => {
128-
const action = actions.createPage(
129-
{
130-
path: `/hi/`,
131-
component: `/whatever/index.js`,
132-
},
133-
{ id: `test`, name: `test` }
134-
)
135-
const action2 = actions.createPage(
136-
{
137-
path: `/hi/pizza/`,
138-
component: `/whatever/index.js`,
139-
},
140-
{ id: `test`, name: `test` }
141-
)
135+
const action = actions
136+
.createPage(
137+
{
138+
path: `/hi/`,
139+
component: `/whatever/index.js`,
140+
},
141+
{ id: `test`, name: `test` }
142+
)
143+
.filter(a => a.type === `CREATE_PAGE`)[0]
144+
const action2 = actions
145+
.createPage(
146+
{
147+
path: `/hi/pizza/`,
148+
component: `/whatever/index.js`,
149+
},
150+
{ id: `test`, name: `test` }
151+
)
152+
.filter(a => a.type === `CREATE_PAGE`)[0]
142153
let state = reducer(undefined, action)
143154
state = reducer(state, action2)
144155
expect(state).toMatchSnapshot()
145156
expect(state.size).toEqual(2)
146157
})
147158

148159
it(`allows you to update existing pages (based on path)`, () => {
149-
const action = actions.createPage(
150-
{
151-
path: `/hi/`,
152-
component: `/whatever/index.js`,
153-
},
154-
{ id: `test`, name: `test` }
155-
)
160+
const action = actions
161+
.createPage(
162+
{
163+
path: `/hi/`,
164+
component: `/whatever/index.js`,
165+
},
166+
{ id: `test`, name: `test` }
167+
)
168+
.filter(a => a.type === `CREATE_PAGE`)[0]
156169

157170
// Change the component
158-
const action2 = actions.createPage(
159-
{
160-
path: `/hi/`,
161-
component: `/whatever2/index.js`,
162-
},
163-
{ id: `test`, name: `test` }
164-
)
171+
const action2 = actions
172+
.createPage(
173+
{
174+
path: `/hi/`,
175+
component: `/whatever2/index.js`,
176+
},
177+
{ id: `test`, name: `test` }
178+
)
179+
.filter(a => a.type === `CREATE_PAGE`)[0]
165180

166181
let state = reducer(undefined, action)
167182
state = reducer(state, action2)
@@ -170,13 +185,15 @@ describe(`Add pages`, () => {
170185
})
171186

172187
it(`allows you to delete paths`, () => {
173-
const action = actions.createPage(
174-
{
175-
path: `/hi/`,
176-
component: `/whatever/index.js`,
177-
},
178-
{ id: `test`, name: `test` }
179-
)
188+
const action = actions
189+
.createPage(
190+
{
191+
path: `/hi/`,
192+
component: `/whatever/index.js`,
193+
},
194+
{ id: `test`, name: `test` }
195+
)
196+
.filter(a => a.type === `CREATE_PAGE`)[0]
180197
const action2 = actions.deletePage({ path: `/hi/` })
181198

182199
let state = reducer(undefined, action)

0 commit comments

Comments
 (0)