-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
[1.0] Query runner refactor #828
Conversation
Deploy preview ready! Built with commit d9d60d2 |
Deploy preview ready! Built with commit 6560744 |
8756144
to
89d880e
Compare
Deploy preview ready! Built with commit 836841b |
So I think this refactor is broadly correct. My main concern is with how sloppy some of the event chaining logic is. Not going to worry about it much now as this stuff will get worked over again in the future. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Big diff! Good works ;) just some styles comments/questions and maybe a bad copy/past find
Note: I haven't run the project on this branch for instant
@@ -305,8 +308,8 @@ module.exports = async (program: any) => { | |||
|
|||
console.log(`created js pages`) | |||
|
|||
return new Promise(resolve => { | |||
queryRunner(thing => { | |||
const finishPromise = new Promise(resolve => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This const it's really useless and finishPromise
is a very strange wording ^^ (what this Promise represent? A variable name never should to be generic)
http://codebuild.blogspot.de/2012/02/15-best-practices-of-variable-method.html 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh oops that was leftover from when I was experimenting with something. Fixed to just returning the promise.
* - Watch for when a page's query is invalidated and re-run it. | ||
***/ | ||
|
||
const _ = require("lodash") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a general style reflection (es6 module vs require):
Sometime we use import ... from ...
sometime const ... = require()
, I think es6 module style is better for performance/readibility but more important I think we need to make a choice! (I always ask to myself "what is better for this file?")
So, what we choose?
ref: https://medium.com/the-node-js-collection/an-update-on-es6-modules-in-node-js-42c958b890c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same fact from lodash, we have four import patterns:
const _ = require("lodash")
const {get, forEach} = require("lodash")
import _ from "lodash"
import {get, forEach} from "lodash"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The general rule I've arrived at (not universally followed) is to use commonjs for node stuff and imports for browser. I write enough "raw" node.js code that getting tripped up by es6 stuff not working when I'm not compiling the code gets really annoying.
For lodash, I just always import the underscore as I dislike going back and forth to change which exact methods I'm importing. When writing browser code, I then just add the webpack/babel lodash plugins to optimize the builds. Which speaking of, it'd be good to get a Gatsby plugin for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Maybe it can be a good idea to add this "coding guidelines" into CONTRIBUTING.md (like https://github.com/lodash/lodash/blob/master/.github/CONTRIBUTING.md#coding-guidelines)
}) | ||
|
||
// Tell everyone who cares that we're done. | ||
callbacks.forEach(cb => cb()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't try, but I think it's a good idea to add callbacks = []
after (to avoid multiple callbacks calls)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Callbacks (the array) isn't ever used again after this... which isn't obvious I agree. But this again points to the weakness of how I've been writing the (I'm not sure what's the right way to describe this) event based boot system.
I was thinking yesterday that SystemD might actually be a good model to follow since Gatsby is kind of an OS. Will read up more on that http://0pointer.de/blog/projects/systemd.html
If there's any other programming architectures you can think of for booting up an event-based system, lemme know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can have a look into ionic-dev-tools , they've got many of our problematics (live-reload, watch, build, notifications…) and their code is very clean ;)
}) | ||
|
||
// Trim whitespace | ||
if (query) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use lodash method (most robut => works with null
)
query = _.trim(query)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
|
||
const debounceNewPages = _.debounce(() => { | ||
store.dispatch({ | ||
type: `BOOTSTRAP_STAGE`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be good to have a constant.js
or anything else to have a list with all possible actions (to avoid any collision).
Another good practice is to have an actionCreator even if the action is very simple (with this pattern, all actions are centralized, so it's easier to maintain)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is my first Redux project so I've heard of doing that but have been skipping it so far to keep moving quicker :-) But yeah, let's refactor things soon to use a constants.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like the pattern constants.js
(you have 3 files to update for 1 action… so yeah, you moving slower) my best compromise to have flexibility and maintabiliy is to merge actionsCreator & constants (an example into my redux sandbox)
// If there's not an index page, just pick the one with the shortest path. | ||
// Probably a bad heuristic. | ||
if (!indexPage) { | ||
indexPage = _.first(_.sortBy(pages, page => page.path.length)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a style suggestion:
_(pages).sortBy(page => page.path.length).first()
Quite same, but you retrieve the natural reading way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh nice! Haven't used this style before but I like it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Chaining with lodash, I just love this notation 😄 Just some subtilities with lodashWrapper
I recommend this talk if you like it:
http://www.nicoespeon.com/en/2015/06/functions-chaining-composition-lodash-underscore/
@@ -41,6 +38,25 @@ if (process.env.NODE_ENV === `test` || process.env.NODE_ENV === `production`) { | |||
) | |||
} | |||
|
|||
// Persist state. | |||
const saveState = _.debounce(state => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! It's better here ;)
module.exports = (state = {}, action) => { | ||
switch (action.type) { | ||
case "ADD_PAGE_COMPONENT": | ||
if (!state[action.payload.componentPath]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This kind of pattern affraid me (a bad past experience this object[a.b.c]
…) It's proofer to use the lodash get
(it's will not break if you have an undefined
somewhere 😃 )
So for this => get(state, 'action.payload.componentPath')
(I know, normally we never should have undefined
in payload
, it's just a protection, it's not a big cost and really improve an application stability)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
} | ||
|
||
return state | ||
case "REMOVE_PAGES_DATA_DEPENDENCIES": | ||
Object.keys(state.nodes).forEach(nodeId => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oooo nice! Much cleaner.
) | ||
}) | ||
Object.keys(state.connections).forEach(connection => { | ||
state.nodes[connection] = _.difference( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think is state.connections[connection]
here
Running queries to date has been a fairly brute force operation. Let's make it faster/slimmer/testable/understandable.