Skip to content

Commit 2bf8c0d

Browse files
authored
feat: add unstable_onPluginInit that would execute once in all processes (#31901)
* feat: add unstable_onPluginInit that would execute once in all processes * update tests * add basic unit test for isGatsbyNodeLifecycleSupported * add readme section about added lifecycle existance check * don't mix ESM and CJS in readme * add example to node api docs * set version to 3.9 * try/catch lifecycle check, just to make sure we never crash because of it * uncoditionally set actions and plugins in onPreBootstrap, it doesn't hurt to do so
1 parent 44257b6 commit 2bf8c0d

File tree

11 files changed

+108
-26
lines changed

11 files changed

+108
-26
lines changed
Loading
Loading

packages/gatsby-plugin-sharp/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"filenamify": "^4.2.0",
1414
"fs-extra": "^9.1.0",
1515
"gatsby-core-utils": "^2.9.0-next.0",
16+
"gatsby-plugin-utils": "^1.9.0-next.0",
1617
"gatsby-telemetry": "^2.9.0-next.0",
1718
"got": "^10.7.0",
1819
"imagemin": "^7.0.1",
@@ -34,8 +35,7 @@
3435
"@types/sharp": "^0.27.1",
3536
"babel-preset-gatsby-package": "^1.9.0-next.0",
3637
"cross-env": "^7.0.3",
37-
"gatsby-plugin-image": "^1.9.0-next.0",
38-
"gatsby-plugin-utils": "^1.9.0-next.0"
38+
"gatsby-plugin-image": "^1.9.0-next.0"
3939
},
4040
"homepage": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-sharp#readme",
4141
"keywords": [

packages/gatsby-plugin-sharp/src/gatsby-node.js

+18
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ const { slash } = require(`gatsby-core-utils`)
1111
const { setPluginOptions } = require(`./plugin-options`)
1212
const path = require(`path`)
1313

14+
let coreSupportsOnPluginInit
15+
try {
16+
const { isGatsbyNodeLifecycleSupported } = require(`gatsby-plugin-utils`)
17+
coreSupportsOnPluginInit = isGatsbyNodeLifecycleSupported(
18+
`unstable_onPluginInit`
19+
)
20+
} catch (e) {
21+
coreSupportsOnPluginInit = false
22+
}
23+
1424
exports.onCreateDevServer = async ({ app, cache, reporter }) => {
1525
if (!_lazyJobsEnabled()) {
1626
return
@@ -104,6 +114,14 @@ exports.onPostBootstrap = async ({ reporter, cache, store }) => {
104114
}
105115
}
106116

117+
if (coreSupportsOnPluginInit) {
118+
// to properly initialize plugin in worker (`onPreBootstrap` won't run in workers)
119+
exports.unstable_onPluginInit = async ({ actions }, pluginOptions) => {
120+
setActions(actions)
121+
setPluginOptions(pluginOptions)
122+
}
123+
}
124+
107125
exports.onPreBootstrap = async ({ actions, emitter, cache }, pluginOptions) => {
108126
setActions(actions)
109127
setPluginOptions(pluginOptions)

packages/gatsby-plugin-utils/README.md

+19
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,22 @@ it(`should partially validate one value of a schema`, async () => {
4444
expect(errors).toEqual([`"toVerify" must be a boolean`])
4545
})
4646
```
47+
48+
### `isGatsbyNodeLifecycleSupported`
49+
50+
Utility to be used by plugins to do runtime check against `gatsby` core package checking wether particular `gatsby-node` lifecycle API is supported. Useful for plugins to be able to support multiple `gatsby` core versions.
51+
52+
#### Example
53+
54+
```js
55+
const { isGatsbyNodeLifecycleSupported } = require(`gatsby-plugin-utils`)
56+
57+
// only use createSchemaCustomization lifecycle only when it's available.
58+
if (isGatsbyNodeLifecycleSupported(`createSchemaCustomization`)) {
59+
exports.createSchemaCustomization = function createSchemaCustomization({
60+
actions,
61+
}) {
62+
// customize schema
63+
}
64+
}
65+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { isGatsbyNodeLifecycleSupported } from "../node-api-is-supported"
2+
3+
describe(`isGatsbyNodeLifecycleSupported`, () => {
4+
it(`returns true for supported API (createSchemaCustomization)`, () => {
5+
expect(isGatsbyNodeLifecycleSupported(`createSchemaCustomization`)).toEqual(
6+
true
7+
)
8+
})
9+
10+
it(`returns false for unsupported API (thisIsNotSupported)`, () => {
11+
expect(isGatsbyNodeLifecycleSupported(`thisIsNotSupported`)).toEqual(false)
12+
})
13+
})
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from "./validate"
22
export * from "./test-plugin-options-schema"
33
export * from "./joi"
4+
export * from "./node-api-is-supported"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export function isGatsbyNodeLifecycleSupported(apiName: string): boolean {
2+
let availableAPIs
3+
try {
4+
availableAPIs = require(`gatsby/apis.json`)
5+
} catch (e) {
6+
throw new Error(
7+
`Couldn't check available APIs. Make sure you are on gatsby version >=2.13.41`
8+
)
9+
}
10+
11+
return !!availableAPIs?.node?.[apiName]
12+
}

packages/gatsby/scripts/__tests__/api.js

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ it("generates the expected api output", done => {
5757
"resolvableExtensions": Object {},
5858
"setFieldsOnGraphQLNodeType": Object {},
5959
"sourceNodes": Object {},
60+
"unstable_onPluginInit": Object {
61+
"version": "3.9.0",
62+
},
6063
"unstable_shouldOnCreateNode": Object {
6164
"version": "2.24.80",
6265
},

packages/gatsby/src/bootstrap/load-plugins/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
ICurrentAPIs,
1414
validateConfigPluginsOptions,
1515
} from "./validate"
16+
import apiRunnerNode from "../../utils/api-runner-node"
1617
import {
1718
IPluginInfo,
1819
IFlattenedPlugin,
@@ -124,5 +125,8 @@ export async function loadPlugins(
124125
payload: flattenedPlugins,
125126
})
126127

128+
// And let plugins initialize if they want to
129+
await apiRunnerNode(`unstable_onPluginInit`)
130+
127131
return flattenedPlugins
128132
}

packages/gatsby/src/utils/api-node-docs.ts

+14
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,20 @@ export const onCreateWebpackConfig = true
410410
*/
411411
export const onPreInit = true
412412

413+
/**
414+
* Lifecycle executed in each process (one time per process). Used to store actions etc for later use.
415+
*
416+
* @example
417+
* let createJobV2
418+
* exports.unstable_onPluginInit = ({ actions }) => {
419+
* // store job creation action to use it later
420+
* createJobV2 = actions.createJobV2
421+
* }
422+
* @gatsbyVersion 3.9.0
423+
*/
424+
// eslint-disable-next-line @typescript-eslint/naming-convention
425+
export const unstable_onPluginInit = true
426+
413427
/**
414428
* Called once Gatsby has initialized itself and is ready to bootstrap your site.
415429
*/

0 commit comments

Comments
 (0)