-
Notifications
You must be signed in to change notification settings - Fork 10
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
make cache file writing sync and hashed by query #346
Conversation
Ugh... getting these stupid invariant errors in the Netlify preview environment. :/ I don't know if it's related to this change though...? Had a thought on it here #331 (comment) |
Your Menu Query for the side menu is not being cached. Check cached files and you'll see theres only a navigation menu query, config, and graph queries. Notice how our testing didn't catch this? Because it relies on mock graph. |
When using: const md5 = crypto.createHash('md5').update(query).digest('hex'); I saw the following error:
It's not being caught. I was only able to catch it by switching back to async fs.writeFile and fs.mkdirs. If you switch back to: const md5 = crypto.createHash('md5').update(cache).digest('hex'); While still using synchronous as per this PR, it works fine, no errors. |
Oof... 🤦♂️
Yeah, noticed that too. Will see if I can do something about that somehow.
Not quite sure I understand, but you are saying saw the JSON parse error when testing this branch and using So this might be a bit more complex of an issue, but I then since every page gets serialized in parallel, all these GraphQL queries are happening as well. I think it would be similar to what we did here for #271 ? So the most sure fire way would be to make it all synchronous then. Or i guess try the file locking approach? Other options? |
The reason you aren't creating a side menu cache is simple: you're using the same data to generate a hash and therefore it only writes one file for two different(albeit similar) queries! menu query for side and navigation: query ($name: String, $route: String, $order: MenuOrderBy) {
menu(name: $name, pathname: $route, orderBy: $order) {
item {
label
link
__typename
}
children {
item {
label
link
__typename
}
children {
item {
label
link
__typename
}
__typename
}
__typename
}
__typename
}
} The fix is to include the query's variables to make it unique for the separate menus: const md5 = crypto.createHash('md5').update(query + JSON.stringify(variables)).digest('hex'); downside to this is we get a unique menu for each pathname as well. Therefore every page generates a menu cache. Try the above and then take a look at the cache files in the |
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.
menu query for side and navigation:
ah, right, of course! two menu queries. thanks, now it all makes sense
downside to this is we get a unique menu for each pathname as well. Therefore every page generates a menu cache.
Hmm, yeah. I think I fixed this as well? One thing that helps make this cleaner is that I refactored the shelf to use the "prop" from the page-template.js for route
and using that within the update
lifecycle. So now GraphQL will get called using this.page
; pretty neat!.
Now, we still have the multiple fetch
calls due to over-rendering, but all the file sizes are now better.
However, now although this seems to be working locally, on Netlify, I sometimes seems to get a shelf that just wont load for a page. Maybe once every 5 clicks? Just keep clicking the header from left to right, and back. eventually one will be blank and no errors.
Getter closer though. :crossed
if (changedProperties.has('page') && this.page !== '' && this.page !== '/') { | ||
await this.fetchShelfData(); | ||
|
||
this.expandRoute(window.location.pathname); |
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'm thinking I would even like to go so further as to just pass the full route from the page-template.js, then the shelf would have access to the full path via "props", and that could be used here instead of window.location.pathname
).
Just could help keep the shelf a little more self contained.
www/components/shelf/shelf.js
Outdated
console.log('ENTER updated - changedProperties', changedProperties); | ||
console.log('updated - this.page', this.page); | ||
if (changedProperties.has('page') && this.page !== '' && this.page !== '/') { | ||
await this.fetchShelfData(); |
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're expecting to return a promise that doesn't exist. Maybe just return the query(which is a promise) like this:
const response = await this.fetchShelfData();
this.shelfList = response.data.menu.children;
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.
still happening, I guess I should just revert back the connectedCallback
/ window.location.pathname
approach then?
Not sure if we'll need to start recommending / documenting certain patterns around this stuff then, though I would hope we don't have to be any different than SPA development. Like if having unpredictable lifecycles could be a concern, or just needing to guard initial values of your variables.
@@ -26,12 +26,14 @@ class PageTemplate extends LitElement { | |||
} | |||
|
|||
updated() { | |||
console.log('ENTER page template updated', window.location.pathname); | |||
this.route = window.location.pathname; |
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.
My understanding is this lifecycle is run after the component has been rendered. I tested using the connectedCallback() to set the this.page variable from the page-template and had better results (I wasn't able to break it). Maybe that's just chance, I don't 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.
this.page
was actually undefined at that point, so updated
seemed like a good way to make the sure the value is "ready".
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.
My understanding is this lifecycle is run after the component has been rendered. I tested using the connectedCallback() to set the this.page variable from the page-template and had better results (I wasn't able to break it). Maybe that's just chance, I don't know.
💥
I didn't release you meant the page-template.js! Thought you meant the shelf. It's working now though!
Will remove the console logs and commented out code. Nice, thanks for the help on this. The async kid saves the day again. 🏆
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.
@hutchgrant
Unless there are any objections, would like to get this approved / merged soonish (today / tomorrow) now that the disappearing shelf issue is fixed, so we can cut an 0.5.1
release ASAP.
We can then work on the other related issues we've uncovered in parallel, but this one certainly being the most egregious due to the increased cache.json size coupled with the over fetching. (although to combat the index.js bundle size, I'll be working on #305 as a means to an end on that)
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.
Related Issue
resolves #345
Summary of Changes