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

Reduce excess file system writes by implementing query queue #3237

Merged
merged 3 commits into from
Dec 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/docs/gatsby-starters.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,11 @@ Community:
* Colorful homepage, and also includes a Landing Page and Generic Page components.
* Many elements are available, including buttons, forms, tables, and pagination.
* Styling with SCSS

* [gatsby-firebase-authentication](https://github.com/rwieruch/gatsby-firebase-authentication) [(demo)](https://react-firebase-authentication.wieruch.com/)

Features:

* Sign In, Sign Up, Sign Out
* Password Forget
* Password Change
Expand Down
2 changes: 2 additions & 0 deletions packages/gatsby/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"babel-runtime": "^6.26.0",
"babel-traverse": "^6.24.1",
"babylon": "^6.17.3",
"better-queue": "^3.8.6",
"bluebird": "^3.5.0",
"chalk": "^1.1.3",
"chokidar": "^1.7.0",
Expand Down Expand Up @@ -66,6 +67,7 @@
"lodash": "^4.17.4",
"lodash-id": "^0.14.0",
"lowdb": "^0.16.2",
"md5": "^2.2.1",
"md5-file": "^3.1.1",
"mime": "^1.3.6",
"mitt": "^1.1.2",
Expand Down
2 changes: 2 additions & 0 deletions packages/gatsby/src/bootstrap/page-hot-reloader.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ const runCreatePages = async () => {
deleteComponentsDependencies([page.path])
deletePage(page)
})

emitter.emit(`CREATE_PAGE_END`)
}

