diff --git a/.jules/bolt.md b/.jules/bolt.md index 2e5d9d4..a4dee8a 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -5,3 +5,7 @@ This journal documents critical performance learnings for the 5L Labs project. ## 2026-02-22 - Font Loading Optimization **Learning:** Using `preconnect` for `fonts.gstatic.com` significantly improves FCP by establishing the connection early. **Action:** Always include `preconnect` links for external font providers in `docusaurus.config.js`. + +## 2026-02-23 - Build Script O(N) Read Optimization +**Learning:** Build scripts that iterate chronologically over files (like finding the latest post) can suffer from O(N) I/O and parsing overhead if they indiscriminately read and parse every file that is newer than the *current* maximum. +**Action:** When finding the newest file, use a two-pass algorithm. First pass: iterate over directory listings and identify the target file using only filenames (and regex matches on dates in the filename). Second pass: perform expensive file reads (`fs.readFileSync`) and parsing (e.g., `gray-matter`) *only* on the single target file. diff --git a/scripts/generate-latest-post.js b/scripts/generate-latest-post.js index 4b8f66a..58da7c9 100644 --- a/scripts/generate-latest-post.js +++ b/scripts/generate-latest-post.js @@ -42,8 +42,15 @@ function stripMarkdown(markdown) { function getLatestPost() { let latestPost = null; + let latestPostMeta = null; const DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})/; + // ⚡ Bolt: Two-pass algorithm optimization. + // Instead of reading and parsing frontmatter for every file that happens to be newer + // than the current max during iteration, we first find the single newest file by just + // examining filenames (O(1) memory, O(1) reads). Then we read and parse ONLY that file. + + // First pass: find the newest file path and its metadata BLOG_DIRS.forEach(dir => { const dirPath = path.join(__dirname, '..', dir); if (!fs.existsSync(dirPath)) return; @@ -59,39 +66,54 @@ function getLatestPost() { const [_, yearStr, monthStr, dayStr] = match; const date = new Date(`${yearStr}-${monthStr}-${dayStr}`); - if (!latestPost || date > latestPost.date) { - const content = fs.readFileSync(path.join(dirPath, file), 'utf-8'); - const { data, content: markdownContent } = matter(content); + if (!latestPostMeta || date > latestPostMeta.date) { + latestPostMeta = { + date, + file, + dirPath, + dir, + yearStr, + monthStr, + dayStr + }; + } + }); + }); - let postContent = ''; - if (data.description) { - postContent = data.description; - } else { - postContent = stripMarkdown(markdownContent); - } + // Second pass: read and parse ONLY the newest file discovered + if (latestPostMeta) { + const { date, file, dirPath, dir, yearStr, monthStr, dayStr } = latestPostMeta; - const truncated = postContent.length > 550 ? postContent.substring(0, 550) + '...' : postContent; + const content = fs.readFileSync(path.join(dirPath, file), 'utf-8'); + const { data, content: markdownContent } = matter(content); - const slug = data.slug || file.replace(/^\d{4}-\d{2}-\d{2}-/, '').replace(/\.(md|mdx)$/, ''); + let postContent = ''; + if (data.description) { + postContent = data.description; + } else { + postContent = stripMarkdown(markdownContent); + } - const routeBasePath = dir.replace('blog-', ''); + const truncated = postContent.length > 550 ? postContent.substring(0, 550) + '...' : postContent; - let url; - if (data.slug) { - url = `/${routeBasePath}/${data.slug}`; - } else { - url = `/${routeBasePath}/${yearStr}/${monthStr}/${dayStr}/${slug}`; - } + const slug = data.slug || file.replace(/^\d{4}-\d{2}-\d{2}-/, '').replace(/\.(md|mdx)$/, ''); - latestPost = { - date: date, - title: data.title || slug, - content: truncated, - url: url - }; - } - }); - }); + const routeBasePath = dir.replace('blog-', ''); + + let url; + if (data.slug) { + url = `/${routeBasePath}/${data.slug}`; + } else { + url = `/${routeBasePath}/${yearStr}/${monthStr}/${dayStr}/${slug}`; + } + + latestPost = { + date: date, + title: data.title || slug, + content: truncated, + url: url + }; + } return latestPost; }