From f89775149789e453ad33eb49d9d533530290165a Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Sat, 4 Sep 2021 17:50:49 +0200 Subject: [PATCH 01/18] fix(gatsby): reduce page-renderer-size --- packages/gatsby/src/utils/webpack.config.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index 4332cbf1e83d7..6ff3619586625 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -330,6 +330,8 @@ module.exports = async ( function getMode() { switch (stage) { case `develop`: + return `development` + case `build-javascript`: case `develop-html`: return `development` case `build-javascript`: From ccc6d290a2524d1f40b64aa3036dc99cdb1ee371 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Sat, 4 Sep 2021 19:18:19 +0200 Subject: [PATCH 02/18] revert develop-html back to develop --- packages/gatsby/src/utils/webpack.config.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index 6ff3619586625..a487c4147a895 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -330,13 +330,10 @@ module.exports = async ( function getMode() { switch (stage) { case `develop`: - return `development` - case `build-javascript`: case `develop-html`: return `development` case `build-javascript`: case `build-html`: - return `production` default: return `production` } From 51186e6ef9c9c69b6bcbd948c8d99c6f7cdcaa8d Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Sat, 4 Sep 2021 18:23:25 +0200 Subject: [PATCH 03/18] feat(gatsby): split page-renderer per route --- docs/docs/html-generation.md | 2 +- .../cache-dir/ssr-develop-static-entry.js | 5 +- packages/gatsby/cache-dir/static-entry.js | 8 ++- packages/gatsby/src/commands/build-html.ts | 24 ++------- .../gatsby/src/utils/babel-loader-helpers.js | 9 ---- .../src/utils/dev-ssr/render-dev-html.ts | 6 +-- packages/gatsby/src/utils/start-server.ts | 4 +- packages/gatsby/src/utils/webpack.config.js | 53 +++++++------------ 8 files changed, 33 insertions(+), 78 deletions(-) diff --git a/docs/docs/html-generation.md b/docs/docs/html-generation.md index 86e8cb77462a6..0c9b5138c2678 100644 --- a/docs/docs/html-generation.md +++ b/docs/docs/html-generation.md @@ -95,7 +95,7 @@ Finally, we call [react-dom](https://reactjs.org/docs/react-dom.html) and render ## build-html.js -So, we've built the means to generate HTML for a page. This webpack bundle is saved to `public/render-page.js`. Next, we need to use it to generate HTML for all the site's pages. +So, we've built the means to generate HTML for a page. This webpack bundles are saved to `.cache/_routes/`. Next, we need to use it to generate HTML for all the site's pages. Page HTML does not depend on other pages. So we can perform this step in parallel. We use the [jest-worker](https://github.com/facebook/jest/tree/master/packages/jest-worker) library to make this easier. By default, the [render-html.ts](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/worker/render-html.ts) creates a pool of workers equal to the number of physical cores on your machine. You can configure the number of pools by passing an optional environment variable, [`GATSBY_CPU_COUNT`](/docs/multi-core-builds). It then partitions the pages into groups and sends them to the workers, which run [worker](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/worker). diff --git a/packages/gatsby/cache-dir/ssr-develop-static-entry.js b/packages/gatsby/cache-dir/ssr-develop-static-entry.js index e67a275dc05d0..b4e8130397397 100644 --- a/packages/gatsby/cache-dir/ssr-develop-static-entry.js +++ b/packages/gatsby/cache-dir/ssr-develop-static-entry.js @@ -220,9 +220,6 @@ export default async function staticPage( /> ) }) - - const createElement = React.createElement - class RouteHandler extends React.Component { render() { const props = { @@ -239,7 +236,7 @@ export default async function staticPage( syncRequires.ssrComponents[componentChunkName] && !isClientOnlyPage ) { - pageElement = createElement( + pageElement = React.createElement( syncRequires.ssrComponents[componentChunkName], props ) diff --git a/packages/gatsby/cache-dir/static-entry.js b/packages/gatsby/cache-dir/static-entry.js index 4d25353cc9382..c4f1e1b3076b9 100644 --- a/packages/gatsby/cache-dir/static-entry.js +++ b/packages/gatsby/cache-dir/static-entry.js @@ -13,7 +13,7 @@ const { WritableAsPromise } = require(`./server-utils/writable-as-promise`) const { RouteAnnouncerProps } = require(`./route-announcer-props`) const { apiRunner, apiRunnerAsync } = require(`./api-runner-ssr`) -const syncRequires = require(`$virtual/sync-requires`) +const asyncRequires = require(`$virtual/async-requires`) const { version: gatsbyVersion } = require(`gatsby/package.json`) const { grabMatchParams } = require(`./find-path`) @@ -209,6 +209,7 @@ export default async function staticPage({ const pageDataUrl = getPageDataUrl(pagePath) const { componentChunkName, staticQueryHashes = [] } = pageData + const pageComponent = await asyncRequires.components[componentChunkName]() const staticQueryUrls = staticQueryHashes.map(getStaticQueryUrl) @@ -223,10 +224,7 @@ export default async function staticPage({ }, } - const pageElement = createElement( - syncRequires.components[componentChunkName], - props - ) + const pageElement = createElement(pageComponent.default, props) const wrappedPage = apiRunner( `wrapPageElement`, diff --git a/packages/gatsby/src/commands/build-html.ts b/packages/gatsby/src/commands/build-html.ts index 871fc6a13fc98..e378f7939e95d 100644 --- a/packages/gatsby/src/commands/build-html.ts +++ b/packages/gatsby/src/commands/build-html.ts @@ -32,6 +32,7 @@ export interface IBuildArgs extends IProgram { profile: boolean graphqlTracing: boolean openTracingConfigFile: string + // TODO remove in v4 keepPageRenderer: boolean } @@ -124,7 +125,7 @@ const runWebpack = ( } = require(`../utils/dev-ssr/render-dev-html`) // Make sure we use the latest version during development if (oldHash !== `` && newHash !== oldHash) { - restartWorker(`${directory}/public/render-page.js`) + restartWorker(`${directory}/.cache/_routes/render-page.js`) } oldHash = newHash @@ -167,7 +168,7 @@ const doBuildRenderer = async ( // render-page.js is hard coded in webpack.config return { - rendererPath: `${directory}/public/render-page.js`, + rendererPath: `${directory}/.cache/_routes/render-page.js`, waitForCompilerClose, } } @@ -185,15 +186,6 @@ export const buildRenderer = async ( return doBuildRenderer(program, config, stage, parentSpan) } -export const deleteRenderer = async (rendererPath: string): Promise => { - try { - await fs.remove(rendererPath) - await fs.remove(`${rendererPath}.map`) - } catch (e) { - // This function will fail on Windows with no further consequences. - } -} - export interface IRenderHtmlResult { unsafeBuiltinsUsageByPagePath: Record> } @@ -370,7 +362,6 @@ export const buildHTML = async ({ }): Promise => { const { rendererPath } = await buildRenderer(program, stage, activity.span) await doBuildPages(rendererPath, pagePaths, activity, workerPool, stage) - await deleteRenderer(rendererPath) } export async function buildHTMLPagesAndDeleteStaleArtifacts({ @@ -441,15 +432,6 @@ export async function buildHTMLPagesAndDeleteStaleArtifacts({ reporter.info(`There are no new or changed html files to build.`) } - // TODO move to per page builds in _routes directory - if (!program.keepPageRenderer && _CFLAGS_.GATSBY_MAJOR !== `4`) { - try { - await deleteRenderer(pageRenderer) - } catch (err) { - // pass through - } - } - if (toDelete.length > 0) { const publicDir = path.join(program.directory, `public`) const deletePageDataActivityTimer = reporter.activityTimer( diff --git a/packages/gatsby/src/utils/babel-loader-helpers.js b/packages/gatsby/src/utils/babel-loader-helpers.js index 2ba66427ce15b..16c30aa6f09ce 100644 --- a/packages/gatsby/src/utils/babel-loader-helpers.js +++ b/packages/gatsby/src/utils/babel-loader-helpers.js @@ -73,15 +73,6 @@ const prepareOptions = (babel, options = {}, resolve = require.resolve) => { const requiredPresets = [] - // Stage specific plugins to add - if (stage === `build-html` || stage === `develop-html`) { - requiredPlugins.push( - babel.createConfigItem([resolve(`babel-plugin-dynamic-import-node`)], { - type: `plugin`, - }) - ) - } - if (stage === `develop`) { requiredPlugins.push( babel.createConfigItem([resolve(`react-refresh/babel`)], { diff --git a/packages/gatsby/src/utils/dev-ssr/render-dev-html.ts b/packages/gatsby/src/utils/dev-ssr/render-dev-html.ts index 53e182d430cd2..7b1e2b0e1b202 100644 --- a/packages/gatsby/src/utils/dev-ssr/render-dev-html.ts +++ b/packages/gatsby/src/utils/dev-ssr/render-dev-html.ts @@ -112,10 +112,10 @@ const ensurePathComponentInSSRBundle = async ( report.panic(`page not found`, page) } - // Now check if it's written to public/render-page.js + // Now check if it's written to .cache/_routes/render-page.js const htmlComponentRendererPath = nodePath.join( directory, - `public/render-page.js` + `.cache/_routes/render-page.js` ) // This search takes 1-10ms @@ -232,7 +232,7 @@ export const renderDevHTML = ({ }) } - // Wait for public/render-page.js to update w/ the page component. + // Wait for .cache/_routes/render-page.js to update w/ the page component. const found = await ensurePathComponentInSSRBundle(pageObj, directory) // If we can't find the page, just force set isClientOnlyPage diff --git a/packages/gatsby/src/utils/start-server.ts b/packages/gatsby/src/utils/start-server.ts index 3d98563a24f58..5746fb1b8cf5c 100644 --- a/packages/gatsby/src/utils/start-server.ts +++ b/packages/gatsby/src/utils/start-server.ts @@ -601,7 +601,7 @@ module.exports = { page: pathObj, skipSsr: req.query[`skip-ssr`] || false, store, - htmlComponentRendererPath: `${program.directory}/public/render-page.js`, + htmlComponentRendererPath: `${program.directory}/.cache/_routes/render-page.js`, directory: program.directory, }) res.status(200).send(renderResponse) @@ -670,7 +670,7 @@ module.exports = { skipSsr: true, store, error: message, - htmlComponentRendererPath: `${program.directory}/public/render-page.js`, + htmlComponentRendererPath: `${program.directory}/.cache/_routes/render-page.js`, directory: program.directory, }) diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index a487c4147a895..7cf248fc04aa9 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -1,6 +1,5 @@ require(`v8-compile-cache`) -const { isCI } = require(`gatsby-core-utils`) const crypto = require(`crypto`) const fs = require(`fs-extra`) const path = require(`path`) @@ -164,9 +163,12 @@ module.exports = async ( // Generate the file needed to SSR pages. // Deleted by build-html.js, since it's not needed for production. return { - path: directoryPath(`public`), - filename: `render-page.js`, - libraryTarget: `commonjs`, + path: directoryPath(`.cache`, `_routes`), + filename: `[name].js`, + chunkFilename: `[name].js`, + library: { + type: `commonjs`, + }, publicPath: withTrailingSlash(publicPath), } case `build-javascript`: @@ -201,23 +203,15 @@ module.exports = async ( } case `develop-html`: return { - main: process.env.GATSBY_EXPERIMENTAL_DEV_SSR + "render-page": process.env.GATSBY_EXPERIMENTAL_DEV_SSR ? directoryPath(`.cache/ssr-develop-static-entry`) : directoryPath(`.cache/develop-static-entry`), } - case `build-ssr`: { - const entries = Object.create(null) - for (const [, { componentPath, componentChunkName }] of store.getState() - .components) { - entries[componentChunkName] = componentPath - } - - return entries - } - case `build-html`: + case `build-html`: { return { - main: directoryPath(`.cache/static-entry`), + "render-page": directoryPath(`.cache/static-entry`), } + } case `build-javascript`: return hasES6ModuleSupport(directory) ? { @@ -487,11 +481,7 @@ module.exports = async ( } const target = - stage === `build-html` || - stage === `develop-html` || - stage === `build-ssr` - ? `node` - : `web` + stage === `build-html` || stage === `develop-html` ? `node` : `web` if (target === `web`) { resolve.alias[`@reach/router`] = path.join( getPackageRoot(`@gatsbyjs/reach-router`), @@ -554,11 +544,7 @@ module.exports = async ( resolve: getResolve(stage), } - if ( - stage === `build-html` || - stage === `develop-html` || - stage === `build-ssr` - ) { + if (stage === `build-html` || stage === `develop-html`) { const [major, minor] = process.version.replace(`v`, ``).split(`.`) config.target = `node14.15` } else { @@ -606,6 +592,12 @@ module.exports = async ( if (stage === `build-html`) { config.optimization = { + splitChunks: { + cacheGroups: { + default: false, + defaultVendors: false, + }, + }, minimize: false, } } @@ -724,11 +716,7 @@ module.exports = async ( } } - if ( - stage === `build-html` || - stage === `develop-html` || - stage === `build-ssr` - ) { + if (stage === `build-html` || stage === `develop-html`) { // externalize react, react-dom when develop-html or build-html(when not generating engines) const shouldMarkPackagesAsExternal = stage === `develop-html` || @@ -848,7 +836,6 @@ module.exports = async ( if ( stage === `build-javascript` || stage === `build-html` || - stage === `build-ssr` || (process.env.GATSBY_EXPERIMENTAL_DEV_WEBPACK_CACHE && (stage === `develop` || stage === `develop-html`)) ) { @@ -885,7 +872,7 @@ module.exports = async ( await apiRunnerNode(`onCreateWebpackConfig`, { getConfig, // we will converge to build-html later on but for now this was the fastest way to get SSR to work - stage: stage === `build-ssr` ? `build-html` : stage, + stage, rules, loaders, plugins, From 4ab669f65e97db26c34a2b44e2c613d48563102b Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Sun, 5 Sep 2021 22:24:48 +0200 Subject: [PATCH 04/18] Update docs/docs/html-generation.md Co-authored-by: Dan Kirkham --- docs/docs/html-generation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/html-generation.md b/docs/docs/html-generation.md index 0c9b5138c2678..bda753eea1516 100644 --- a/docs/docs/html-generation.md +++ b/docs/docs/html-generation.md @@ -95,7 +95,7 @@ Finally, we call [react-dom](https://reactjs.org/docs/react-dom.html) and render ## build-html.js -So, we've built the means to generate HTML for a page. This webpack bundles are saved to `.cache/_routes/`. Next, we need to use it to generate HTML for all the site's pages. +So, we've built the means to generate HTML for a page. These webpack bundles are saved to `.cache/_routes/`. Next, we need to use it to generate HTML for all the site's pages. Page HTML does not depend on other pages. So we can perform this step in parallel. We use the [jest-worker](https://github.com/facebook/jest/tree/master/packages/jest-worker) library to make this easier. By default, the [render-html.ts](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/worker/render-html.ts) creates a pool of workers equal to the number of physical cores on your machine. You can configure the number of pools by passing an optional environment variable, [`GATSBY_CPU_COUNT`](/docs/multi-core-builds). It then partitions the pages into groups and sends them to the workers, which run [worker](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/worker). From fc70de895db1e69424933617a5317c39a7659f8e Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Mon, 6 Sep 2021 11:08:40 +0200 Subject: [PATCH 05/18] wrap in v4 tags --- packages/gatsby/src/commands/build-html.ts | 22 +++++++++++++++++-- .../gatsby/src/utils/babel-loader-helpers.js | 12 ++++++++++ .../src/utils/dev-ssr/render-dev-html.ts | 8 ++++--- packages/gatsby/src/utils/start-server.ts | 4 ++-- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/packages/gatsby/src/commands/build-html.ts b/packages/gatsby/src/commands/build-html.ts index e378f7939e95d..463aef8e24a46 100644 --- a/packages/gatsby/src/commands/build-html.ts +++ b/packages/gatsby/src/commands/build-html.ts @@ -15,6 +15,7 @@ import { getPageData } from "../utils/get-page-data" import { Span } from "opentracing" import { IProgram, Stage } from "./types" +import { ROUTES_DIRECTORY } from "../constants" import { PackageJson } from "../.." import type { GatsbyWorkerPool } from "../utils/worker/pool" import { IPageDataWithQueryResult } from "../utils/page-data" @@ -125,7 +126,7 @@ const runWebpack = ( } = require(`../utils/dev-ssr/render-dev-html`) // Make sure we use the latest version during development if (oldHash !== `` && newHash !== oldHash) { - restartWorker(`${directory}/.cache/_routes/render-page.js`) + restartWorker(`${directory}/${ROUTES_DIRECTORY}render-page.js`) } oldHash = newHash @@ -168,7 +169,7 @@ const doBuildRenderer = async ( // render-page.js is hard coded in webpack.config return { - rendererPath: `${directory}/.cache/_routes/render-page.js`, + rendererPath: `${directory}/${ROUTES_DIRECTORY}render-page.js`, waitForCompilerClose, } } @@ -186,6 +187,15 @@ export const buildRenderer = async ( return doBuildRenderer(program, config, stage, parentSpan) } +// TODO remove after v4 release and update cloud internals +export const deleteRenderer = async (rendererPath: string): Promise => { + try { + await fs.remove(rendererPath) + await fs.remove(`${rendererPath}.map`) + } catch (e) { + // This function will fail on Windows with no further consequences. + } +} export interface IRenderHtmlResult { unsafeBuiltinsUsageByPagePath: Record> } @@ -432,6 +442,14 @@ export async function buildHTMLPagesAndDeleteStaleArtifacts({ reporter.info(`There are no new or changed html files to build.`) } + if (_CFLAGS_.GATSBY_MAJOR !== `4` && !program.keepPageRenderer) { + try { + await deleteRenderer(pageRenderer) + } catch (err) { + // pass through + } + } + if (toDelete.length > 0) { const publicDir = path.join(program.directory, `public`) const deletePageDataActivityTimer = reporter.activityTimer( diff --git a/packages/gatsby/src/utils/babel-loader-helpers.js b/packages/gatsby/src/utils/babel-loader-helpers.js index 16c30aa6f09ce..4ca388a318dbf 100644 --- a/packages/gatsby/src/utils/babel-loader-helpers.js +++ b/packages/gatsby/src/utils/babel-loader-helpers.js @@ -73,6 +73,18 @@ const prepareOptions = (babel, options = {}, resolve = require.resolve) => { const requiredPresets = [] + // Stage specific plugins to add + if ( + _CFLAGS_.GATSBY_MAJOR !== `4` && + (stage === `build-html` || stage === `develop-html`) + ) { + requiredPlugins.push( + babel.createConfigItem([resolve(`babel-plugin-dynamic-import-node`)], { + type: `plugin`, + }) + ) + } + if (stage === `develop`) { requiredPlugins.push( babel.createConfigItem([resolve(`react-refresh/babel`)], { diff --git a/packages/gatsby/src/utils/dev-ssr/render-dev-html.ts b/packages/gatsby/src/utils/dev-ssr/render-dev-html.ts index 7b1e2b0e1b202..0647075e12c36 100644 --- a/packages/gatsby/src/utils/dev-ssr/render-dev-html.ts +++ b/packages/gatsby/src/utils/dev-ssr/render-dev-html.ts @@ -4,6 +4,7 @@ import nodePath from "path" import report from "gatsby-cli/lib/reporter" import { isCI } from "gatsby-core-utils" import { Stats } from "webpack" +import { ROUTES_DIRECTORY } from "../../constants" import { startListener } from "../../bootstrap/requires-writer" import { findPageByPath } from "../find-page-by-path" import { getPageData as getPageDataExperimental } from "../get-page-data" @@ -112,10 +113,11 @@ const ensurePathComponentInSSRBundle = async ( report.panic(`page not found`, page) } - // Now check if it's written to .cache/_routes/render-page.js + // Now check if it's written to the correct path const htmlComponentRendererPath = nodePath.join( directory, - `.cache/_routes/render-page.js` + ROUTES_DIRECTORY, + `render-page.js` ) // This search takes 1-10ms @@ -232,7 +234,7 @@ export const renderDevHTML = ({ }) } - // Wait for .cache/_routes/render-page.js to update w/ the page component. + // Wait for html-renderer to update w/ the page component. const found = await ensurePathComponentInSSRBundle(pageObj, directory) // If we can't find the page, just force set isClientOnlyPage diff --git a/packages/gatsby/src/utils/start-server.ts b/packages/gatsby/src/utils/start-server.ts index 5746fb1b8cf5c..4ec09a65899d8 100644 --- a/packages/gatsby/src/utils/start-server.ts +++ b/packages/gatsby/src/utils/start-server.ts @@ -601,7 +601,7 @@ module.exports = { page: pathObj, skipSsr: req.query[`skip-ssr`] || false, store, - htmlComponentRendererPath: `${program.directory}/.cache/_routes/render-page.js`, + htmlComponentRendererPath: `${program.directory}/${ROUTES_DIRECTORY}render-page.js`, directory: program.directory, }) res.status(200).send(renderResponse) @@ -670,7 +670,7 @@ module.exports = { skipSsr: true, store, error: message, - htmlComponentRendererPath: `${program.directory}/.cache/_routes/render-page.js`, + htmlComponentRendererPath: `${program.directory}/${ROUTES_DIRECTORY}render-page.js`, directory: program.directory, }) From 4e451a4003c07a3b609f8f7cc9607a4c07af73c4 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Mon, 6 Sep 2021 12:02:43 +0200 Subject: [PATCH 06/18] fix --- packages/gatsby/src/utils/webpack.config.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index 7cf248fc04aa9..7428873a0c54c 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -163,7 +163,10 @@ module.exports = async ( // Generate the file needed to SSR pages. // Deleted by build-html.js, since it's not needed for production. return { - path: directoryPath(`.cache`, `_routes`), + path: + _CFLAGS_.GATSBY_MAJOR === `4` + ? directoryPath(`.cache`, `_routes`) + : directoryPath(`public`), filename: `[name].js`, chunkFilename: `[name].js`, library: { From 209b5641dcc27d291c65720407844c93d585e54f Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Mon, 6 Sep 2021 14:46:46 +0200 Subject: [PATCH 07/18] fix tests --- packages/gatsby/cache-dir/__tests__/static-entry.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/gatsby/cache-dir/__tests__/static-entry.js b/packages/gatsby/cache-dir/__tests__/static-entry.js index 1230d314885b9..0f0077bc8d54e 100644 --- a/packages/gatsby/cache-dir/__tests__/static-entry.js +++ b/packages/gatsby/cache-dir/__tests__/static-entry.js @@ -34,11 +34,14 @@ jest.mock( ) jest.mock( - `$virtual/sync-requires`, + `$virtual/async-requires`, () => { return { components: { - "page-component---src-pages-test-js": () => null, + "page-component---src-pages-test-js": () => + Promise.resolve({ + default: () => null, + }), }, } }, From e7c8ba20d58aaf4d063acb41f9ba87f712d9a932 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Sat, 11 Sep 2021 16:16:38 +0200 Subject: [PATCH 08/18] move back to build-html --- packages/gatsby/src/commands/build.ts | 29 --------------------- packages/gatsby/src/commands/types.ts | 2 -- packages/gatsby/src/utils/webpack.config.js | 23 +++------------- 3 files changed, 4 insertions(+), 50 deletions(-) diff --git a/packages/gatsby/src/commands/build.ts b/packages/gatsby/src/commands/build.ts index 893b7e4a10cc1..5eacc05a57dff 100644 --- a/packages/gatsby/src/commands/build.ts +++ b/packages/gatsby/src/commands/build.ts @@ -274,35 +274,6 @@ module.exports = async function build(program: IBuildArgs): Promise { } }) } - - // TODO Move to page-renderer - if (_CFLAGS_.GATSBY_MAJOR === `4`) { - const routesWebpackConfig = await webpackConfig( - program, - program.directory, - `build-ssr`, - null, - { parentSpan: buildSSRBundleActivityProgress.span } - ) - - await new Promise((resolve, reject) => { - const compiler = webpack(routesWebpackConfig) - compiler.run(err => { - if (err) { - return void reject(err) - } - - compiler.close(error => { - if (error) { - return void reject(error) - } - return void resolve(undefined) - }) - - return undefined - }) - }) - } } catch (err) { buildActivityTimer.panic(structureWebpackErrors(Stage.BuildHTML, err)) } finally { diff --git a/packages/gatsby/src/commands/types.ts b/packages/gatsby/src/commands/types.ts index a2de901f79085..1cc9c692aef7c 100644 --- a/packages/gatsby/src/commands/types.ts +++ b/packages/gatsby/src/commands/types.ts @@ -50,6 +50,4 @@ export enum Stage { DevelopHTML = `develop-html`, BuildJavascript = `build-javascript`, BuildHTML = `build-html`, - // TODO move to BuildHTML when queryengine pieces are merged - SSR = `build-ssr`, } diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index 7428873a0c54c..ff6f742903485 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -46,16 +46,12 @@ module.exports = async ( // we will converge to build-html later on but for now this was the fastest way to get SSR to work // TODO remove in v4 - we deprecated this in v3 - process.env.GATSBY_BUILD_STAGE = - suppliedStage === `build-ssr` ? `build-html` : suppliedStage + process.env.GATSBY_BUILD_STAGE = suppliedStage // We combine develop & develop-html stages for purposes of generating the // webpack config. const stage = suppliedStage - const { rules, loaders, plugins } = createWebpackUtils( - suppliedStage === `build-ssr` ? `build-html` : stage, - program - ) + const { rules, loaders, plugins } = createWebpackUtils(stage, program) const { assetPrefix, pathPrefix } = store.getState().config @@ -97,9 +93,7 @@ module.exports = async ( // Don't allow overwriting of NODE_ENV, PUBLIC_DIR as to not break gatsby things envObject.NODE_ENV = JSON.stringify(nodeEnv) envObject.PUBLIC_DIR = JSON.stringify(`${process.cwd()}/public`) - envObject.BUILD_STAGE = JSON.stringify( - stage === `build-ssr` ? `build-html` : stage - ) + envObject.BUILD_STAGE = JSON.stringify(stage) envObject.CYPRESS_SUPPORT = JSON.stringify(process.env.CYPRESS_SUPPORT) envObject.GATSBY_EXPERIMENTAL_QUERY_ON_DEMAND = JSON.stringify( !!process.env.GATSBY_EXPERIMENTAL_QUERY_ON_DEMAND @@ -165,7 +159,7 @@ module.exports = async ( return { path: _CFLAGS_.GATSBY_MAJOR === `4` - ? directoryPath(`.cache`, `_routes`) + ? directoryPath(ROUTES_DIRECTORY) : directoryPath(`public`), filename: `[name].js`, chunkFilename: `[name].js`, @@ -181,13 +175,6 @@ module.exports = async ( path: directoryPath(`public`), publicPath: withTrailingSlash(publicPath), } - case `build-ssr`: { - return { - path: directoryPath(ROUTES_DIRECTORY), - filename: `[name].js`, - libraryTarget: `commonjs2`, - } - } default: throw new Error(`The state requested ${stage} doesn't exist.`) } @@ -316,7 +303,6 @@ module.exports = async ( // it gives better line and column numbers case `develop-html`: case `build-html`: - case `build-ssr`: case `build-javascript`: return `source-map` default: @@ -410,7 +396,6 @@ module.exports = async ( } case `build-html`: case `develop-html`: - case `build-ssr`: // We don't deal with CSS at all when building the HTML. // The 'null' loader is used to prevent 'module not found' errors. // On the other hand CSS modules loaders are necessary. From 1061d9937c5f8a6a2758b72212843cd569195f72 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Sat, 11 Sep 2021 16:19:24 +0200 Subject: [PATCH 09/18] use cflags for directory --- packages/gatsby/src/constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/gatsby/src/constants.ts b/packages/gatsby/src/constants.ts index ce536b612c24c..40fb9333274e3 100644 --- a/packages/gatsby/src/constants.ts +++ b/packages/gatsby/src/constants.ts @@ -1 +1,2 @@ -export const ROUTES_DIRECTORY = `.cache/page-ssr/routes` +export const ROUTES_DIRECTORY = + _CFLAGS_.GATSBY_MAJOR === `4` ? `.cache/page-ssr/routes` : `public` From 015ceb94de8241f8fd920e6d0b46413422fa4486 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Sun, 12 Sep 2021 14:30:17 +0200 Subject: [PATCH 10/18] remove ssr bundle and use build-html instead --- packages/gatsby/src/commands/build.ts | 16 ---------------- packages/gatsby/src/constants.ts | 2 +- .../src/utils/page-ssr-module/bundle-webpack.ts | 2 +- .../gatsby/src/utils/page-ssr-module/entry.ts | 9 +++------ packages/gatsby/src/utils/start-server.ts | 8 ++++++-- packages/gatsby/src/utils/webpack-error-utils.ts | 2 -- packages/gatsby/src/utils/webpack.config.js | 5 +---- 7 files changed, 12 insertions(+), 32 deletions(-) diff --git a/packages/gatsby/src/commands/build.ts b/packages/gatsby/src/commands/build.ts index 5eacc05a57dff..871b3c65cbd5c 100644 --- a/packages/gatsby/src/commands/build.ts +++ b/packages/gatsby/src/commands/build.ts @@ -47,8 +47,6 @@ import { mergeWorkerState, runQueriesInWorkersQueue, } from "../utils/worker/pool" -import webpackConfig from "../utils/webpack.config.js" -import { webpack } from "webpack" import { createGraphqlEngineBundle } from "../schema/graphql-engine/bundle-webpack" import { createPageSSRBundle } from "../utils/page-ssr-module/bundle-webpack" import { shouldGenerateEngines } from "../utils/engines-helpers" @@ -246,20 +244,6 @@ module.exports = async function build(program: IBuildArgs): Promise { buildSSRBundleActivityProgress.span ) pageRenderer = result.rendererPath - if (_CFLAGS_.GATSBY_MAJOR === `4` && shouldGenerateEngines()) { - // for now copy page-render to `.cache` so page-ssr module can require it as a sibling module - const outputDir = path.join(program.directory, `.cache`, `page-ssr`) - engineBundlingPromises.push( - fs - .ensureDir(outputDir) - .then(() => - fs.copyFile( - result.rendererPath, - path.join(outputDir, `render-page.js`) - ) - ) - ) - } waitForCompilerCloseBuildHtml = result.waitForCompilerClose if (_CFLAGS_.GATSBY_MAJOR === `4` && shouldGenerateEngines()) { diff --git a/packages/gatsby/src/constants.ts b/packages/gatsby/src/constants.ts index 40fb9333274e3..2464657180d37 100644 --- a/packages/gatsby/src/constants.ts +++ b/packages/gatsby/src/constants.ts @@ -1,2 +1,2 @@ export const ROUTES_DIRECTORY = - _CFLAGS_.GATSBY_MAJOR === `4` ? `.cache/page-ssr/routes` : `public` + _CFLAGS_.GATSBY_MAJOR === `4` ? `.cache/page-ssr/routes/` : `public/` diff --git a/packages/gatsby/src/utils/page-ssr-module/bundle-webpack.ts b/packages/gatsby/src/utils/page-ssr-module/bundle-webpack.ts index 4a77280f33b80..a0c8775ebb668 100644 --- a/packages/gatsby/src/utils/page-ssr-module/bundle-webpack.ts +++ b/packages/gatsby/src/utils/page-ssr-module/bundle-webpack.ts @@ -54,7 +54,7 @@ export async function createPageSSRBundle(): Promise { }, // those are required in some runtime paths, but we don't need them externals: [ - `./render-page`, + /^\.\/routes/, `electron`, // :shrug: `got` seems to have electron specific code path mod.builtinModules.reduce((acc, builtinModule) => { if (builtinModule === `fs`) { diff --git a/packages/gatsby/src/utils/page-ssr-module/entry.ts b/packages/gatsby/src/utils/page-ssr-module/entry.ts index fe5ed8524eae3..03ccd3f5d19f7 100644 --- a/packages/gatsby/src/utils/page-ssr-module/entry.ts +++ b/packages/gatsby/src/utils/page-ssr-module/entry.ts @@ -15,8 +15,8 @@ import { getPagePathFromPageDataPath, } from "../page-data-helpers" // @ts-ignore render-page import will become valid later on (it's marked as external) -import htmlComponentRenderer from "./render-page" -import { getServerData, IServerData } from "../get-server-data" +import htmlComponentRenderer from "./routes/render-page" +import { getServerData } from "../get-server-data" export interface ITemplateDetails { query: string @@ -37,9 +37,6 @@ const pageTemplateDetailsMap: Record< // @ts-ignore INLINED_TEMPLATE_TO_DETAILS is being "inlined" by bundler > = INLINED_TEMPLATE_TO_DETAILS -// eslint-disable-next-line @typescript-eslint/naming-convention -declare const __non_webpack_require__: typeof require - export async function getData({ pathName, graphqlEngine, @@ -88,7 +85,7 @@ export async function getData({ // 4. (if SSR) run getServerData if (page.mode === `SSR`) { - const mod = __non_webpack_require__(`./routes/${page.componentChunkName}`) + const mod = require(`./routes/${page.componentChunkName}`) executionPromises.push( getServerData(req, page, potentialPagePath, mod).then( serverDataResults => { diff --git a/packages/gatsby/src/utils/start-server.ts b/packages/gatsby/src/utils/start-server.ts index 4ec09a65899d8..aeef437f07d98 100644 --- a/packages/gatsby/src/utils/start-server.ts +++ b/packages/gatsby/src/utils/start-server.ts @@ -177,7 +177,7 @@ module.exports = { const serverDevConfig = await webpackConfig( program, directory, - Stage.SSR, + Stage.BuildHTML, program.port, { parentSpan: webpackActivity.span, @@ -368,7 +368,11 @@ module.exports = { .get(page.componentChunkName)! .getEntrypointChunk().hash as string const modulePath = path.resolve( - `${program.directory}/${ROUTES_DIRECTORY}/${page.componentChunkName}.js` + path.posix.join( + program.directory, + ROUTES_DIRECTORY, + `${page.componentChunkName}.js` + ) ) // if webpack compilation is diff we delete old cache diff --git a/packages/gatsby/src/utils/webpack-error-utils.ts b/packages/gatsby/src/utils/webpack-error-utils.ts index 4349297bd3a27..ac16ce191921a 100644 --- a/packages/gatsby/src/utils/webpack-error-utils.ts +++ b/packages/gatsby/src/utils/webpack-error-utils.ts @@ -6,8 +6,6 @@ import formatWebpackMessages from "react-dev-utils/formatWebpackMessages" const stageCodeToReadableLabel: Record = { [StageEnum.BuildJavascript]: `Generating JavaScript bundles`, [StageEnum.BuildHTML]: `Generating SSR bundle`, - // TODO remove when part of buildhtml - [StageEnum.SSR]: `Generating SSR bundle`, [StageEnum.DevelopHTML]: `Generating development SSR bundle`, [StageEnum.Develop]: `Generating development JavaScript bundle`, } diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index ff6f742903485..26a2a3b0128dd 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -157,10 +157,7 @@ module.exports = async ( // Generate the file needed to SSR pages. // Deleted by build-html.js, since it's not needed for production. return { - path: - _CFLAGS_.GATSBY_MAJOR === `4` - ? directoryPath(ROUTES_DIRECTORY) - : directoryPath(`public`), + path: directoryPath(ROUTES_DIRECTORY), filename: `[name].js`, chunkFilename: `[name].js`, library: { From 15b8edcbfa2e4d95327aed11430153227b8c5c8e Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Sun, 12 Sep 2021 14:33:28 +0200 Subject: [PATCH 11/18] use path.posix --- packages/gatsby/src/utils/start-server.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/gatsby/src/utils/start-server.ts b/packages/gatsby/src/utils/start-server.ts index aeef437f07d98..4ba3e57939d7f 100644 --- a/packages/gatsby/src/utils/start-server.ts +++ b/packages/gatsby/src/utils/start-server.ts @@ -605,7 +605,11 @@ module.exports = { page: pathObj, skipSsr: req.query[`skip-ssr`] || false, store, - htmlComponentRendererPath: `${program.directory}/${ROUTES_DIRECTORY}render-page.js`, + htmlComponentRendererPath: path.posix.join( + program.directory, + ROUTES_DIRECTORY, + `render-page.js` + ), directory: program.directory, }) res.status(200).send(renderResponse) @@ -674,7 +678,11 @@ module.exports = { skipSsr: true, store, error: message, - htmlComponentRendererPath: `${program.directory}/${ROUTES_DIRECTORY}render-page.js`, + htmlComponentRendererPath: path.posix.join( + program.directory, + ROUTES_DIRECTORY, + `render-page.js` + ), directory: program.directory, }) From 6137929e265116778b2324fe0b4db809366f5640 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Mon, 13 Sep 2021 10:15:31 +0200 Subject: [PATCH 12/18] Fix develop to use getPageChunk --- .../gatsby/cache-dir/develop-static-entry.js | 6 + packages/gatsby/cache-dir/static-entry.js | 4 + .../gatsby/src/bootstrap/requires-writer.ts | 5 +- packages/gatsby/src/utils/flags.ts | 18 +-- .../gatsby/src/utils/page-ssr-module/entry.ts | 11 +- packages/gatsby/src/utils/start-server.ts | 123 +++++------------- packages/gatsby/src/utils/webpack.config.js | 2 +- 7 files changed, 56 insertions(+), 113 deletions(-) diff --git a/packages/gatsby/cache-dir/develop-static-entry.js b/packages/gatsby/cache-dir/develop-static-entry.js index ded207cd426fb..78c04d8e11b4d 100644 --- a/packages/gatsby/cache-dir/develop-static-entry.js +++ b/packages/gatsby/cache-dir/develop-static-entry.js @@ -3,6 +3,8 @@ import React from "react" import { renderToStaticMarkup } from "react-dom/server" import { merge } from "lodash" import { apiRunner } from "./api-runner-ssr" +import asyncRequires from "$virtual/async-requires" + // import testRequireError from "./test-require-error" // For some extremely mysterious reason, webpack adds the above module *after* // this module so that when this code runs, testRequireError is undefined. @@ -125,3 +127,7 @@ export default ({ pagePath }) => { return htmlStr } + +export function getPageChunk({ componentChunkName }) { + return asyncRequires.components[componentChunkName]() +} diff --git a/packages/gatsby/cache-dir/static-entry.js b/packages/gatsby/cache-dir/static-entry.js index c4f1e1b3076b9..7b3a89108f9a9 100644 --- a/packages/gatsby/cache-dir/static-entry.js +++ b/packages/gatsby/cache-dir/static-entry.js @@ -477,3 +477,7 @@ export default async function staticPage({ throw e } } + +export function getPageChunk({ componentChunkName }) { + return asyncRequires.components[componentChunkName]() +} diff --git a/packages/gatsby/src/bootstrap/requires-writer.ts b/packages/gatsby/src/bootstrap/requires-writer.ts index 58afcaf4d7baa..4b2cd8119105d 100644 --- a/packages/gatsby/src/bootstrap/requires-writer.ts +++ b/packages/gatsby/src/bootstrap/requires-writer.ts @@ -249,10 +249,7 @@ const preferDefault = m => (m && m.default) || m }\n\n` // Create file with async requires of components/json files. - let asyncRequires = `// prefer default export if available -const preferDefault = m => (m && m.default) || m -\n` - asyncRequires += `exports.components = {\n${components + const asyncRequires = `exports.components = {\n${components .map((c: IGatsbyPageComponent): string => { // we need a relative import path to keep contenthash the same if directory changes const relativeComponentPath = path.relative( diff --git a/packages/gatsby/src/utils/flags.ts b/packages/gatsby/src/utils/flags.ts index 3899a8d6ee66e..33d4f0cb36d6d 100644 --- a/packages/gatsby/src/utils/flags.ts +++ b/packages/gatsby/src/utils/flags.ts @@ -1,7 +1,7 @@ import _ from "lodash" import semver from "semver" -import sampleSiteForExperiment from "./sample-site-for-experiment" +// import sampleSiteForExperiment from "./sample-site-for-experiment" // Does this experiment run for only builds type executingCommand = "build" | "develop" | "all" @@ -101,13 +101,15 @@ const activeFlags: Array = [ experimental: false, description: `Server Side Render (SSR) pages on full reloads during develop. Helps you detect SSR bugs and fix them without needing to do full builds. See umbrella issue for how to update custom webpack config.`, umbrellaIssue: `https://gatsby.dev/dev-ssr-feedback`, - testFitness: (): fitnessEnum => { - if (sampleSiteForExperiment(`DEV_SSR`, 20)) { - return `OPT_IN` - } else { - return true - } - }, + testFitness: (): fitnessEnum => false, + // testFitness: (): fitnessEnum => { + // // TODO Re-enable after gatsybcamp + // if (sampleSiteForExperiment(`DEV_SSR`, 20)) { + // return `OPT_IN` + // } else { + // return true + // } + // }, }, { name: `QUERY_ON_DEMAND`, diff --git a/packages/gatsby/src/utils/page-ssr-module/entry.ts b/packages/gatsby/src/utils/page-ssr-module/entry.ts index 03ccd3f5d19f7..ce15717cadd0c 100644 --- a/packages/gatsby/src/utils/page-ssr-module/entry.ts +++ b/packages/gatsby/src/utils/page-ssr-module/entry.ts @@ -15,7 +15,7 @@ import { getPagePathFromPageDataPath, } from "../page-data-helpers" // @ts-ignore render-page import will become valid later on (it's marked as external) -import htmlComponentRenderer from "./routes/render-page" +import htmlComponentRenderer, { getPageChunk } from "./routes/render-page" import { getServerData } from "../get-server-data" export interface ITemplateDetails { @@ -85,13 +85,12 @@ export async function getData({ // 4. (if SSR) run getServerData if (page.mode === `SSR`) { - const mod = require(`./routes/${page.componentChunkName}`) executionPromises.push( - getServerData(req, page, potentialPagePath, mod).then( - serverDataResults => { + getPageChunk(page) + .then(mod => getServerData(req, page, potentialPagePath, mod)) + .then(serverDataResults => { serverData = serverDataResults - } - ) + }) ) } diff --git a/packages/gatsby/src/utils/start-server.ts b/packages/gatsby/src/utils/start-server.ts index 4ba3e57939d7f..26d20b2531cca 100644 --- a/packages/gatsby/src/utils/start-server.ts +++ b/packages/gatsby/src/utils/start-server.ts @@ -52,7 +52,6 @@ import { writeVirtualLoadingIndicatorModule, } from "./loading-indicator" import { renderDevHTML } from "./dev-ssr/render-dev-html" -import pDefer from "p-defer" import { getServerData, IServerData } from "./get-server-data" import { ROUTES_DIRECTORY } from "../constants" @@ -79,6 +78,11 @@ export async function startServer( workerPool: WorkerPool.GatsbyWorkerPool = WorkerPool.create() ): Promise { const directory = program.directory + const PAGE_RENDERER_PATH = path.join( + program.directory, + ROUTES_DIRECTORY, + `render-page.js` + ) const webpackActivity = report.activityTimer(`Building development bundle`, { id: `webpack-develop`, @@ -171,38 +175,6 @@ module.exports = { ) const compiler = webpack(devConfig) - let waitForServerCompilation = (): Promise => - Promise.resolve(undefined) - if (_CFLAGS_.GATSBY_MAJOR === `4`) { - const serverDevConfig = await webpackConfig( - program, - directory, - Stage.BuildHTML, - program.port, - { - parentSpan: webpackActivity.span, - } - ) - const serverCompiler = webpack(serverDevConfig) - - const waitForServerCompilationDeferred = pDefer() - waitForServerCompilation = (): Promise => - waitForServerCompilationDeferred.promise - let compileCounter = 0 - serverCompiler.watch( - { - ignored: /node_modules/, - }, - (_, stats) => { - if (compileCounter++ > 0) { - waitForServerCompilation = (): Promise => - Promise.resolve(stats as webpack.Stats) - } else { - waitForServerCompilationDeferred.resolve(stats) - } - } - ) - } /** * Set up the express app. @@ -333,7 +305,20 @@ module.exports = { res.end() }) - const previousHashes: Map = new Map() + // Disable directory indexing i.e. serving index.html from a directory. + // This can lead to serving stale html files during development. + // + // We serve by default an empty index.html that sets up the dev environment. + app.use(developStatic(`public`, { index: false })) + + const webpackDevMiddlewareInstance = webpackDevMiddleware(compiler, { + publicPath: devConfig.output.publicPath, + stats: `errors-only`, + serverSideRender: true, + }) + + app.use(webpackDevMiddlewareInstance) + app.get( `/page-data/:pagePath(*)/page-data.json`, async (req, res, next): Promise => { @@ -351,43 +336,15 @@ module.exports = { let serverDataPromise: Promise = Promise.resolve({}) if (page.mode === `SSR`) { - // get dynamic serverModule$ - const stats = await waitForServerCompilation() - - if ( - !stats || - !stats.compilation.entrypoints.has(page.componentChunkName) - ) { - report.error( - `Error loading a result for the page query in "${requestedPagePath}" / "${potentialPagePath}". getServerData threw an error.` - ) - } - - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const componentHash = stats!.compilation.entrypoints - .get(page.componentChunkName)! - .getEntrypointChunk().hash as string - const modulePath = path.resolve( - path.posix.join( - program.directory, - ROUTES_DIRECTORY, - `${page.componentChunkName}.js` - ) + const renderer = require(PAGE_RENDERER_PATH) + const componentInstance = await renderer.getPageChunk(page) + + serverDataPromise = getServerData( + req, + page, + potentialPagePath, + componentInstance ) - - // if webpack compilation is diff we delete old cache - if ( - previousHashes.has(page.componentChunkName) && - previousHashes.get(page.componentChunkName) === componentHash - ) { - delete require.cache[modulePath] - } - - const mod = require(modulePath) - - previousHashes.set(page.componentChunkName, componentHash) - - serverDataPromise = getServerData(req, page, potentialPagePath, mod) } let pageData: IPageDataWithQueryResult @@ -431,20 +388,6 @@ module.exports = { } ) - // Disable directory indexing i.e. serving index.html from a directory. - // This can lead to serving stale html files during development. - // - // We serve by default an empty index.html that sets up the dev environment. - app.use(developStatic(`public`, { index: false })) - - const webpackDevMiddlewareInstance = webpackDevMiddleware(compiler, { - publicPath: devConfig.output.publicPath, - stats: `errors-only`, - serverSideRender: true, - }) - - app.use(webpackDevMiddlewareInstance) - app.get(`/__original-stack-frame`, async (req, res) => { const compilation = res.locals?.webpack?.devMiddleware?.stats?.compilation const emptyResponse = { @@ -605,11 +548,7 @@ module.exports = { page: pathObj, skipSsr: req.query[`skip-ssr`] || false, store, - htmlComponentRendererPath: path.posix.join( - program.directory, - ROUTES_DIRECTORY, - `render-page.js` - ), + htmlComponentRendererPath: PAGE_RENDERER_PATH, directory: program.directory, }) res.status(200).send(renderResponse) @@ -678,11 +617,7 @@ module.exports = { skipSsr: true, store, error: message, - htmlComponentRendererPath: path.posix.join( - program.directory, - ROUTES_DIRECTORY, - `render-page.js` - ), + htmlComponentRendererPath: PAGE_RENDERER_PATH, directory: program.directory, }) diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index 26a2a3b0128dd..6df476d8f57d7 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -575,7 +575,7 @@ module.exports = async ( } } - if (stage === `build-html`) { + if (stage === `build-html` || stage === `develop-html`) { config.optimization = { splitChunks: { cacheGroups: { From 4a89aa574aa1a32471e80a6ecddcb6bf7f0fc03d Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Mon, 13 Sep 2021 11:54:27 +0200 Subject: [PATCH 13/18] only disable ssr on v4 --- packages/gatsby/src/utils/flags.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/gatsby/src/utils/flags.ts b/packages/gatsby/src/utils/flags.ts index 33d4f0cb36d6d..c5295f9d03518 100644 --- a/packages/gatsby/src/utils/flags.ts +++ b/packages/gatsby/src/utils/flags.ts @@ -1,7 +1,7 @@ import _ from "lodash" import semver from "semver" -// import sampleSiteForExperiment from "./sample-site-for-experiment" +import sampleSiteForExperiment from "./sample-site-for-experiment" // Does this experiment run for only builds type executingCommand = "build" | "develop" | "all" @@ -101,15 +101,18 @@ const activeFlags: Array = [ experimental: false, description: `Server Side Render (SSR) pages on full reloads during develop. Helps you detect SSR bugs and fix them without needing to do full builds. See umbrella issue for how to update custom webpack config.`, umbrellaIssue: `https://gatsby.dev/dev-ssr-feedback`, - testFitness: (): fitnessEnum => false, - // testFitness: (): fitnessEnum => { - // // TODO Re-enable after gatsybcamp - // if (sampleSiteForExperiment(`DEV_SSR`, 20)) { - // return `OPT_IN` - // } else { - // return true - // } - // }, + testFitness: (): fitnessEnum => { + // TODO Re-enable after gatsybcamp + if (_CFLAGS_.GATSBY_MAJOR === `4`) { + return false + } + + if (sampleSiteForExperiment(`DEV_SSR`, 20)) { + return `OPT_IN` + } else { + return true + } + }, }, { name: `QUERY_ON_DEMAND`, From 0cdad1a415a1e106a5aa2e3ad5dd51afd8235572 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Tue, 14 Sep 2021 17:46:50 +0200 Subject: [PATCH 14/18] move static middleware --- packages/gatsby/src/utils/start-server.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/gatsby/src/utils/start-server.ts b/packages/gatsby/src/utils/start-server.ts index 26d20b2531cca..2e75c773d851a 100644 --- a/packages/gatsby/src/utils/start-server.ts +++ b/packages/gatsby/src/utils/start-server.ts @@ -305,12 +305,6 @@ module.exports = { res.end() }) - // Disable directory indexing i.e. serving index.html from a directory. - // This can lead to serving stale html files during development. - // - // We serve by default an empty index.html that sets up the dev environment. - app.use(developStatic(`public`, { index: false })) - const webpackDevMiddlewareInstance = webpackDevMiddleware(compiler, { publicPath: devConfig.output.publicPath, stats: `errors-only`, @@ -477,6 +471,12 @@ module.exports = { developMiddleware(app, program) } + // Disable directory indexing i.e. serving index.html from a directory. + // This can lead to serving stale html files during development. + // + // We serve by default an empty index.html that sets up the dev environment. + app.use(developStatic(`public`, { index: false })) + // Set up API proxy. const { proxy } = store.getState().config if (proxy) { From 4035482493c5688f9c939f9cac92d3741b544979 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Tue, 14 Sep 2021 18:05:22 +0200 Subject: [PATCH 15/18] update type --- packages/gatsby/src/utils/page-ssr-module/entry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/gatsby/src/utils/page-ssr-module/entry.ts b/packages/gatsby/src/utils/page-ssr-module/entry.ts index ce15717cadd0c..221244265a970 100644 --- a/packages/gatsby/src/utils/page-ssr-module/entry.ts +++ b/packages/gatsby/src/utils/page-ssr-module/entry.ts @@ -16,7 +16,7 @@ import { } from "../page-data-helpers" // @ts-ignore render-page import will become valid later on (it's marked as external) import htmlComponentRenderer, { getPageChunk } from "./routes/render-page" -import { getServerData } from "../get-server-data" +import { getServerData, IServerData } from "../get-server-data" export interface ITemplateDetails { query: string From 6cd417eb2ff28d3dda0df193d224d146de89bde6 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Tue, 14 Sep 2021 21:27:00 +0200 Subject: [PATCH 16/18] don't use pageRenderer arg in buildHTMLPagesAndDeleteStaleArtifacts --- packages/gatsby/src/commands/build-html.ts | 3 +-- packages/gatsby/src/commands/build.ts | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/gatsby/src/commands/build-html.ts b/packages/gatsby/src/commands/build-html.ts index 463aef8e24a46..b51488f0c0b3e 100644 --- a/packages/gatsby/src/commands/build-html.ts +++ b/packages/gatsby/src/commands/build-html.ts @@ -375,12 +375,10 @@ export const buildHTML = async ({ } export async function buildHTMLPagesAndDeleteStaleArtifacts({ - pageRenderer, workerPool, buildSpan, program, }: { - pageRenderer: string workerPool: GatsbyWorkerPool buildSpan?: Span program: IBuildArgs @@ -388,6 +386,7 @@ export async function buildHTMLPagesAndDeleteStaleArtifacts({ toRegenerate: Array toDelete: Array }> { + const pageRenderer = `${program.directory}/${ROUTES_DIRECTORY}render-page.js` buildUtils.markHtmlDirtyIfResultOfUsedStaticQueryChanged() const { toRegenerate, toDelete, toCleanupFromTrackedState } = diff --git a/packages/gatsby/src/commands/build.ts b/packages/gatsby/src/commands/build.ts index 871b3c65cbd5c..149ad188ffdf2 100644 --- a/packages/gatsby/src/commands/build.ts +++ b/packages/gatsby/src/commands/build.ts @@ -274,7 +274,6 @@ module.exports = async function build(program: IBuildArgs): Promise { const { toRegenerate, toDelete } = await buildHTMLPagesAndDeleteStaleArtifacts({ program, - pageRenderer, workerPool, buildSpan, }) From 40a7fe20721aaa91908185cbfebdbb44050c9e6c Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Tue, 14 Sep 2021 21:34:14 +0200 Subject: [PATCH 17/18] drop unused var --- packages/gatsby/src/commands/build.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/gatsby/src/commands/build.ts b/packages/gatsby/src/commands/build.ts index 149ad188ffdf2..d8ece16af015d 100644 --- a/packages/gatsby/src/commands/build.ts +++ b/packages/gatsby/src/commands/build.ts @@ -235,7 +235,6 @@ module.exports = async function build(program: IBuildArgs): Promise { { parentSpan: buildSpan } ) buildSSRBundleActivityProgress.start() - let pageRenderer = `` let waitForCompilerCloseBuildHtml try { const result = await buildRenderer( @@ -243,7 +242,6 @@ module.exports = async function build(program: IBuildArgs): Promise { Stage.BuildHTML, buildSSRBundleActivityProgress.span ) - pageRenderer = result.rendererPath waitForCompilerCloseBuildHtml = result.waitForCompilerClose if (_CFLAGS_.GATSBY_MAJOR === `4` && shouldGenerateEngines()) { From 5b92ce6a194fe1a8772d1bb920f9171b2aa7e0b7 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Tue, 14 Sep 2021 21:51:32 +0200 Subject: [PATCH 18/18] Update docs/docs/html-generation.md Co-authored-by: Michal Piechowiak --- docs/docs/html-generation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/html-generation.md b/docs/docs/html-generation.md index bda753eea1516..6ca0c6a1cb560 100644 --- a/docs/docs/html-generation.md +++ b/docs/docs/html-generation.md @@ -95,7 +95,7 @@ Finally, we call [react-dom](https://reactjs.org/docs/react-dom.html) and render ## build-html.js -So, we've built the means to generate HTML for a page. These webpack bundles are saved to `.cache/_routes/`. Next, we need to use it to generate HTML for all the site's pages. +So, we've built the means to generate HTML for a page. These webpack bundles are saved to `.cache/page-ssr/routes`. Next, we need to use it to generate HTML for all the site's pages. Page HTML does not depend on other pages. So we can perform this step in parallel. We use the [jest-worker](https://github.com/facebook/jest/tree/master/packages/jest-worker) library to make this easier. By default, the [render-html.ts](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/worker/render-html.ts) creates a pool of workers equal to the number of physical cores on your machine. You can configure the number of pools by passing an optional environment variable, [`GATSBY_CPU_COUNT`](/docs/multi-core-builds). It then partitions the pages into groups and sends them to the workers, which run [worker](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/worker).