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

make cache file writing sync and hashed by query #346

Merged
merged 12 commits into from
May 15, 2020
10 changes: 6 additions & 4 deletions packages/cli/src/data/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ module.exports = async (req, context) => {
/* Take the same query from request, and repeat the query for our server side cache */
const { query, variables } = req.body;

let { data } = await client.query({
const { data } = await client.query({
query: gql`${query}`,
variables
});

if (data) {
const cache = JSON.stringify(client.extract());
const md5 = crypto.createHash('md5').update(cache).digest('hex');
const md5 = crypto.createHash('md5').update(query + JSON.stringify(variables)).digest('hex');

/* Get the requests entire (full) route and rootRoute to use as reference for designated cache directory */
const { origin, referer } = req.headers;
Expand All @@ -39,8 +39,10 @@ module.exports = async (req, context) => {
const targetDir = path.join(context.publicDir, rootRoute);
const targetFile = path.join(targetDir, `${md5}-cache.json`);

await fs.mkdirs(targetDir, { recursive: true });
await fs.writeFile(path.join(targetFile), cache, 'utf8');
if (!fs.existsSync(targetFile)) {
fs.mkdirsSync(targetDir, { recursive: true });
fs.writeFileSync(path.join(targetFile), cache, 'utf8');
}
}
resolve();
} catch (err) {
Expand Down
40 changes: 37 additions & 3 deletions packages/cli/test/cases/build.data.graph/build.data.graph.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,30 @@ describe('Build Greenwood With: ', function() {
expect(await glob.promise(path.join(this.context.publicDir, './index.*.bundle.js'))).to.have.lengthOf(1);
});

it('should output one cache.json file', async function() {
it('should output one (unified) cache.json file', async function() {
expect(await glob.promise(path.join(this.context.publicDir, './cache.json'))).to.have.lengthOf(1);
});

it('should output one (unified) cache.json file that is defined', function() {
const cacheContents = require(path.join(this.context.publicDir, 'cache.json'));

expect(cacheContents).to.not.be.undefined;
});

it('should output three (partial) *-cache.json files, one per query made', async function() {
expect(await glob.promise(path.join(this.context.publicDir, './*-cache.json'))).to.have.lengthOf(3);
});

it('should output three (partial) *-cache.json files that are all defined', async function() {
const cacheFiles = await glob.promise(path.join(this.context.publicDir, './*-cache.json'));

cacheFiles.forEach(file => {
const cache = require(file);

expect(cache).to.not.be.undefined;
});
});

it('should have one window.__APOLLO_STATE__ <script> with (approximated) expected state', () => {
const scriptTags = dom.window.document.querySelectorAll('head > script');
const apolloScriptTags = Array.prototype.slice.call(scriptTags).filter(script => {
Expand Down Expand Up @@ -110,16 +130,30 @@ describe('Build Greenwood With: ', function() {
expect(fs.existsSync(path.join(this.context.publicDir, 'blog', 'first-post', 'index.html'))).to.be.true;
});

it('should output one cache.json file', async function() {
it('should output one (unified) cache.json file', async function() {
expect(await glob.promise(path.join(this.context.publicDir, 'blog', 'cache.json'))).to.have.lengthOf(1);
});

it('should output one cache.json file to be defined', function() {
it('should output one (unified) cache.json file that is defined', function() {
const cacheContents = require(path.join(this.context.publicDir, 'blog', 'cache.json'));

expect(cacheContents).to.not.be.undefined;
});

it('should output four ("partial") *-cache.json files, one per query made', async function() {
expect(await glob.promise(path.join(this.context.publicDir, 'blog', './*-cache.json'))).to.have.lengthOf(4);
});

it('should output four (partial) *-cache.json files that are defined', async function() {
const cacheFiles = await glob.promise(path.join(this.context.publicDir, 'blog', './*-cache.json'));

cacheFiles.forEach(file => {
const cache = require(file);

expect(cache).to.not.be.undefined;
});
});

it('should have one window.__APOLLO_STATE__ <script> with (approximated) expected state', () => {
const scriptTags = dom.window.document.querySelectorAll('head > script');
const apolloScriptTags = Array.prototype.slice.call(scriptTags).filter(script => {
Expand Down
41 changes: 22 additions & 19 deletions www/components/shelf/shelf.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,14 @@ class Shelf extends LitElement {

constructor() {
super();
this.page = '';
this.selectedIndex = '';
this.shelfList = [];
this.page = '';
}

async connectedCallback() {
super.connectedCallback();
if (this.page !== '' && this.page !== '/') {
const response = await client.query({
query: MenuQuery,
variables: {
name: 'side',
route: window.location.pathname,
order: 'index_asc'
}
});

this.shelfList = response.data.menu.children;
this.requestUpdate();
}

this.collapseAll();
this.expandRoute(window.location.pathname);
}

goTo(path) {
Expand All @@ -48,7 +33,6 @@ class Shelf extends LitElement {
}

expandRoute(path) {
// find list item containing current window.location.pathname
let routeShelfListIndex = this.shelfList.findIndex(list => {
let expRoute = new RegExp(`^${path}$`);
return expRoute.test(list.item.link);
Expand All @@ -57,8 +41,6 @@ class Shelf extends LitElement {
if (routeShelfListIndex > -1) {
this.shelfList[routeShelfListIndex].selected = true;
this.selectedIndex = routeShelfListIndex;
// force re-render
this.requestUpdate();
}
}

Expand Down Expand Up @@ -99,6 +81,27 @@ class Shelf extends LitElement {
this.requestUpdate();
}

async fetchShelfData() {
return await client.query({
query: MenuQuery,
variables: {
name: 'side',
route: `/${this.page}/`,
order: 'index_asc'
}
});
}

async updated(changedProperties) {
if (changedProperties.has('page') && this.page !== '' && this.page !== '/') {
const response = await this.fetchShelfData();
this.shelfList = response.data.menu.children;

this.expandRoute(window.location.pathname);
Copy link
Member Author

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.

this.requestUpdate();
}
}

renderList() {
/* eslint-disable indent */
const renderListItems = (list, selected) => {
Expand Down
3 changes: 2 additions & 1 deletion www/templates/page-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class PageTemplate extends LitElement {
this.route = '';
}

updated() {
connectedCallback() {
super.connectedCallback();
this.route = window.location.pathname;
Copy link
Member

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.

Copy link
Member Author

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".

}

Expand Down