Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow dsg/ssr renders without access to datastore if it's not required #38974

Merged
merged 13 commits into from
May 17, 2024
Merged
8 changes: 4 additions & 4 deletions e2e-tests/adapters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
"develop:debug": "start-server-and-test develop http://localhost:8000 'npm run cy:open -- --config baseUrl=http://localhost:8000'",
"ssat:debug": "start-server-and-test serve http://localhost:9000 cy:open",
"test:template": "cross-env-shell CYPRESS_GROUP_NAME=\"adapter:$ADAPTER / trailingSlash:${TRAILING_SLASH:-always} / pathPrefix:${PATH_PREFIX:--}\" TRAILING_SLASH=$TRAILING_SLASH PATH_PREFIX=$PATH_PREFIX node ../../scripts/cypress-run-with-conditional-record-flag.js --browser chrome --e2e --config-file \"cypress/configs/$ADAPTER.ts\" --env TRAILING_SLASH=$TRAILING_SLASH,PATH_PREFIX=$PATH_PREFIX",
"test:template:debug": "cross-env-shell CYPRESS_GROUP_NAME=\"adapter:$ADAPTER / trailingSlash:${TRAILING_SLASH:-always} / pathPrefix:${PATH_PREFIX:--}\" TRAILING_SLASH=$TRAILING_SLASH PATH_PREFIX=$PATH_PREFIX npm run cy:open -- --config-file \"cypress/configs/$ADAPTER.ts\" --env TRAILING_SLASH=$TRAILING_SLASH,PATH_PREFIX=$PATH_PREFIX",
"test:template:debug": "cross-env-shell CYPRESS_GROUP_NAME=\"adapter:$ADAPTER / trailingSlash:${TRAILING_SLASH:-always} / pathPrefix:${PATH_PREFIX:--} / excludeDatastoreFromBundle:${GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE:-false}\" TRAILING_SLASH=$TRAILING_SLASH PATH_PREFIX=$PATH_PREFIX npm run cy:open -- --config-file \"cypress/configs/$ADAPTER.ts\" --env TRAILING_SLASH=$TRAILING_SLASH,PATH_PREFIX=$PATH_PREFIX",
"test:debug": "npm-run-all -s build:debug ssat:debug",
"test:netlify": "cross-env TRAILING_SLASH=always node scripts/deploy-and-run/netlify.mjs test:template",
"test:smoke": "node smoke-test.mjs",
"test:netlify:debug": "cross-env TRAILING_SLASH=always node scripts/deploy-and-run/netlify.mjs test:template:debug",
"test:netlify:prefix-never": "cross-env TRAILING_SLASH=never PATH_PREFIX=/prefix node scripts/deploy-and-run/netlify.mjs test:template",
"test:netlify:prefix-never:debug": "cross-env TRAILING_SLASH=never PATH_PREFIX=/prefix node scripts/deploy-and-run/netlify.mjs test:template:debug",
"test": "npm-run-all -c -s test:netlify test:netlify:prefix-never"
"test:netlify:non-defaults-variant": "cross-env TRAILING_SLASH=never PATH_PREFIX=/prefix GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE=true node scripts/deploy-and-run/netlify.mjs test:template",
"test:netlify:non-defaults-variant:debug": "cross-env TRAILING_SLASH=never PATH_PREFIX=/prefix GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE=true node scripts/deploy-and-run/netlify.mjs test:template:debug",
"test": "npm-run-all -c -s test:netlify test:netlify:non-defaults-variant"
},
"dependencies": {
"gatsby": "next",
Expand Down
2 changes: 2 additions & 0 deletions packages/gatsby-adapter-netlify/src/lambda-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,13 @@ const createRequestObject = ({ event, context }) => {
multiValueHeaders = {},
body,
isBase64Encoded,
rawUrl
} = event
const newStream = new Stream.Readable()
const req = Object.assign(newStream, http.IncomingMessage.prototype)
req.url = path
req.originalUrl = req.url
req.rawUrl = rawUrl
req.query = queryStringParameters
req.multiValueQuery = multiValueQueryStringParameters
req.method = httpMethod
Expand Down
4 changes: 4 additions & 0 deletions packages/gatsby/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1869,6 +1869,10 @@ export interface GatsbyFunctionRequest<ReqBody = any> extends IncomingMessage {
* Object of `cookies` from header
*/
cookies: Record<string, string>
/**
* Optional field to store the full raw URL by adapters
*/
rawUrl?: string
}

export interface GatsbyFunctionBodyParserCommonMiddlewareConfig {
Expand Down
60 changes: 29 additions & 31 deletions packages/gatsby/src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,37 +191,6 @@ module.exports = async function build(
buildActivityTimer.end()
}

if (shouldGenerateEngines()) {
const state = store.getState()
const buildActivityTimer = report.activityTimer(
`Building Rendering Engines`,
{ parentSpan: buildSpan }
)
try {
buildActivityTimer.start()
// bundle graphql-engine
engineBundlingPromises.push(
createGraphqlEngineBundle(program.directory, report, program.verbose)
)

engineBundlingPromises.push(
createPageSSRBundle({
rootDir: program.directory,
components: state.components,
staticQueriesByTemplate: state.staticQueriesByTemplate,
webpackCompilationHash: webpackCompilationHash as string, // we set webpackCompilationHash above
reporter: report,
isVerbose: program.verbose,
})
)
await Promise.all(engineBundlingPromises)
} catch (err) {
reporter.panic(err)
} finally {
buildActivityTimer.end()
}
}

const buildSSRBundleActivityProgress = report.activityTimer(
`Building HTML renderer`,
{ parentSpan: buildSpan }
Expand Down Expand Up @@ -295,6 +264,35 @@ module.exports = async function build(
}

if (shouldGenerateEngines()) {
const state = store.getState()
const buildActivityTimer = report.activityTimer(
`Building Rendering Engines`,
{ parentSpan: buildSpan }
)
try {
buildActivityTimer.start()
// bundle graphql-engine
engineBundlingPromises.push(
createGraphqlEngineBundle(program.directory, report, program.verbose)
)

engineBundlingPromises.push(
createPageSSRBundle({
rootDir: program.directory,
components: state.components,
staticQueriesByTemplate: state.staticQueriesByTemplate,
webpackCompilationHash: webpackCompilationHash as string, // we set webpackCompilationHash above
reporter: report,
isVerbose: program.verbose,
})
)
await Promise.all(engineBundlingPromises)
} catch (err) {
reporter.panic(err)
} finally {
buildActivityTimer.end()
}
Comment on lines +267 to +294
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved engine bundling a bit later to a point where we know already which pages would actually be DSG or SSR (need to be after preparePageTemplateConfigs call)


await validateEnginesWithActivity(program.directory, buildSpan)
}

Expand Down
6 changes: 3 additions & 3 deletions packages/gatsby/src/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ module.exports = async (program: IServeProgram): Promise<void> => {
try {
const { GraphQLEngine } =
require(graphqlEnginePath) as typeof import("../schema/graphql-engine/entry")
const { getData, renderPageData, renderHTML } =
const { getData, renderPageData, renderHTML, findEnginePageByPath } =
require(pageSSRModule) as typeof import("../utils/page-ssr-module/entry")
const graphqlEngine = new GraphQLEngine({
dbPath: path.posix.join(
Expand All @@ -222,7 +222,7 @@ module.exports = async (program: IServeProgram): Promise<void> => {
}

const potentialPagePath = reverseFixedPagePath(requestedPagePath)
const page = graphqlEngine.findPageByPath(potentialPagePath)
const page = findEnginePageByPath(potentialPagePath)

if (page && (page.mode === `DSG` || page.mode === `SSR`)) {
const requestActivity = report.phantomActivity(
Expand Down Expand Up @@ -272,7 +272,7 @@ module.exports = async (program: IServeProgram): Promise<void> => {
router.use(async (req, res, next) => {
if (req.accepts(`html`)) {
const potentialPagePath = req.path
const page = graphqlEngine.findPageByPath(potentialPagePath)
const page = findEnginePageByPath(potentialPagePath)
if (page && (page.mode === `DSG` || page.mode === `SSR`)) {
const requestActivity = report.phantomActivity(
`request for "${req.path}"`
Expand Down
3 changes: 3 additions & 0 deletions packages/gatsby/src/schema/graphql-engine/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ export class GraphQLEngine {
}
}

/**
* @deprecated use findEnginePageByPath exported from page-ssr module instead
*/
public findPageByPath(pathName: string): IGatsbyPage | undefined {
// adapter so `findPageByPath` use SitePage nodes in datastore
// instead of `pages` redux slice
Expand Down
4 changes: 3 additions & 1 deletion packages/gatsby/src/utils/adapter/get-route-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ function maybeDropNamedPartOfWildcard(
return path.replace(/\*.+$/, `*`)
}

export function getRoutePathFromPage(page: IGatsbyPage): string {
export function getRoutePathFromPage(
page: Pick<IGatsbyPage, "path" | "matchPath">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this (and other places I applied Pick<> to IGatsbyPage) was mainly to figure out minimal subset of IGatsbyPage fields that is actually needed for engines to work.

After everything was narrowed down this allowed me to produce final subset of fields to be inlined in engine ( https://github.com/gatsbyjs/gatsby/pull/38974/files#diff-6e15aa2b28579972ae31b662310cd05809325fe178e51e48e4a89bbbc3b34134R45-R54 )

): string {
return maybeDropNamedPartOfWildcard(page.matchPath) ?? page.path
}

Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby/src/utils/adapter/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { getPageMode } from "../page-mode"
import { getStaticQueryPath } from "../static-query-utils"
import { getAdapterInit } from "./init"
import {
LmdbOnCdnPath,
getLmdbOnCdnPath,
shouldBundleDatastore,
shouldGenerateEngines,
} from "../engines-helpers"
Expand Down Expand Up @@ -192,7 +192,7 @@ export async function initAdapterManager(): Promise<IAdapterManager> {
}

// handle lmdb file
const mdbInPublicPath = `public/${LmdbOnCdnPath}`
const mdbInPublicPath = `public/${getLmdbOnCdnPath()}`
if (!shouldBundleDatastore()) {
const mdbPath = getDefaultDbPath() + `/data.mdb`
copy(mdbPath, mdbInPublicPath)
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby/src/utils/engines-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function getCDNObfuscatedPath(path: string): string {
return `${store.getState().status.cdnObfuscatedPrefix}-${path}`
}

export const LmdbOnCdnPath = getCDNObfuscatedPath(`data.mdb`)
export const getLmdbOnCdnPath = (): string => getCDNObfuscatedPath(`data.mdb`)
Copy link
Contributor Author

@pieh pieh May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

making it lazy here, as getCDNObfuscatedPath is potentially using some values from cache that might not have been restored yet at import time (adapters restore it later)

that was causing a bug where generated path was different on each build while it should be the same to avoid publishing multiple versions of db to cdn


export interface IPlatformAndArch {
platform: string
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby/src/utils/get-server-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function getServerData(
req:
| Partial<Pick<Request, "query" | "method" | "url" | "headers">>
| undefined,
page: IGatsbyPage,
page: Pick<IGatsbyPage, "path" | "matchPath" | "context">,
pagePath: string,
mod: IModuleWithServerData | undefined
): Promise<IServerData> {
Expand Down
33 changes: 28 additions & 5 deletions packages/gatsby/src/utils/page-ssr-module/bundle-webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import webpack from "webpack"
import mod from "module"
import { WebpackLoggingPlugin } from "../../utils/webpack/plugins/webpack-logging"
import reporter from "gatsby-cli/lib/reporter"
import type { ITemplateDetails } from "./entry"
import type { EnginePage, ITemplateDetails } from "./entry"

import {
getScriptsAndStylesForTemplate,
readWebpackStats,
} from "../client-assets-for-template"
import { IGatsbyState } from "../../redux/types"
import { store } from "../../redux"
import { LmdbOnCdnPath, shouldBundleDatastore } from "../engines-helpers"
import { getLmdbOnCdnPath, shouldBundleDatastore } from "../engines-helpers"
import { getPageMode } from "../page-mode"

type Reporter = typeof reporter

Expand Down Expand Up @@ -112,6 +113,25 @@ export async function createPageSSRBundle({
}
}

const pagesIterable: Array<[string, EnginePage]> = []
for (const [pagePath, page] of state.pages) {
const mode = getPageMode(page, state)
if (mode !== `SSG`) {
pagesIterable.push([
pagePath,
{
componentChunkName: page.componentChunkName,
componentPath: page.componentPath,
context: page.context,
matchPath: page.matchPath,
mode,
path: page.path,
slices: page.slices,
},
])
}
}

const compiler = webpack({
name: `Page Engine`,
mode: `none`,
Expand Down Expand Up @@ -193,6 +213,7 @@ export async function createPageSSRBundle({
INLINED_TEMPLATE_TO_DETAILS: JSON.stringify(toInline),
INLINED_HEADERS_CONFIG: JSON.stringify(state.config.headers),
WEBPACK_COMPILATION_HASH: JSON.stringify(webpackCompilationHash),
GATSBY_PAGES: JSON.stringify(pagesIterable),
GATSBY_SLICES: JSON.stringify(slicesStateObject),
GATSBY_SLICES_BY_TEMPLATE: JSON.stringify(slicesByTemplateStateObject),
GATSBY_SLICES_SCRIPT: JSON.stringify(
Expand Down Expand Up @@ -248,9 +269,11 @@ export async function createPageSSRBundle({
functionCode = functionCode
.replaceAll(
`%CDN_DATASTORE_PATH%`,
shouldBundleDatastore()
? ``
: `${state.adapter.config.deployURL ?? ``}/${LmdbOnCdnPath}`
shouldBundleDatastore() ? `` : getLmdbOnCdnPath()
)
.replaceAll(
`%CDN_DATASTORE_ORIGIN%`,
shouldBundleDatastore() ? `` : state.adapter.config.deployURL ?? ``
)
.replaceAll(`%PATH_PREFIX%`, pathPrefix)
.replaceAll(
Expand Down
Loading