Skip to content

Commit

Permalink
feat(prefetch): ✨ limit the number of prefetched links
Browse files Browse the repository at this point in the history
This close #708.
  • Loading branch information
xavierfoucrier committed May 12, 2023
2 parents 59acc45 + 779936a commit 68c8914
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 28 deletions.
3 changes: 3 additions & 0 deletions packages/prefetch/__tests__/prefetch.init.test.ts
Expand Up @@ -31,6 +31,7 @@ it('init with defaults', () => {

expect(prefetch.root).toBe(document.body);
expect(prefetch.timeout).toBe(2e3);
expect(prefetch.limit).toBe(0);
expect(prefetch.observe).toHaveBeenCalled();
});

Expand All @@ -40,11 +41,13 @@ it('init with options', () => {
barba.use(prefetch, {
root: wrapper,
timeout: 0,
limit: 0
});
barba.init();

expect(prefetch.root).toBe(wrapper);
expect(prefetch.timeout).toBe(0);
expect(prefetch.limit).toBe(0);
});

it('registers hooks', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/prefetch/src/defs/index.ts
Expand Up @@ -5,4 +5,5 @@
export interface IPrefetchOptions {
root?: HTMLElement | HTMLDocument;
timeout?: number;
limit?: number;
}
70 changes: 42 additions & 28 deletions packages/prefetch/src/prefetch.ts
Expand Up @@ -28,20 +28,22 @@ class Prefetch implements IBarbaPlugin<IPrefetchOptions> {
public observer: IntersectionObserver;
public root: HTMLElement | HTMLDocument;
public timeout: number;
public limit: number;
public toPrefetch: Set<string> = new Set();

/**
* Plugin installation.
*/
public install(
barba: Core,
{ root = document.body, timeout = 2e3 }: IPrefetchOptions = {}
{ root = document.body, timeout = 2e3, limit = 0 }: IPrefetchOptions = {}
) {
this.logger = new barba.Logger(this.name);
this.logger.info(this.version);
this.barba = barba;
this.root = root;
this.timeout = timeout;
this.limit = limit;
}

/**
Expand All @@ -68,38 +70,44 @@ class Prefetch implements IBarbaPlugin<IPrefetchOptions> {
/* istanbul ignore next */
this.observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const link = entry.target as Link;
const href = this.barba.dom.getHref(link);
if (!entry.isIntersecting) {
return;
}

const link = entry.target as Link;
const href = this.barba.dom.getHref(link);

if (!this.toPrefetch.has(href)) {
return;
}

this.observer.unobserve(link);

if (this.toPrefetch.has(href)) {
this.observer.unobserve(link);
// Prefetch and cache
if (!this.barba.cache.has(href)) {
this.barba.cache.set(
// Prefetch and cache
if (!this.barba.cache.has(href)) {
this.barba.cache.set(
href,
this.barba
.request(
href,
this.barba
.request(
href,
this.barba.timeout,
this.barba['onRequestError'].bind(this.barba, 'barba'), // tslint:disable-line:no-string-literal
this.barba.cache,
this.barba.headers
)
.catch(error => {
this.logger.error(error);
}),
'prefetch',
'pending'
);
} else {
this.barba.cache.update(href, { action: 'prefetch' });
}
}
this.barba.timeout,
this.barba['onRequestError'].bind(this.barba, 'barba'), // tslint:disable-line:no-string-literal
this.barba.cache,
this.barba.headers
)
.catch(error => {
this.logger.error(error);
}),
'prefetch',
'pending'
);
} else {
this.barba.cache.update(href, { action: 'prefetch' });
}
});
});
this.observe();

// Register hooks
this.barba.hooks.after(this.observe, this);
}
Expand All @@ -110,8 +118,14 @@ class Prefetch implements IBarbaPlugin<IPrefetchOptions> {

requestIdleCallback(
() => {
let links = Array.from(this.root.querySelectorAll('a'));

if (this.limit > 0) {
links = links.slice(0, this.limit);
}

// If not, find all links and use IntersectionObserver.
this.root.querySelectorAll('a').forEach(el => {
links.forEach(el => {
const link = (el as unknown) as Link;
const href = this.barba.dom.getHref(link);

Expand Down

0 comments on commit 68c8914

Please sign in to comment.