@sc4rfurryx/proteusjs
Version:
The Modern Web Development Framework for Accessible, Responsive, and High-Performance Applications. Intelligent container queries, fluid typography, WCAG compliance, and performance optimization.
258 lines (256 loc) • 8.44 kB
JavaScript
/*!
* ProteusJS v2.0.0
* Shape-shifting responsive design that adapts like the sea god himself
* (c) 2025 sc4rfurry
* Released under the MIT License
*/
/**
* @sc4rfurryx/proteusjs/perf
* Performance guardrails and CWV-friendly patterns
*
* @version 2.0.0
* @author sc4rfurry
* @license MIT
*/
/**
* Apply content-visibility for performance optimization
*/
function contentVisibility(selector, mode = 'auto', opts = {}) {
const elements = typeof selector === 'string'
? document.querySelectorAll(selector)
: [selector];
const { containIntrinsicSize = '1000px 400px' } = opts;
elements.forEach(element => {
const el = element;
el.style.contentVisibility = mode;
if (mode === 'auto') {
el.style.containIntrinsicSize = containIntrinsicSize;
}
});
}
/**
* Set fetch priority for resources
*/
function fetchPriority(selector, priority) {
const elements = typeof selector === 'string'
? document.querySelectorAll(selector)
: [selector];
elements.forEach(element => {
if (element instanceof HTMLImageElement ||
element instanceof HTMLLinkElement ||
element instanceof HTMLScriptElement) {
element.fetchPriority = priority;
}
});
}
/**
* Set up speculation rules for prerendering and prefetching
*/
function speculate(opts) {
const { prerender = [], prefetch = [], sameOriginOnly = true } = opts;
// Check for Speculation Rules API support
if (!('supports' in HTMLScriptElement && HTMLScriptElement.supports('speculationrules'))) {
console.warn('Speculation Rules API not supported');
return;
}
const rules = {};
if (prerender.length > 0) {
rules.prerender = prerender.map(url => {
const rule = { where: { href_matches: url } };
if (sameOriginOnly) {
rule.where.href_matches = new URL(url, window.location.origin).href;
}
return rule;
});
}
if (prefetch.length > 0) {
rules.prefetch = prefetch.map(url => {
const rule = { where: { href_matches: url } };
if (sameOriginOnly) {
rule.where.href_matches = new URL(url, window.location.origin).href;
}
return rule;
});
}
if (Object.keys(rules).length === 0)
return;
// Create and inject speculation rules script
const script = document.createElement('script');
script.type = 'speculationrules';
script.textContent = JSON.stringify(rules);
document.head.appendChild(script);
}
/**
* Yield to browser using scheduler.yield or postTask when available
*/
async function yieldToBrowser() {
// Use scheduler.yield if available (Chrome 115+)
if ('scheduler' in window && 'yield' in window.scheduler) {
return window.scheduler.yield();
}
// Use scheduler.postTask if available
if ('scheduler' in window && 'postTask' in window.scheduler) {
return new Promise(resolve => {
window.scheduler.postTask(resolve, { priority: 'user-blocking' });
});
}
// Fallback to setTimeout
return new Promise(resolve => {
setTimeout(resolve, 0);
});
}
/**
* Optimize images with loading and decoding hints
*/
function optimizeImages(selector = 'img') {
const images = typeof selector === 'string'
? document.querySelectorAll(selector)
: [selector];
images.forEach(img => {
if (!(img instanceof HTMLImageElement))
return;
// Set loading attribute if not already set
if (!img.hasAttribute('loading')) {
const rect = img.getBoundingClientRect();
const isAboveFold = rect.top < window.innerHeight;
img.loading = isAboveFold ? 'eager' : 'lazy';
}
// Set decoding hint
if (!img.hasAttribute('decoding')) {
img.decoding = 'async';
}
// Set fetch priority for above-fold images
if (!img.hasAttribute('fetchpriority')) {
const rect = img.getBoundingClientRect();
const isAboveFold = rect.top < window.innerHeight;
if (isAboveFold) {
img.fetchPriority = 'high';
}
}
});
}
/**
* Preload critical resources
*/
function preloadCritical(resources) {
resources.forEach(({ href, as, type }) => {
// Check if already preloaded
const existing = document.querySelector(`link[rel="preload"][href="${href}"]`);
if (existing)
return;
const link = document.createElement('link');
link.rel = 'preload';
link.href = href;
link.as = as;
if (type) {
link.type = type;
}
document.head.appendChild(link);
});
}
/**
* Measure and report Core Web Vitals
*/
function measureCWV() {
return new Promise(resolve => {
const metrics = {};
let metricsCount = 0;
const totalMetrics = 3;
const checkComplete = () => {
metricsCount++;
if (metricsCount >= totalMetrics) {
resolve(metrics);
}
};
// LCP (Largest Contentful Paint)
if ('PerformanceObserver' in window) {
try {
const lcpObserver = new PerformanceObserver(list => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
metrics.lcp = lastEntry.startTime;
});
lcpObserver.observe({ entryTypes: ['largest-contentful-paint'] });
// Stop observing after 10 seconds
setTimeout(() => {
lcpObserver.disconnect();
checkComplete();
}, 10000);
}
catch {
checkComplete();
}
// FID (First Input Delay)
try {
const fidObserver = new PerformanceObserver(list => {
const entries = list.getEntries();
entries.forEach((entry) => {
metrics.fid = entry.processingStart - entry.startTime;
});
fidObserver.disconnect();
checkComplete();
});
fidObserver.observe({ entryTypes: ['first-input'] });
// If no input after 10 seconds, consider FID as 0
setTimeout(() => {
if (metrics.fid === undefined) {
metrics.fid = 0;
fidObserver.disconnect();
checkComplete();
}
}, 10000);
}
catch {
checkComplete();
}
// CLS (Cumulative Layout Shift)
try {
let clsValue = 0;
const clsObserver = new PerformanceObserver(list => {
list.getEntries().forEach((entry) => {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
});
metrics.cls = clsValue;
});
clsObserver.observe({ entryTypes: ['layout-shift'] });
// Stop observing after 10 seconds
setTimeout(() => {
clsObserver.disconnect();
checkComplete();
}, 10000);
}
catch {
checkComplete();
}
}
else {
// Fallback if PerformanceObserver is not supported
setTimeout(() => resolve(metrics), 100);
}
});
}
// Export boost object to match usage examples in upgrade spec
const boost = {
contentVisibility,
fetchPriority,
speculate,
yieldToBrowser,
optimizeImages,
preloadCritical,
measureCWV
};
// Export all functions as named exports and default object
var index = {
contentVisibility,
fetchPriority,
speculate,
yieldToBrowser,
optimizeImages,
preloadCritical,
measureCWV,
boost
};
export { boost, contentVisibility, index as default, fetchPriority, measureCWV, optimizeImages, preloadCritical, speculate, yieldToBrowser };
//# sourceMappingURL=perf.esm.js.map