diff --git a/packages/gatsby/src/schema/context.ts b/packages/gatsby/src/schema/context.ts index 38f3b622a968b..f961445826b78 100644 --- a/packages/gatsby/src/schema/context.ts +++ b/packages/gatsby/src/schema/context.ts @@ -48,11 +48,7 @@ export default function withResolverContext({ importName?: string }): string => { if (!context?.path) { - throw new Error(`Adding modules doesn't work in gatsby-node`) - } - - if (context.path.startsWith(`sq--`)) { - throw new Error(`Adding modules in static queries not implemented (yet)`) + throw new Error(`Adding modules doesn't work in gatsby-node or graphiql`) } // TO-DO: validation: diff --git a/packages/gatsby/src/utils/__tests__/map-templates-to-static-query-hashes.js b/packages/gatsby/src/utils/__tests__/map-templates-to-static-query-hashes.js index eac045a272123..9e0eb4648b5b9 100644 --- a/packages/gatsby/src/utils/__tests__/map-templates-to-static-query-hashes.js +++ b/packages/gatsby/src/utils/__tests__/map-templates-to-static-query-hashes.js @@ -54,6 +54,7 @@ describe(`map-templates-to-static-query-hashes`, () => { { components, staticQueryComponents, + modules: new Map(), }, { modules: [ diff --git a/packages/gatsby/src/utils/map-templates-to-static-query-hashes.ts b/packages/gatsby/src/utils/map-templates-to-static-query-hashes.ts index efcfa0f0d2855..4d70070b85384 100644 --- a/packages/gatsby/src/utils/map-templates-to-static-query-hashes.ts +++ b/packages/gatsby/src/utils/map-templates-to-static-query-hashes.ts @@ -54,7 +54,11 @@ export default function mapTemplatesToStaticQueryHashes( * Note that this upward traversal is much shallower (and hence more performant) * than an equivalent downward one from an entry point. */ - const { components, staticQueryComponents } = reduxState + const { + components, + staticQueryComponents, + modules: queryModules, + } = reduxState const { modules } = compilation /* We call the queries included above a page (via wrapRootElement or wrapPageElement APIs) @@ -129,7 +133,7 @@ export default function mapTemplatesToStaticQueryHashes( return getDepsRec(mod, seen) } - const mapOfStaticQueryComponentsToDependants = new Map() + const mapOfStaticQueryComponentsToDependants = new Map>() // For every known static query, we get its dependents. staticQueryComponents.forEach(({ componentPath }) => { @@ -141,7 +145,7 @@ export default function mapTemplatesToStaticQueryHashes( ) const dependants = staticQueryComponentModule ? getDeps(staticQueryComponentModule) - : new Set() + : new Set() mapOfStaticQueryComponentsToDependants.set(componentPath, dependants) }) @@ -193,6 +197,35 @@ export default function mapTemplatesToStaticQueryHashes( ) }) + queryModules.forEach(queryModule => { + const staticQueryHashes: Array = [] + + // Does this module contain an inline static query? + if (mapOfComponentsToStaticQueryHashes.has(queryModule.source)) { + const hash = mapOfComponentsToStaticQueryHashes.get(queryModule.source) + if (hash) { + staticQueryHashes.push(hash) + } + } + + // Check dependencies + mapOfStaticQueryComponentsToDependants.forEach( + (setOfDependants, moduleSource) => { + if (setOfDependants.has(queryModule.source)) { + const hash = mapOfComponentsToStaticQueryHashes.get(moduleSource) + if (hash) { + staticQueryHashes.push(hash) + } + } + } + ) + + mapOfTemplatesToStaticQueryHashes.set( + queryModule.source, + staticQueryHashes.sort().map(String) + ) + }) + return mapOfTemplatesToStaticQueryHashes } diff --git a/packages/gatsby/src/utils/page-data.ts b/packages/gatsby/src/utils/page-data.ts index 1ce16a2529fdf..5298e66ae513f 100644 --- a/packages/gatsby/src/utils/page-data.ts +++ b/packages/gatsby/src/utils/page-data.ts @@ -15,6 +15,11 @@ interface IPageData { staticQueryHashes: string[] } +interface IPageDataResources { + staticQueryHashes: Set + moduleDependencies: Set +} + export interface IPageDataWithQueryResult extends IPageData { result: IExecutionResult } @@ -121,6 +126,8 @@ export async function flush(): Promise { components, pages, program, + staticQueryComponents, + modules, staticQueriesByTemplate, queryModuleDependencies, } = store.getState() @@ -138,6 +145,51 @@ export async function flush(): Promise { new Set(pagePaths.values()) ) + const hashToStaticQueryId = new Map() + staticQueryComponents.forEach(({ id, hash }) => { + hashToStaticQueryId.set(String(hash), id) + }) + + function pickModulesFromStaticQuery( + staticQueryHash: string, + resources: IPageDataResources + ): void { + const staticQueryId = hashToStaticQueryId.get(staticQueryHash) + + const modulesUsedByStaticQuery = queryModuleDependencies.get(staticQueryId) + + if (modulesUsedByStaticQuery && modulesUsedByStaticQuery?.size > 0) { + modulesUsedByStaticQuery.forEach(moduleId => { + // if this hash was added, don't traverse this path again + if (!resources.moduleDependencies.has(staticQueryHash)) { + resources.moduleDependencies.add(moduleId) + pickStaticQueriesFromModule(moduleId, resources) + } + }) + } + } + + function pickStaticQueriesFromModule( + moduleId: string, + resources: IPageDataResources + ): void { + const source = modules.get(moduleId)?.source + if (!source) { + return + } + + const staticQueriesUsedByModule = staticQueriesByTemplate.get(source) + if (staticQueriesUsedByModule && staticQueriesUsedByModule.length > 0) { + staticQueriesUsedByModule.forEach(staticQueryHash => { + // if this hash was added, don't traverse this path again + if (!resources.staticQueryHashes.has(staticQueryHash)) { + resources.staticQueryHashes.add(staticQueryHash) + pickModulesFromStaticQuery(staticQueryHash, resources) + } + }) + } + } + for (const pagePath of pagesToWrite) { const page = pages.get(pagePath) @@ -148,11 +200,32 @@ export async function flush(): Promise { // them, a page might not exist anymore щ(゚Д゚щ) // This is why we need this check if (page) { - const staticQueryHashes = - staticQueriesByTemplate.get(page.componentPath) || [] - const moduleDependencies = Array.from( - queryModuleDependencies.get(pagePath) || [] - ).sort() + const resources: IPageDataResources = { + staticQueryHashes: new Set(), + moduleDependencies: new Set(), + } + + const staticQueryForTemplate = staticQueriesByTemplate.get( + page.componentPath + ) + const modulesForPage = queryModuleDependencies.get(pagePath) + + if (staticQueryForTemplate) { + staticQueryForTemplate.forEach(staticQueryHash => { + resources.staticQueryHashes.add(staticQueryHash) + pickModulesFromStaticQuery(staticQueryHash, resources) + }) + } + + if (modulesForPage) { + modulesForPage.forEach(moduleId => { + resources.moduleDependencies.add(moduleId) + pickStaticQueriesFromModule(moduleId, resources) + }) + } + + const staticQueryHashes = Array.from(resources.staticQueryHashes) + const moduleDependencies = Array.from(resources.moduleDependencies) const result = await writePageData( path.join(program.directory, `public`),