Skip to content

Commit

Permalink
feat(query-modules): add support for static queries
Browse files Browse the repository at this point in the history
  • Loading branch information
pieh committed Aug 4, 2020
1 parent 85ed892 commit f11fcb3
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 13 deletions.
6 changes: 1 addition & 5 deletions packages/gatsby/src/schema/context.ts
Expand Up @@ -48,11 +48,7 @@ export default function withResolverContext<TSource, TArgs>({
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:
Expand Down
Expand Up @@ -54,6 +54,7 @@ describe(`map-templates-to-static-query-hashes`, () => {
{
components,
staticQueryComponents,
modules: new Map(),
},
{
modules: [
Expand Down
39 changes: 36 additions & 3 deletions packages/gatsby/src/utils/map-templates-to-static-query-hashes.ts
Expand Up @@ -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)
Expand Down Expand Up @@ -129,7 +133,7 @@ export default function mapTemplatesToStaticQueryHashes(
return getDepsRec(mod, seen)
}

const mapOfStaticQueryComponentsToDependants = new Map()
const mapOfStaticQueryComponentsToDependants = new Map<string, Set<string>>()

// For every known static query, we get its dependents.
staticQueryComponents.forEach(({ componentPath }) => {
Expand All @@ -141,7 +145,7 @@ export default function mapTemplatesToStaticQueryHashes(
)
const dependants = staticQueryComponentModule
? getDeps(staticQueryComponentModule)
: new Set()
: new Set<string>()

mapOfStaticQueryComponentsToDependants.set(componentPath, dependants)
})
Expand Down Expand Up @@ -193,6 +197,35 @@ export default function mapTemplatesToStaticQueryHashes(
)
})

queryModules.forEach(queryModule => {
const staticQueryHashes: Array<string> = []

// 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
}

Expand Down
83 changes: 78 additions & 5 deletions packages/gatsby/src/utils/page-data.ts
Expand Up @@ -15,6 +15,11 @@ interface IPageData {
staticQueryHashes: string[]
}

interface IPageDataResources {
staticQueryHashes: Set<string>
moduleDependencies: Set<string>
}

export interface IPageDataWithQueryResult extends IPageData {
result: IExecutionResult
}
Expand Down Expand Up @@ -121,6 +126,8 @@ export async function flush(): Promise<void> {
components,
pages,
program,
staticQueryComponents,
modules,
staticQueriesByTemplate,
queryModuleDependencies,
} = store.getState()
Expand All @@ -138,6 +145,51 @@ export async function flush(): Promise<void> {
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)

Expand All @@ -148,11 +200,32 @@ export async function flush(): Promise<void> {
// 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<string>(),
moduleDependencies: new Set<string>(),
}

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`),
Expand Down

0 comments on commit f11fcb3

Please sign in to comment.