mirror of
https://github.com/svemagie/blog-eleventy-indiekit.git
synced 2026-04-02 16:44:56 +02:00
Introduce shared cachedFetch helper (lib/data-fetch.js) wrapping EleventyFetch with two protections: - 10-second hard timeout via AbortController on every network request, preventing slow or unresponsive APIs from hanging the build - 4-hour cache TTL in watch/serve mode (vs 5-15 min originals), so incremental rebuilds serve from disk cache instead of re-fetching APIs every time a markdown file changes All 13 network _data files updated to use cachedFetch. Production builds keep original short TTLs for fresh data. Targets the "Data File" benchmark (12,169ms / 32% of incremental rebuild) — the largest remaining bottleneck after filter memoization. Confab-Link: http://localhost:8080/sessions/0b241cd6-aff2-4fec-853c-2b5a61e61946
55 lines
1.6 KiB
JavaScript
55 lines
1.6 KiB
JavaScript
/**
|
|
* Shared data-fetching helper for _data files.
|
|
*
|
|
* Wraps @11ty/eleventy-fetch with two protections:
|
|
* 1. Hard timeout — 10-second AbortController ceiling on every request
|
|
* 2. Watch-mode cache extension — uses "4h" TTL during watch/serve,
|
|
* keeping the original (shorter) TTL only for production builds
|
|
*
|
|
* Usage:
|
|
* import { cachedFetch } from "../lib/data-fetch.js";
|
|
* const data = await cachedFetch(url, { duration: "15m", type: "json" });
|
|
*/
|
|
|
|
import EleventyFetch from "@11ty/eleventy-fetch";
|
|
|
|
const FETCH_TIMEOUT_MS = 10_000; // 10 seconds
|
|
|
|
// In watch/serve mode, extend cache to avoid re-fetching on every rebuild.
|
|
// Production builds use the caller's original TTL for fresh data.
|
|
const isWatchMode = process.env.ELEVENTY_RUN_MODE !== "build";
|
|
const WATCH_MODE_DURATION = "4h";
|
|
|
|
/**
|
|
* Fetch with timeout and watch-mode cache extension.
|
|
*
|
|
* @param {string} url - URL to fetch
|
|
* @param {object} options - EleventyFetch options (duration, type, fetchOptions, etc.)
|
|
* @returns {Promise<any>} Parsed response
|
|
*/
|
|
export async function cachedFetch(url, options = {}) {
|
|
// Extend cache in watch mode
|
|
const duration = isWatchMode ? WATCH_MODE_DURATION : (options.duration || "15m");
|
|
|
|
// Create abort controller for hard timeout
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
|
|
try {
|
|
const fetchOptions = {
|
|
...options.fetchOptions,
|
|
signal: controller.signal,
|
|
};
|
|
|
|
const result = await EleventyFetch(url, {
|
|
...options,
|
|
duration,
|
|
fetchOptions,
|
|
});
|
|
|
|
return result;
|
|
} finally {
|
|
clearTimeout(timeoutId);
|
|
}
|
|
}
|