From eeeacb7bdec3ce43702f85af46b8bdb2b2336c22 Mon Sep 17 00:00:00 2001 From: Kazuyoshi Kato Date: Thu, 5 Dec 2019 06:38:01 -0800 Subject: [PATCH 1/2] Make / work under FastBoot This commit adds a transparent cache called "fetcher" to prevent making 2 XHRs (both from the frontend to the backend). --- app/controllers/index.js | 28 +--------------------------- app/routes/index.js | 23 ++++++++++++++++++++++- app/services/fetcher.js | 31 +++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 app/services/fetcher.js diff --git a/app/controllers/index.js b/app/controllers/index.js index 6d05773771..6b5263cde0 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -1,31 +1,5 @@ import Controller from '@ember/controller'; -import { computed } from '@ember/object'; -import { readOnly } from '@ember/object/computed'; - -import ajax from 'ember-fetch/ajax'; -import { task } from 'ember-concurrency'; export default Controller.extend({ - model: readOnly('dataTask.lastSuccessful.value'), - - hasData: computed('dataTask.{lastSuccessful,isRunning}', function() { - return this.get('dataTask.lastSuccessful') || !this.get('dataTask.isRunning'); - }), - - dataTask: task(function*() { - let data = yield ajax('/api/v1/summary'); - - addCrates(this.store, data.new_crates); - addCrates(this.store, data.most_downloaded); - addCrates(this.store, data.just_updated); - addCrates(this.store, data.most_recently_downloaded); - - return data; - }).drop(), + hasData: true, }); - -function addCrates(store, crates) { - for (let i = 0; i < crates.length; i++) { - crates[i] = store.push(store.normalize('crate', crates[i])); - } -} diff --git a/app/routes/index.js b/app/routes/index.js index b4a8f83619..78d43c4659 100644 --- a/app/routes/index.js +++ b/app/routes/index.js @@ -1,6 +1,9 @@ import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; export default Route.extend({ + fetcher: service(), + headTags() { return [ { @@ -13,8 +16,26 @@ export default Route.extend({ ]; }, + // eslint-disable-next-line no-unused-vars setupController(controller) { this.controllerFor('application').set('searchQuery', null); - controller.dataTask.perform(); + }, + + model() { + return this.fetcher.ajax('/api/v1/summary'); + }, + + // eslint-disable-next-line no-unused-vars + afterModel(model, transition) { + addCrates(this.store, model.new_crates); + addCrates(this.store, model.most_downloaded); + addCrates(this.store, model.just_updated); + addCrates(this.store, model.most_recently_downloaded); }, }); + +function addCrates(store, crates) { + for (let i = 0; i < crates.length; i++) { + crates[i] = store.push(store.normalize('crate', crates[i])); + } +} diff --git a/app/services/fetcher.js b/app/services/fetcher.js new file mode 100644 index 0000000000..dcf1dc2299 --- /dev/null +++ b/app/services/fetcher.js @@ -0,0 +1,31 @@ +import Service, { inject as service } from '@ember/service'; +import ajax from 'ember-fetch/ajax'; + +export default Service.extend({ + fastboot: service(), + + ajax(url) { + let fastboot = this.fastboot; + let shoebox = this.fastboot.shoebox; + let cache = shoebox.retrieve('ajax-cache'); + if (!cache) { + cache = {}; + } + + if (cache[url]) { + return cache[url]; + } + + return ajax(url).then(function(resp) { + if (shoebox && fastboot.isFastBoot) { + cache[url] = deepCopy(resp); + shoebox.put('ajax-cache', cache); + } + return resp; + }); + }, +}); + +function deepCopy(obj) { + return JSON.parse(JSON.stringify(obj)); +} From 380b07db58549ee335416d777f1cf71b443afac0 Mon Sep 17 00:00:00 2001 From: Kazuyoshi Kato Date: Mon, 9 Dec 2019 22:32:06 -0800 Subject: [PATCH 2/2] Fix non-FastBoot case https://api.emberjs.com/ember/3.14/classes/Route/methods/setupController?anchor=setupController > If you implement the setupController hook in your Route, it will prevent this default behavior. --- app/routes/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/routes/index.js b/app/routes/index.js index 78d43c4659..226dd33e6f 100644 --- a/app/routes/index.js +++ b/app/routes/index.js @@ -16,8 +16,8 @@ export default Route.extend({ ]; }, - // eslint-disable-next-line no-unused-vars - setupController(controller) { + setupController(controller, model) { + this._super(controller, model); this.controllerFor('application').set('searchQuery', null); },