-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Try prefetching again using a Map<Promise> to avoid duplicate requests
- Loading branch information
1 parent
19237aa
commit ec0d74e
Showing
1 changed file
with
43 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ const IN_PROGRESS = 'A transition is currently in progress' | |
/** | ||
* @typedef CacheEntry | ||
* @type {object} | ||
* @property {typeof Renderer} renderer | ||
* @property {typeof Renderer|Renderer} renderer | ||
* @property {Document|Node} page | ||
* @property {array} scripts | ||
* @property {boolean} skipCache | ||
|
@@ -30,12 +30,19 @@ export default class Core { | |
*/ | ||
cache = new Map() | ||
|
||
/** | ||
* @private | ||
* @type {Map<string, Promise>} | ||
*/ | ||
activePromises = new Map() | ||
|
||
/** | ||
* @param {{ | ||
* links?: string, | ||
* removeOldContent?: boolean, | ||
* allowInterruption?: boolean, | ||
* bypassCache?: boolean, | ||
* enablePrefetch?: boolean, | ||
* renderers?: Object.<string, typeof Renderer>, | ||
* transitions?: Object.<string, typeof Transition>, | ||
* reloadJsFilter?: boolean|function(HTMLElement): boolean | ||
|
@@ -47,6 +54,7 @@ export default class Core { | |
removeOldContent = true, | ||
allowInterruption = false, | ||
bypassCache = false, | ||
enablePrefetch = true, | ||
renderers = { | ||
default: Renderer | ||
}, | ||
|
@@ -65,6 +73,7 @@ export default class Core { | |
this.removeOldContent = removeOldContent | ||
this.allowInterruption = allowInterruption | ||
this.bypassCache = bypassCache | ||
this.enablePrefetch = enablePrefetch | ||
this.cache = new Map() | ||
this.isPopping = false | ||
|
||
|
@@ -190,15 +199,15 @@ export default class Core { | |
let navigationPromise | ||
|
||
if (this.bypassCache || !this.cache.has(this.targetLocation.href) || this.cache.get(this.targetLocation.href).skipCache) { | ||
const fetched = this.fetch(this.targetLocation.raw) | ||
const fetched = this.fetch(this.targetLocation.href) | ||
.then((newPage) => { | ||
this.cache.set(this.targetLocation.href, this.createCacheEntry(newPage)) | ||
this.cache.get(this.targetLocation.href).renderer.createDom() | ||
}) | ||
|
||
navigationPromise = this.beforeFetch(this.targetLocation, TransitionClass, trigger) | ||
.then(async () => { | ||
return fetched.then(async (newPage) => { | ||
return fetched.then(async () => { | ||
return await this.afterFetch(this.targetLocation, TransitionClass, this.cache.get(this.targetLocation.href), trigger) | ||
}) | ||
}) | ||
|
@@ -333,6 +342,10 @@ export default class Core { | |
attachEvents(links) { | ||
E.delegate('click', links, this.onClick) | ||
E.on('popstate', window, this.onPopstate) | ||
|
||
if (this.enablePrefetch) { | ||
E.delegate('mouseenter focus', links, this.onPrefetch) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jakewhiteley
Author
Member
|
||
} | ||
} | ||
|
||
/** | ||
|
@@ -390,14 +403,33 @@ export default class Core { | |
this.navigateTo(window.location.href, false, 'popstate') | ||
} | ||
|
||
/** | ||
* @private | ||
* @param {MouseEvent} e | ||
*/ | ||
onPrefetch = (e) => { | ||
const target = processUrl(e.currentTarget.href) | ||
|
||
if (this.currentLocation.host !== target.host) { | ||
return | ||
} | ||
|
||
this.preload(e.currentTarget.href, false) | ||
} | ||
|
||
/** | ||
* @private | ||
* @param {string} url | ||
* @param {boolean} [runFallback] | ||
* @return {Promise<Document>} | ||
*/ | ||
fetch(url, runFallback = true) { | ||
return new Promise((resolve, reject) => { | ||
// If Taxi is currently performing a fetch for the given URL, return that instead of starting a new request | ||
if (this.activePromises.has(url)) { | ||
return this.activePromises.get(url) | ||
} | ||
|
||
const request = new Promise((resolve, reject) => { | ||
fetch(url, { | ||
mode: 'same-origin', | ||
method: 'GET', | ||
|
@@ -425,7 +457,14 @@ export default class Core { | |
window.location.href = url | ||
} | ||
}) | ||
.finally(() => { | ||
this.activePromises.delete(url) | ||
}) | ||
}) | ||
|
||
this.activePromises.set(url, request) | ||
|
||
return request | ||
} | ||
|
||
/** | ||
|
I'd add listening to the
touchstart
event, @jakewhiteley. It's also used in libraries like https://github.com/weebney/tachyon or instant.page. :)