Skip to content

Commit

Permalink
Added control of Access-Control-Allow-Origin and Credentials
Browse files Browse the repository at this point in the history
  • Loading branch information
giorgiopellegrino committed Dec 5, 2024
1 parent bc6f2cd commit 037e592
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 57 deletions.
8 changes: 4 additions & 4 deletions .size-limit.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
[
{
"path": "dist/quicklink.js",
"limit": "2.36 kB",
"limit": "2 kB",
"gzip": true
},
{
"path": "dist/quicklink.mjs",
"limit": "2.36 kB",
"limit": "2 kB",
"gzip": true
},
{
"path": "dist/quicklink.modern.mjs",
"limit": "1.91 kB",
"limit": "1.6 kB",
"gzip": true
},
{
"path": "dist/quicklink.umd.js",
"limit": "2.43 kB",
"limit": "2 kB",
"gzip": true
}
]
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "quicklink",
"version": "2.4.0",
"version": "2.3.0",
"description": "Faster subsequent page-loads by prefetching in-viewport links during idle time",
"repository": {
"type": "git",
Expand Down
19 changes: 8 additions & 11 deletions src/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
**/

import throttle from 'throttles';
import {prefetchOnHover, supported, viaFetch} from './prefetch.mjs';
import {supported, viaFetch} from './prefetch.mjs';
import requestIdleCallback from './request-idle-callback.mjs';
import {addSpeculationRules, hasSpecRulesSupport} from './prerender.mjs';

Expand Down Expand Up @@ -87,7 +87,6 @@ function checkConnection(conn) {
* @param {Function} [options.hrefFn] - Function to use to build the URL to prefetch.
* If it's not a valid function, then it will use the entry href.
* @param {Boolean} [options.prerender] - Option to switch from prefetching and use prerendering only
* @param {String} [options.eagerness] - Prerender eagerness mode - default immediate
* @param {Boolean} [options.prerenderAndPrefetch] - Option to use both prerendering and prefetching
* @return {Function}
*/
Expand Down Expand Up @@ -137,7 +136,7 @@ export function listen(options = {}) {
// either it's the prerender + prefetch mode or it's prerender *only* mode
// Prerendering limit is following options.limit. UA may impose arbitraty numeric limit
if ((shouldPrerenderAndPrefetch || shouldOnlyPrerender) && toPrerender.size < limit) {
prerender(hrefFn ? hrefFn(entry) : entry.href, options.eagerness).catch(error => {
prerender(hrefFn ? hrefFn(entry) : entry.href).catch(error => {
if (options.onError) {
options.onError(error);
} else {
Expand All @@ -152,7 +151,7 @@ export function listen(options = {}) {
if (toPrefetch.size < limit && !shouldOnlyPrerender) {
toAdd(() => {
prefetch(hrefFn ? hrefFn(entry) : entry.href, options.priority,
options.checkAccessControlAllowOrigin, options.checkAccessControlAllowCredentials, options.onlyOnMouseover)
options.checkAccessControlAllowOrigin, options.checkAccessControlAllowCredentials)
.then(isDone)
.catch(error => {
isDone();
Expand Down Expand Up @@ -210,10 +209,9 @@ export function listen(options = {}) {
* @param {Boolean} checkAccessControlAllowOrigin - true to set crossorigin="anonymous" for DOM prefetch
* and mode:'cors' for API fetch
* @param {Boolean} checkAccessControlAllowCredentials - true to set credentials:'include' for API fetch
* @param {Boolean} onlyOnMouseover - true to enable prefetch only on mouseover event
* @return {Object} a Promise
*/
export function prefetch(url, isPriority, checkAccessControlAllowOrigin, checkAccessControlAllowCredentials, onlyOnMouseover) {
export function prefetch(url, isPriority, checkAccessControlAllowOrigin, checkAccessControlAllowCredentials) {
const chkConn = checkConnection(navigator.connection);
if (chkConn instanceof Error) {
return Promise.reject(new Error(`Cannot prefetch, ${chkConn.message}`));
Expand All @@ -232,7 +230,7 @@ export function prefetch(url, isPriority, checkAccessControlAllowOrigin, checkAc
// ~> so that we don't repeat broken links
toPrefetch.add(str);

return prefetchOnHover((isPriority ? viaFetch : supported), new URL(str, location.href).toString(), onlyOnMouseover,
return (isPriority ? viaFetch : supported)(new URL(str, location.href).toString(),
checkAccessControlAllowOrigin, checkAccessControlAllowCredentials, isPriority);
}),
);
Expand All @@ -241,10 +239,9 @@ export function prefetch(url, isPriority, checkAccessControlAllowOrigin, checkAc
/**
* Prerender a given URL
* @param {String} urls - the URL to fetch
* @param {String} eagerness - prerender eagerness mode - default immediate
* @return {Object} a Promise
*/
export function prerender(urls, eagerness = 'immediate') {
export function prerender(urls) {
const chkConn = checkConnection(navigator.connection);
if (chkConn instanceof Error) {
return Promise.reject(new Error(`Cannot prerender, ${chkConn.message}`));
Expand All @@ -254,7 +251,7 @@ export function prerender(urls, eagerness = 'immediate') {
// 1) whether UA supports spec rules.. If not, fallback to prefetch
// Note: Prerendering supports same-site cross origin with opt-in header
if (!hasSpecRulesSupport()) {
prefetch(urls, true, false, false, eagerness === 'moderate' || eagerness === 'conservative');
prefetch(urls, true, false, false);
return Promise.reject(new Error('This browser does not support the speculation rules API. Falling back to prefetch.'));
}

Expand All @@ -267,6 +264,6 @@ export function prerender(urls, eagerness = 'immediate') {
console.warn('[Warning] You are using both prefetching and prerendering on the same document');
}

const addSpecRules = addSpeculationRules(toPrerender, eagerness);
const addSpecRules = addSpeculationRules(toPrerender);
return addSpecRules === true ? Promise.resolve() : Promise.reject(addSpecRules);
}
37 changes: 0 additions & 37 deletions src/prefetch.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -101,41 +101,4 @@ export function viaFetch(url, hasModeCors, hasCredentials, isPriority) {
return window.fetch ? fetch(url, options) : viaXHR(url, hasCredentials);
}

/**
* Calls the prefetch function immediately
* or only on the mouseover event.
* @param {Function} callback - original prefetch function
* @param {String} url - url to prefetch
* @param {Boolean} onlyOnMouseover - true to add the mouseover listener
* @return {Object} a Promise
*/
export function prefetchOnHover(callback, url, onlyOnMouseover, ...args) {
if (!onlyOnMouseover) return callback(url, ...args);

const elements = document.querySelectorAll(`a[href="${decodeURIComponent(url)}"]`);
const timerMap = new Map();

for (const el of elements) {
const mouseenterListener = e => {
const timer = setTimeout(() => {
el.removeEventListener('mouseenter', mouseenterListener);
el.removeEventListener('mouseleave', mouseleaveListener);
return callback(url, ...args);
}, 200);
timerMap.set(el, timer);
};

const mouseleaveListener = e => {
const timer = timerMap.get(el);
if (timer) {
clearTimeout(timer);
timerMap.delete(el);
}
};

el.addEventListener('mouseenter', mouseenterListener);
el.addEventListener('mouseleave', mouseleaveListener);
}
}

export const supported = hasPrefetch() ? viaDOM : viaFetch;
6 changes: 2 additions & 4 deletions src/prerender.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@
* @param {String} eagerness - prerender eagerness mode
* @return {Boolean|Object} boolean or Error Object
*/
export function addSpeculationRules(urlsToPrerender, eagerness) {
export function addSpeculationRules(urlsToPrerender) {
const specScript = document.createElement('script');
specScript.type = 'speculationrules';
specScript.text = `{"prerender":[{"source": "list",
"urls": ["${Array.from(urlsToPrerender).join('","')}"],
"eagerness": "${eagerness}"}]}`;
specScript.text = `{"prerender":[{"source": "list","urls": ["${Array.from(urlsToPrerender).join('","')}"]}]}`;
try {
document.head.appendChild(specScript);
} catch (error) {
Expand Down

0 comments on commit 037e592

Please sign in to comment.