Skip to content

Commit

Permalink
[json-loader] develop - reading results from file improvments (#4850)
Browse files Browse the repository at this point in the history
* dont emit results for layouts

* [develop] store query results in memory, read json data from file only if we don't have it stored yet (we didn't run this query, but results are cached)
  • Loading branch information
pieh authored and KyleAMathews committed Apr 5, 2018
1 parent 62754de commit 4a09f74
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 71 deletions.
84 changes: 46 additions & 38 deletions packages/gatsby/cache-dir/json-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,81 +6,89 @@ import socketIo from "./socketIo"
import omit from "lodash/omit"
import get from "lodash/get"

const getPathFromProps = props => {
if (props.isPage) {
return get(props.pageResources, `page.path`)
} else {
return `/dev-404-page/`
}
}

class JSONStore extends React.Component {
constructor(props) {
super(props)
this.state = {
data: {},
path: null,
}

this.socket = socketIo()

this.setPageData = this.setPageData.bind(this)
this.getPageData = this.getPageData.bind(this)
}

componentDidMount() {
this.socket = socketIo()
this.socket.on(`queryResult`, this.setPageData)
}

shouldComponentUpdate(nextProps, nextState) {
if (nextProps !== this.props) return true

// if json for nextState is not available
const nextJsonId = get(nextProps.pageResources, `page.jsonName`)
if (!nextState.data[nextJsonId]) return false

// if nextState json is the same as current state json
const sameDataPath =
get(nextState, `data[${nextJsonId}].dataPath`) ===
get(this, `state.data[${nextJsonId}].dataPath`)
componentWillMount() {
this.registerPath(getPathFromProps(this.props))
}

if (sameDataPath) return false
componentWillReceiveProps(nextProps) {
const { path } = this.state
const newPath = getPathFromProps(nextProps)

return true
if (path !== newPath) {
this.unregisterPath(path)
this.registerPath(newPath)
}
}

setPageData(newData) {
this.setState({
data: { [newData.path]: newData },
})
registerPath(path) {
this.setState({ path })
this.socket.emit(`registerPath`, path)
}

getPageData(path) {
const res = this.state.data[path]
unregisterPath(path) {
this.setState({ path: null })
this.socket.emit(`unregisterPath`, path)
}

// always check for fresh data
this.socket.emit(`getPageData`, path)
componentWillUnmount() {
this.unregisterPath(this.state.path)
}

if (!res || !res.data) return false
return JSON.parse(res.data)
setPageData({ path, result }) {
this.setState({
data: {
...this.state.data,
[path]: result,
},
})
}

render() {
const { isPage, pages, pageResources } = this.props
const data = this.state.data[this.state.path]
const propsWithoutPages = omit(this.props, `pages`)

if (isPage) {
const jsonId = get(pageResources, `page.jsonName`)
const pageData = this.getPageData(jsonId)
if (pageData === false) return ``
if (!data) {
return null
} else if (isPage) {
return createElement(ComponentRenderer, {
key: `normal-page`,
...propsWithoutPages,
...pageData,
...data,
})
} else {
const dev404Page = pages.find(p => /^\/dev-404-page/.test(p.path))
const dev404Props = {
...propsWithoutPages,
...this.getPageData(dev404Page.jsonName),
}
return createElement(Route, {
key: `404-page`,
component: props =>
createElement(
syncRequires.components[dev404Page.componentChunkName],
dev404Props
{
...propsWithoutPages,
...data,
}
),
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,11 @@ module.exports = async (pageOrLayout, component) => {

const programType = program._[0]

if (programType === `develop`) {
const data = {
dataPath,
data: resultJSON,
path: pageOrLayout.jsonName,
}
websocketManager.emitData({ data })
if (programType === `develop` && pageOrLayout.path) {
websocketManager.emitData({
result,
path: pageOrLayout.path,
})
}

const resultPath = path.join(
Expand Down
68 changes: 42 additions & 26 deletions packages/gatsby/src/utils/websocket-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ const path = require(`path`)
const { store } = require(`../redux`)
const fs = require(`fs`)

const getCachedPageData = (jsonName, directory) => {
const jsonDataPaths = store.getState().jsonDataPaths
const dataPath = jsonDataPaths[jsonName]
const getCachedPageData = (pagePath, directory) => {
const { jsonDataPaths, pages } = store.getState()
const page = pages.find(p => p.path === pagePath)
const dataPath = jsonDataPaths[page.jsonName]
if (typeof dataPath === `undefined`) return undefined
const filePath = path.join(
directory,
Expand All @@ -13,25 +14,25 @@ const getCachedPageData = (jsonName, directory) => {
`d`,
`${dataPath}.json`
)
const data = fs.readFileSync(filePath, `utf-8`)
const result = JSON.parse(fs.readFileSync(filePath, `utf-8`))
return {
data,
dataPath,
path: jsonName,
result,
path: pagePath,
}
}

const getRoomNameFromPath = path => `path-${path}`

class WebsocketManager {
constructor() {
this.isInitialised = false
this.results = {}
this.activePaths = new Map()
this.results = new Map()
this.websocket
this.programDir

this.init = this.init.bind(this)
this.getSocket = this.getSocket.bind(this)
this.getPageData = this.getPageData.bind(this)
this.emitData = this.emitData.bind(this)
}

Expand All @@ -40,13 +41,33 @@ class WebsocketManager {
this.websocket = require(`socket.io`)(server)

this.websocket.on(`connection`, s => {
const clientId = s.id
s.join(`clients`)
s.on(`getPageData`, path => {
this.getPageData(path, clientId)
})
let activePath = null

const leaveRoom = path => {
s.leave(getRoomNameFromPath(path))
activePath = null
}

s.on(`disconnect`, s => {
this.activePaths.delete(clientId)
leaveRoom(activePath)
})

s.on(`registerPath`, path => {
s.join(getRoomNameFromPath(path))
activePath = path
this.activePaths.set(s.id, path)

if (this.results.has(path)) {
s.emit(`queryResult`, this.results.get(path))
} else {
const result = getCachedPageData(path, this.programDir)
this.results.set(path, result)
s.emit(`queryResult`, result)
}
})

s.on(`unregisterPath`, path => {
leaveRoom(path)
})
})

Expand All @@ -57,21 +78,16 @@ class WebsocketManager {
return this.isInitialised && this.websocket
}

getPageData(path, clientId) {
// track the active path for each connected client
this.activePaths.set(clientId, path)
const data = getCachedPageData(path, this.programDir)
this.emitData({ data, forceEmit: true })
}

emitData({ data, forceEmit = false }) {
emitData(data) {
const isActivePath =
data.path && Array.from(this.activePaths.values()).includes(data.path)

// push results if this path is active on a client
if (isActivePath || forceEmit) {
this.websocket.emit(`queryResult`, data)
if (isActivePath) {
this.websocket
.to(getRoomNameFromPath(data.path))
.emit(`queryResult`, data)
}
this.results.set(data.path, data)
}
}

Expand Down

0 comments on commit 4a09f74

Please sign in to comment.