const debouncedCreatePages = _.debounce(runCreatePages, 100)
Expand Down
1 change: 0 additions & 1 deletion packages/gatsby/src/commands/data-explorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,3 @@ module.exports = async (program: any) => {
console.log(`Gatsby data explorer running at`, `http://${host}:${port}`)
app.listen(port, host)
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
*/

const _ = require(`lodash`)
const async = require(`async`)

const queue = require(`./query-queue`)
const { store, emitter } = require(`../../redux`)
const queryRunner = require(`./query-runner`)

let queuedDirtyActions = []
let active = false
Expand Down Expand Up @@ -95,34 +94,27 @@ const findIdsWithoutDataDependencies = () => {
}

const runQueriesForIds = ids => {
ids = _.uniq(ids)
if (ids.length < 1) {
const state = store.getState()
const pagesAndLayouts = [...state.pages, ...state.layouts]
let didNotQueueItems = true
ids.forEach(id => {
const plObj = pagesAndLayouts.find(
pl => pl.path === id || `LAYOUT___${pl.id}` === id
)
if (plObj) {
didNotQueueItems = false
queue.push({ ...plObj, _id: plObj.id, id: plObj.jsonName })
}
})

if (didNotQueueItems || !ids || ids.length === 0) {
return Promise.resolve()
}
const state = store.getState()

return new Promise((resolve, reject) => {
async.mapLimit(
ids,
4,
(id, callback) => {
const pagesAndLayouts = [...state.pages, ...state.layouts]
const plObj = pagesAndLayouts.find(
pl => pl.path === id || `LAYOUT___${pl.id}` === id
)
if (plObj) {
return queryRunner(plObj, state.components[plObj.component]).then(
result => callback(null, result),
error => callback(error)
)
} else {
return callback(null, null)
}
},
(error, result) => {
error ? reject(error) : resolve(result)
}
)
return new Promise(resolve => {
queue.on(`drain`, () => {
resolve()
})
})
}

Expand Down
44 changes: 23 additions & 21 deletions packages/gatsby/src/internal-plugins/query-runner/pages-writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ const writePages = async () => {
pageLayouts = _.uniq(pageLayouts)
components = _.uniqBy(components, c => c.componentChunkName)

await fs.writeFile(
joinPath(program.directory, `.cache/pages.json`),
JSON.stringify(pagesData, null, 4)
)

// Create file with sync requires of layouts/components/json files.
let syncRequires = `// prefer default export if available
const preferDefault = m => m && m.default || m
Expand Down Expand Up @@ -93,10 +88,6 @@ const preferDefault = m => m && m.default || m
.join(`,\n`)}
}`

await fs.writeFile(
`${program.directory}/.cache/sync-requires.js`,
syncRequires
)
// Create file with async requires of layouts/components/json files.
let asyncRequires = `// prefer default export if available
const preferDefault = m => m && m.default || m
Expand Down Expand Up @@ -131,10 +122,17 @@ const preferDefault = m => m && m.default || m
.join(`,\n`)}
}`

await fs.writeFile(
joinPath(program.directory, `.cache/async-requires.js`),
asyncRequires
)
await Promise.all([
fs.writeFile(
joinPath(program.directory, `.cache/pages.json`),
JSON.stringify(pagesData, null, 4)
),
fs.writeFile(`${program.directory}/.cache/sync-requires.js`, syncRequires),
fs.writeFile(
joinPath(program.directory, `.cache/async-requires.js`),
asyncRequires
),
])

return
}
Expand All @@ -143,15 +141,19 @@ exports.writePages = writePages

let bootstrapFinished = false
let oldPages
const debouncedWritePages = _.debounce(() => {
// Don't write pages again until bootstrap has finished.
if (bootstrapFinished && !_.isEqual(oldPages, store.getState().pages)) {
writePages()
oldPages = store.getState().pages
}
}, 250)
const debouncedWritePages = _.debounce(
() => {
// Don't write pages again until bootstrap has finished.
if (bootstrapFinished && !_.isEqual(oldPages, store.getState().pages)) {
writePages()
oldPages = store.getState().pages
}
},
500,
{ leading: true }
)

emitter.on(`CREATE_PAGE`, () => {
emitter.on(`CREATE_PAGE_END`, () => {
debouncedWritePages()
})
emitter.on(`DELETE_PAGE`, () => {
Expand Down
17 changes: 17 additions & 0 deletions packages/gatsby/src/internal-plugins/query-runner/query-queue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const Queue = require(`better-queue`)

const queryRunner = require(`./query-runner`)
const { store } = require(`../../redux`)

const queue = new Queue(
(plObj, callback) => {
const state = store.getState()
return queryRunner(plObj, state.components[plObj.component]).then(
result => callback(null, result),
error => callback(error)
)
},
{ concurrent: 4 }
)

module.exports = queue
21 changes: 16 additions & 5 deletions packages/gatsby/src/internal-plugins/query-runner/query-runner.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { graphql as graphqlFunction } from "graphql"
const fs = require(`fs-extra`)
const report = require(`gatsby-cli/lib/reporter`)
const md5 = require(`md5`)

const { joinPath } = require(`../../utils/path`)
const { store } = require(`../../redux`)

const resultHashes = {}

// Run query for a page
module.exports = async (pageOrLayout, component) => {
pageOrLayout.id = pageOrLayout._id
const { schema, program } = store.getState()

const graphql = (query, context) =>
Expand Down Expand Up @@ -51,10 +55,17 @@ module.exports = async (pageOrLayout, component) => {
contextKey = `layoutContext`
}
result[contextKey] = pageOrLayout.context
const resultJSON = JSON.stringify(result, null, 4)

await fs.writeFile(
joinPath(program.directory, `.cache`, `json`, pageOrLayout.jsonName),
resultJSON
const resultJSON = JSON.stringify(result)
const resultHash = md5(resultJSON)
const resultPath = joinPath(
program.directory,
`.cache`,
`json`,
pageOrLayout.jsonName
)

if (resultHashes[resultPath] !== resultHash) {
resultHashes[resultPath] = resultHash
await fs.writeFile(resultPath, resultJSON)
}
}
24 changes: 7 additions & 17 deletions packages/gatsby/src/internal-plugins/query-runner/query-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@

const _ = require(`lodash`)
const chokidar = require(`chokidar`)
const async = require(`async`)

const { store } = require(`../../redux/`)
const { boundActionCreators } = require(`../../redux/actions`)
const queryCompiler = require(`./query-compiler`).default
const queryRunner = require(`./query-runner`)
const queue = require(`./query-queue`)
const invariant = require(`invariant`)
const normalize = require(`normalize-path`)

Expand Down Expand Up @@ -57,21 +56,12 @@ const runQueriesForComponent = componentPath => {
boundActionCreators.deleteComponentsDependencies(
pages.map(p => p.path || p.id)
)
const component = store.getState().components[componentPath]
return new Promise((resolve, reject) => {
async.mapLimit(
pages,
4,
(page, callback) => {
queryRunner(page, component).then(
result => callback(null, result),
error => callback(error)
)
},
(error, result) => {
error ? reject(error) : resolve(result)
}
)
pages.forEach(page =>
queue.push({ ...page, _id: page.id, id: page.jsonName })
)

return new Promise(resolve => {
queue.on(`drain`, () => resolve())
})
}

Expand Down
4 changes: 2 additions & 2 deletions scripts/publish-site.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

yarn global add gatsby-dev-cli
yarn bootstrap
npm install -g gatsby-dev-cli
gatsby-dev --set-path-to-repo .

echo "=== Installing the website dependencies"
Expand Down
18 changes: 17 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1528,6 +1528,18 @@ better-assert@~1.0.0:
dependencies:
callsite "1.0.0"

better-queue-memory@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/better-queue-memory/-/better-queue-memory-1.0.2.tgz#aa6d169aa1d0cc77409185cb9cb5c7dc251bcd41"

better-queue@^3.8.6:
version "3.8.6"
resolved "https://registry.yarnpkg.com/better-queue/-/better-queue-3.8.6.tgz#73220bdfab403924cffa7497220dd387abb73a63"
dependencies:
better-queue-memory "^1.0.1"
node-eta "^0.9.0"
uuid "^3.0.0"

big.js@^3.1.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
Expand Down Expand Up @@ -7705,7 +7717,7 @@ md5.js@^1.3.4:
hash-base "^3.0.0"
inherits "^2.0.1"

md5@^2.0.0:
md5@^2.0.0, md5@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
dependencies:
Expand Down Expand Up @@ -8161,6 +8173,10 @@ node-emoji@^1.0.4:
dependencies:
lodash.toarray "^4.4.0"

node-eta@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/node-eta/-/node-eta-0.9.0.tgz#9fb0b099bcd2a021940e603c64254dc003d9a7a8"

node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
Expand Down