From 3e2d852e64861956b9c10e46b447782aac9588c0 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Thu, 14 Dec 2017 13:10:04 -0800 Subject: [PATCH] Track pages/layouts without queries fixes #3139 #3148 #3094 (#3218) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Track pages/layouts without queries fixes #3139 #3148 #3094 This bug was hard to track down as it manifested itself in a weird way. Gatsby tracks external changes which indicate a need to re-run GraphQL queries. Which is normally fine since Gatsby also is tracking which queries would be dirtied by the external change (e.g. a query depends on a file — when that file is changed, the query is "dirty" and needs run again). But pages/layouts *without* queries weren't being tracked which meant that on every external change, Gatsby would think it needed to run those queries again. During the build process. Gatsby assumes that external data won't change so during the bootstrap, it waits for the initials set of queries to finish running but during later stages, it doesn't. Because sites with lots of pages with no queries were running their queries over and over, this meant that occassionally webpack would try to load a JSON file (queries are written out as JSON files) that wasn't finished writing. This PR fixes the problem as now during build, Gatsby only attempts to run queries for page/layout components without queries during the initial bootstrap. * Fix formatting --- .../query-runner/page-query-runner.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/gatsby/src/internal-plugins/query-runner/page-query-runner.js b/packages/gatsby/src/internal-plugins/query-runner/page-query-runner.js index 618dc8ac4ee7d..4caf5666473f0 100644 --- a/packages/gatsby/src/internal-plugins/query-runner/page-query-runner.js +++ b/packages/gatsby/src/internal-plugins/query-runner/page-query-runner.js @@ -62,6 +62,7 @@ const runQueuedActions = async () => { // query things in a 1/2 finished state. emitter.on(`API_RUNNING_QUEUE_EMPTY`, runQueuedActions) +let seenIdsWithoutDataDependencies = [] const findIdsWithoutDataDependencies = () => { const state = store.getState() const allTrackedIds = _.uniq( @@ -75,13 +76,22 @@ const findIdsWithoutDataDependencies = () => { // Get list of paths not already tracked and run the queries for these // paths. - return _.difference( + const notTrackedIds = _.difference( [ ...state.pages.map(p => p.path), ...state.layouts.map(l => `LAYOUT___${l.id}`), ], - allTrackedIds + [...allTrackedIds, ...seenIdsWithoutDataDependencies] ) + + // Add new IDs to our seen array so we don't keep trying to run queries for them. + // Pages/Layouts without queries can't be tracked. + seenIdsWithoutDataDependencies = _.uniq([ + ...notTrackedIds, + ...seenIdsWithoutDataDependencies, + ]) + + return notTrackedIds } const runQueriesForIds = ids => { @@ -105,8 +115,9 @@ const runQueriesForIds = ids => { result => callback(null, result), error => callback(error) ) + } else { + return callback(null, null) } - return callback(null, null) }, (error, result) => { error ? reject(error) : resolve(result)