mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-10 21:07:48 +00:00
[static-build] Patch the gatsby-node config file to invoke @vercel/gatsby-plugin-vercel-builder (#9308)
We need to ensure that `@vercel/gatsby-plugin-vercel-builder` is executed as the very last plugin, which Gatsby itself doesn't really support in the plugins listing. So instead we'll patch the `gatsby-node` file to invoke the plugin in the project's own `onPostBuild()` hook, which does get executed last. The patching is similar to how is done with the `gatsby-config` file.
This commit is contained in:
@@ -19,53 +19,44 @@ const PLUGINS = [
|
|||||||
type PluginName = typeof PLUGINS[number];
|
type PluginName = typeof PLUGINS[number];
|
||||||
|
|
||||||
const GATSBY_CONFIG_FILE = 'gatsby-config';
|
const GATSBY_CONFIG_FILE = 'gatsby-config';
|
||||||
|
const GATSBY_NODE_FILE = 'gatsby-node';
|
||||||
|
|
||||||
export async function injectPlugins(
|
export async function injectPlugins(
|
||||||
detectedVersion: string | null,
|
detectedVersion: string | null,
|
||||||
dir: string
|
dir: string
|
||||||
) {
|
) {
|
||||||
const pluginsToInject = new Set<PluginName>();
|
const plugins = new Set<PluginName>();
|
||||||
|
|
||||||
if (process.env.VERCEL_GATSBY_BUILDER_PLUGIN && detectedVersion) {
|
if (process.env.VERCEL_GATSBY_BUILDER_PLUGIN && detectedVersion) {
|
||||||
const version = semver.coerce(detectedVersion);
|
const version = semver.coerce(detectedVersion);
|
||||||
if (version && semver.satisfies(version, '>=4.0.0')) {
|
if (version && semver.satisfies(version, '>=4.0.0')) {
|
||||||
pluginsToInject.add('@vercel/gatsby-plugin-vercel-builder');
|
plugins.add('@vercel/gatsby-plugin-vercel-builder');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.VERCEL_ANALYTICS_ID) {
|
if (process.env.VERCEL_ANALYTICS_ID) {
|
||||||
process.env.GATSBY_VERCEL_ANALYTICS_ID = process.env.VERCEL_ANALYTICS_ID;
|
process.env.GATSBY_VERCEL_ANALYTICS_ID = process.env.VERCEL_ANALYTICS_ID;
|
||||||
pluginsToInject.add('@vercel/gatsby-plugin-vercel-analytics');
|
plugins.add('@vercel/gatsby-plugin-vercel-analytics');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginsToInject.size === 0) {
|
if (plugins.size === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await addGatsbyPackage(dir, pluginsToInject);
|
const ops = [addGatsbyPackage(dir, plugins)];
|
||||||
|
|
||||||
const gatsbyConfigPathTs = path.join(dir, `${GATSBY_CONFIG_FILE}.ts`);
|
if (plugins.has('@vercel/gatsby-plugin-vercel-analytics')) {
|
||||||
const gatsbyConfigPathMjs = path.join(dir, `${GATSBY_CONFIG_FILE}.mjs`);
|
ops.push(
|
||||||
const gatsbyConfigPathJs = path.join(dir, `${GATSBY_CONFIG_FILE}.js`);
|
updateGatsbyConfig(dir, ['@vercel/gatsby-plugin-vercel-analytics'])
|
||||||
if (await fileExists(gatsbyConfigPathTs)) {
|
);
|
||||||
printInjectingPlugins(pluginsToInject, gatsbyConfigPathTs);
|
|
||||||
await updateGatsbyTsConfig(gatsbyConfigPathTs, pluginsToInject);
|
|
||||||
} else if (await fileExists(gatsbyConfigPathMjs)) {
|
|
||||||
printInjectingPlugins(pluginsToInject, gatsbyConfigPathMjs);
|
|
||||||
await updateGatsbyMjsConfig(gatsbyConfigPathMjs, pluginsToInject);
|
|
||||||
} else {
|
|
||||||
printInjectingPlugins(pluginsToInject, gatsbyConfigPathJs);
|
|
||||||
if (await fileExists(gatsbyConfigPathJs)) {
|
|
||||||
await updateGatsbyJsConfig(gatsbyConfigPathJs, pluginsToInject);
|
|
||||||
} else {
|
|
||||||
await fs.writeFile(
|
|
||||||
gatsbyConfigPathJs,
|
|
||||||
`module.exports = ${JSON.stringify({
|
|
||||||
plugins: pluginsToInject,
|
|
||||||
})}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (plugins.has('@vercel/gatsby-plugin-vercel-builder')) {
|
||||||
|
ops.push(updateGatsbyNode(dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(ops);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,23 +102,49 @@ async function addGatsbyPackage(
|
|||||||
await writePackageJson(dir, pkgJson);
|
await writePackageJson(dir, pkgJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateGatsbyTsConfig(
|
async function updateGatsbyConfig(dir: string, plugins: Iterable<PluginName>) {
|
||||||
|
const gatsbyConfigPathTs = path.join(dir, `${GATSBY_CONFIG_FILE}.ts`);
|
||||||
|
const gatsbyConfigPathMjs = path.join(dir, `${GATSBY_CONFIG_FILE}.mjs`);
|
||||||
|
const gatsbyConfigPathJs = path.join(dir, `${GATSBY_CONFIG_FILE}.js`);
|
||||||
|
if (await fileExists(gatsbyConfigPathTs)) {
|
||||||
|
printInjectingPlugins(plugins, gatsbyConfigPathTs);
|
||||||
|
await updateGatsbyConfigTs(gatsbyConfigPathTs, plugins);
|
||||||
|
} else if (await fileExists(gatsbyConfigPathMjs)) {
|
||||||
|
printInjectingPlugins(plugins, gatsbyConfigPathMjs);
|
||||||
|
await updateGatsbyConfigMjs(gatsbyConfigPathMjs, plugins);
|
||||||
|
} else {
|
||||||
|
printInjectingPlugins(plugins, gatsbyConfigPathJs);
|
||||||
|
if (await fileExists(gatsbyConfigPathJs)) {
|
||||||
|
await updateGatsbyConfigJs(gatsbyConfigPathJs, plugins);
|
||||||
|
} else {
|
||||||
|
await fs.writeFile(
|
||||||
|
gatsbyConfigPathJs,
|
||||||
|
`module.exports = ${JSON.stringify({
|
||||||
|
plugins: Array.from(plugins),
|
||||||
|
})}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateGatsbyConfigTs(
|
||||||
configPath: string,
|
configPath: string,
|
||||||
plugins: Iterable<PluginName>
|
plugins: Iterable<PluginName>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await fs.rename(configPath, configPath + '.__vercel_builder_backup__.ts');
|
const renamedPath = `${configPath}.__vercel_builder_backup__.ts`;
|
||||||
|
if (!(await fileExists(renamedPath))) {
|
||||||
|
await fs.rename(configPath, renamedPath);
|
||||||
|
}
|
||||||
|
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
configPath,
|
configPath,
|
||||||
`import userConfig from "./gatsby-config.ts.__vercel_builder_backup__.ts";
|
`import userConfig from "./gatsby-config.ts.__vercel_builder_backup__.ts";
|
||||||
import type { PluginRef } from "gatsby";
|
import type { PluginRef } from "gatsby";
|
||||||
|
|
||||||
// https://github.com/gatsbyjs/gatsby/blob/354003fb2908e02ff12109ca3a02978a5a6e608c/packages/gatsby/src/bootstrap/prefer-default.ts
|
|
||||||
const preferDefault = (m: any) => (m && m.default) || m;
|
const preferDefault = (m: any) => (m && m.default) || m;
|
||||||
|
|
||||||
const vercelConfig = Object.assign(
|
const vercelConfig = Object.assign(
|
||||||
{},
|
{},
|
||||||
// https://github.com/gatsbyjs/gatsby/blob/a6ecfb2b01d761e8a3612b8ea132c698659923d9/packages/gatsby/src/services/initialize.ts#L113-L117
|
|
||||||
preferDefault(userConfig)
|
preferDefault(userConfig)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -152,22 +169,23 @@ export default vercelConfig;
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateGatsbyMjsConfig(
|
async function updateGatsbyConfigMjs(
|
||||||
configPath: string,
|
configPath: string,
|
||||||
plugins: Iterable<PluginName>
|
plugins: Iterable<PluginName>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await fs.rename(configPath, configPath + '.__vercel_builder_backup__.mjs');
|
const renamedPath = `${configPath}.__vercel_builder_backup__.mjs`;
|
||||||
|
if (!(await fileExists(renamedPath))) {
|
||||||
|
await fs.rename(configPath, renamedPath);
|
||||||
|
}
|
||||||
|
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
configPath,
|
configPath,
|
||||||
`import userConfig from "./gatsby-config.mjs.__vercel_builder_backup__.mjs";
|
`import userConfig from "./gatsby-config.mjs.__vercel_builder_backup__.mjs";
|
||||||
|
|
||||||
// https://github.com/gatsbyjs/gatsby/blob/354003fb2908e02ff12109ca3a02978a5a6e608c/packages/gatsby/src/bootstrap/prefer-default.ts
|
|
||||||
const preferDefault = (m) => (m && m.default) || m;
|
const preferDefault = (m) => (m && m.default) || m;
|
||||||
|
|
||||||
const vercelConfig = Object.assign(
|
const vercelConfig = Object.assign(
|
||||||
{},
|
{},
|
||||||
// https://github.com/gatsbyjs/gatsby/blob/a6ecfb2b01d761e8a3612b8ea132c698659923d9/packages/gatsby/src/services/initialize.ts#L113-L117
|
|
||||||
preferDefault(userConfig)
|
preferDefault(userConfig)
|
||||||
);
|
);
|
||||||
if (!vercelConfig.plugins) {
|
if (!vercelConfig.plugins) {
|
||||||
@@ -190,22 +208,23 @@ export default vercelConfig;
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateGatsbyJsConfig(
|
async function updateGatsbyConfigJs(
|
||||||
configPath: string,
|
configPath: string,
|
||||||
plugins: Iterable<PluginName>
|
plugins: Iterable<PluginName>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await fs.rename(configPath, configPath + '.__vercel_builder_backup__.js');
|
const renamedPath = `${configPath}.__vercel_builder_backup__.js`;
|
||||||
|
if (!(await fileExists(renamedPath))) {
|
||||||
|
await fs.rename(configPath, renamedPath);
|
||||||
|
}
|
||||||
|
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
configPath,
|
configPath,
|
||||||
`const userConfig = require("./gatsby-config.js.__vercel_builder_backup__.js");
|
`const userConfig = require("./gatsby-config.js.__vercel_builder_backup__.js");
|
||||||
|
|
||||||
// https://github.com/gatsbyjs/gatsby/blob/354003fb2908e02ff12109ca3a02978a5a6e608c/packages/gatsby/src/bootstrap/prefer-default.ts
|
|
||||||
const preferDefault = m => (m && m.default) || m;
|
const preferDefault = m => (m && m.default) || m;
|
||||||
|
|
||||||
const vercelConfig = Object.assign(
|
const vercelConfig = Object.assign(
|
||||||
{},
|
{},
|
||||||
// https://github.com/gatsbyjs/gatsby/blob/a6ecfb2b01d761e8a3612b8ea132c698659923d9/packages/gatsby/src/services/initialize.ts#L113-L117
|
|
||||||
preferDefault(userConfig)
|
preferDefault(userConfig)
|
||||||
);
|
);
|
||||||
if (!vercelConfig.plugins) {
|
if (!vercelConfig.plugins) {
|
||||||
@@ -226,3 +245,93 @@ module.exports = vercelConfig;
|
|||||||
`
|
`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateGatsbyNode(dir: string) {
|
||||||
|
const gatsbyNodePathTs = path.join(dir, `${GATSBY_NODE_FILE}.ts`);
|
||||||
|
const gatsbyNodePathMjs = path.join(dir, `${GATSBY_NODE_FILE}.mjs`);
|
||||||
|
const gatsbyNodePathJs = path.join(dir, `${GATSBY_NODE_FILE}.js`);
|
||||||
|
if (await fileExists(gatsbyNodePathTs)) {
|
||||||
|
await updateGatsbyNodeTs(gatsbyNodePathTs);
|
||||||
|
} else if (await fileExists(gatsbyNodePathMjs)) {
|
||||||
|
await updateGatsbyNodeMjs(gatsbyNodePathMjs);
|
||||||
|
} else if (await fileExists(gatsbyNodePathJs)) {
|
||||||
|
await updateGatsbyNodeJs(gatsbyNodePathJs);
|
||||||
|
} else {
|
||||||
|
await fs.writeFile(
|
||||||
|
gatsbyNodePathJs,
|
||||||
|
`module.exports = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateGatsbyNodeTs(configPath: string) {
|
||||||
|
const renamedPath = `${configPath}.__vercel_builder_backup__.ts`;
|
||||||
|
if (!(await fileExists(renamedPath))) {
|
||||||
|
await fs.rename(configPath, renamedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
configPath,
|
||||||
|
`import type { GatsbyNode } from 'gatsby';
|
||||||
|
import * as vercelBuilder from '@vercel/gatsby-plugin-vercel-builder/gatsby-node.js';
|
||||||
|
import * as gatsbyNode from './gatsby-node.ts.__vercel_builder_backup__.ts';
|
||||||
|
|
||||||
|
export * from './gatsby-node.ts.__vercel_builder_backup__.ts';
|
||||||
|
|
||||||
|
export const onPostBuild: GatsbyNode['onPostBuild'] = async (args, options) => {
|
||||||
|
if (typeof (gatsbyNode as any).onPostBuild === 'function') {
|
||||||
|
await (gatsbyNode as any).onPostBuild(args, options);
|
||||||
|
}
|
||||||
|
await vercelBuilder.onPostBuild(args, options);
|
||||||
|
};
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateGatsbyNodeMjs(configPath: string) {
|
||||||
|
const renamedPath = `${configPath}.__vercel_builder_backup__.mjs`;
|
||||||
|
if (!(await fileExists(renamedPath))) {
|
||||||
|
await fs.rename(configPath, renamedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
configPath,
|
||||||
|
`import * as vercelBuilder from '@vercel/gatsby-plugin-vercel-builder/gatsby-node.js';
|
||||||
|
import * as gatsbyNode from './gatsby-node.mjs.__vercel_builder_backup__.mjs';
|
||||||
|
|
||||||
|
export * from './gatsby-node.mjs.__vercel_builder_backup__.mjs';
|
||||||
|
|
||||||
|
export const onPostBuild = async (args, options) => {
|
||||||
|
if (typeof gatsbyNode.onPostBuild === 'function') {
|
||||||
|
await gatsbyNode.onPostBuild(args, options);
|
||||||
|
}
|
||||||
|
await vercelBuilder.onPostBuild(args, options);
|
||||||
|
};
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateGatsbyNodeJs(configPath: string) {
|
||||||
|
const renamedPath = `${configPath}.__vercel_builder_backup__.js`;
|
||||||
|
if (!(await fileExists(renamedPath))) {
|
||||||
|
await fs.rename(configPath, renamedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
configPath,
|
||||||
|
`const vercelBuilder = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');
|
||||||
|
const gatsbyNode = require('./gatsby-node.js.__vercel_builder_backup__.js');
|
||||||
|
|
||||||
|
const origOnPostBuild = gatsbyNode.onPostBuild;
|
||||||
|
|
||||||
|
gatsbyNode.onPostBuild = async (args, options) => {
|
||||||
|
if (typeof origOnPostBuild === 'function') {
|
||||||
|
await origOnPostBuild(args, options);
|
||||||
|
}
|
||||||
|
await vercelBuilder.onPostBuild(args, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = gatsbyNode;
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
module.exports = {
|
import type { GatsbyConfig } from 'gatsby';
|
||||||
|
|
||||||
|
const config: GatsbyConfig = {
|
||||||
siteMetadata: {
|
siteMetadata: {
|
||||||
title: `Gatsby Default Starter`,
|
title: `Gatsby Default Starter`,
|
||||||
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
|
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
|
||||||
@@ -33,3 +35,5 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
exports.createPages = async ({ actions }) => {
|
|
||||||
const { createPage } = actions;
|
|
||||||
createPage({
|
|
||||||
path: '/using-dsg',
|
|
||||||
component: require.resolve('./src/templates/using-dsg.js'),
|
|
||||||
context: {},
|
|
||||||
defer: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
12
packages/static-build/test/fixtures/gatsby-v4-pnpm/gatsby-node.ts
vendored
Normal file
12
packages/static-build/test/fixtures/gatsby-v4-pnpm/gatsby-node.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import type { GatsbyNode } from 'gatsby';
|
||||||
|
|
||||||
|
export const createPages: GatsbyNode['createPages'] = async ({ actions }) => {
|
||||||
|
const { createPage } = actions;
|
||||||
|
createPage({
|
||||||
|
path: '/using-dsg',
|
||||||
|
component: path.resolve('./src/templates/using-dsg.js'),
|
||||||
|
context: {},
|
||||||
|
defer: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
1
packages/static-build/test/fixtures/gatsby-v4/asset.txt
vendored
Normal file
1
packages/static-build/test/fixtures/gatsby-v4/asset.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
asset that was added in `onPostBuild`
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
exports.createPages = async ({ actions }) => {
|
exports.createPages = async ({ actions }) => {
|
||||||
const { createPage } = actions;
|
const { createPage } = actions;
|
||||||
createPage({
|
createPage({
|
||||||
@@ -8,3 +10,6 @@ exports.createPages = async ({ actions }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.onPostBuild = async () => {
|
||||||
|
await fs.promises.copyFile('asset.txt', 'public/asset.txt');
|
||||||
|
};
|
||||||
|
|||||||
@@ -21,6 +21,10 @@
|
|||||||
{
|
{
|
||||||
"path": "/page-data/using-dsg/page-data.json",
|
"path": "/page-data/using-dsg/page-data.json",
|
||||||
"mustContain": "\"componentChunkName\":\"component---src-templates-using-dsg-js\",\"path\":\"/using-dsg\""
|
"mustContain": "\"componentChunkName\":\"component---src-templates-using-dsg-js\",\"path\":\"/using-dsg\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/asset.txt",
|
||||||
|
"mustContain": "asset that was added in `onPostBuild`"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user