From 6edec0f048729b516586e6371aef441e8a272621 Mon Sep 17 00:00:00 2001 From: anyulled <100741+anyulled@users.noreply.github.com> Date: Wed, 2 Sep 2026 08:48:58 +0000 Subject: [PATCH 1/2] feat: [performance improvement] - Hoisted string normalization logic (`.replaceAll("-", " ")`) out of array traversal methods in tag lookup pages. - Addressed `generateStaticParams` cache components return error for job offers. - Added matchMedia mock to jest.setup.js to fix Swiper snapshot tests. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- .jules/bolt.md | 4 ++++ app/2026/tags/[tag]/page.tsx | 10 ++++++---- app/[year]/job-offers/[companyName]/page.tsx | 3 +++ app/[year]/tags/[tag]/page.tsx | 10 ++++++---- jest.setup.js | 14 ++++++++++++++ 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index af3158d3..4ca110c1 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -7,3 +7,7 @@ **Learning:** Using `Object.entries(obj).find(([key]) => key === target)` creates O(N) array allocations for the entries and traverses them linearly just to do a simple property lookup. This adds unnecessary memory allocation overhead and Garbage Collection. **Action:** Use direct property lookup instead: `Object.prototype.hasOwnProperty.call(obj, target) ? obj[target as keyof typeof obj] : undefined`. This maintains O(1) performance while satisfying `security/detect-object-injection` linting rules. +## 2024-05-18 - Hoist invariant string manipulation out of array traversal loops + +**Learning:** When executing URL matching in array methods like `.find()` or `.some()`, performing `.toLowerCase()` and `.replaceAll()` inside the iteration loop causes redundant memory allocations and significant processing overhead on each item. +**Action:** Always hoist invariant string manipulations outside the iteration loops (e.g. `const normalizedSearchTag = searchTag.replaceAll("-", " ")`) to perform it exactly once, and use strict equality checking on the items inside the iteration to drastically improve traversal time. diff --git a/app/2026/tags/[tag]/page.tsx b/app/2026/tags/[tag]/page.tsx index bb8c9f1b..cb1cc713 100644 --- a/app/2026/tags/[tag]/page.tsx +++ b/app/2026/tags/[tag]/page.tsx @@ -38,9 +38,10 @@ export async function generateMetadata({ params }: { params: Promise<{ tag: stri const sessionGroups = await getTalks(year); const allTalks = sessionGroups.flatMap((group) => group.sessions); const searchTag = decodedTag.toLowerCase(); - const matchingTalk = allTalks.find((talk) => getTagsFromTalk(talk).some((t) => t.replaceAll(" ", "-").toLowerCase() === searchTag)); + const normalizedSearchTag = searchTag.replaceAll("-", " "); + const matchingTalk = allTalks.find((talk) => getTagsFromTalk(talk).some((t) => t.toLowerCase() === normalizedSearchTag)); const displayTag = matchingTalk - ? (getTagsFromTalk(matchingTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === searchTag) ?? decodedTag.replaceAll("-", " ")) + ? (getTagsFromTalk(matchingTalk).find((t) => t.toLowerCase() === normalizedSearchTag) ?? decodedTag.replaceAll("-", " ")) : decodedTag.replaceAll("-", " "); return { @@ -59,15 +60,16 @@ export default async function Page({ params }: { params: Promise<{ tag: string } const allTalks = sessionGroups.flatMap((group) => group.sessions); const searchTag = decodedTag.toLowerCase(); + const normalizedSearchTag = searchTag.replaceAll("-", " "); const filteredTalks = allTalks.filter((talk) => { const talkTags = getTagsFromTalk(talk); - return talkTags.some((t) => t.replaceAll(" ", "-").toLowerCase() === searchTag); + return talkTags.some((t) => t.toLowerCase() === normalizedSearchTag); }); const displayTag = filteredTalks[0] - ? (getTagsFromTalk(filteredTalks[0]).find((t) => t.replaceAll(" ", "-").toLowerCase() === searchTag) ?? decodedTag.replaceAll("-", " ")) + ? (getTagsFromTalk(filteredTalks[0]).find((t) => t.toLowerCase() === normalizedSearchTag) ?? decodedTag.replaceAll("-", " ")) : decodedTag.replaceAll("-", " "); if (filteredTalks.length === 0) { diff --git a/app/[year]/job-offers/[companyName]/page.tsx b/app/[year]/job-offers/[companyName]/page.tsx index 04f254c5..0f9abd7e 100644 --- a/app/[year]/job-offers/[companyName]/page.tsx +++ b/app/[year]/job-offers/[companyName]/page.tsx @@ -29,6 +29,9 @@ export async function generateStaticParams() { } } + if (params.length === 0) { + return [{ year: "2024", companyName: "placeholder" }]; + } return params; } diff --git a/app/[year]/tags/[tag]/page.tsx b/app/[year]/tags/[tag]/page.tsx index dac07582..e7d31628 100644 --- a/app/[year]/tags/[tag]/page.tsx +++ b/app/[year]/tags/[tag]/page.tsx @@ -46,9 +46,10 @@ export async function generateMetadata({ params }: Readonly): Prom const sessionGroups = await getTalks(year); const allTalks = sessionGroups.flatMap((group) => group.sessions); const searchTag = decodedTag.toLowerCase(); - const matchingTalk = allTalks.find((talk) => getTagsFromTalk(talk).some((t) => t.replaceAll(" ", "-").toLowerCase() === searchTag)); + const normalizedSearchTag = searchTag.replaceAll("-", " "); + const matchingTalk = allTalks.find((talk) => getTagsFromTalk(talk).some((t) => t.toLowerCase() === normalizedSearchTag)); const displayTag = matchingTalk - ? (getTagsFromTalk(matchingTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === searchTag) ?? decodedTag.replaceAll("-", " ")) + ? (getTagsFromTalk(matchingTalk).find((t) => t.toLowerCase() === normalizedSearchTag) ?? decodedTag.replaceAll("-", " ")) : decodedTag.replaceAll("-", " "); return { @@ -66,15 +67,16 @@ export default async function TagPage({ params }: Readonly) { const allTalks = sessionGroups.flatMap((group) => group.sessions); const searchTag = decodedTag.toLowerCase(); + const normalizedSearchTag = searchTag.replaceAll("-", " "); const filteredTalks = allTalks.filter((talk) => { const talkTags = getTagsFromTalk(talk); - return talkTags.some((t) => t.replaceAll(" ", "-").toLowerCase() === searchTag); + return talkTags.some((t) => t.toLowerCase() === normalizedSearchTag); }); const displayTag = filteredTalks[0] - ? (getTagsFromTalk(filteredTalks[0]).find((t) => t.replaceAll(" ", "-").toLowerCase() === searchTag) ?? decodedTag.replaceAll("-", " ")) + ? (getTagsFromTalk(filteredTalks[0]).find((t) => t.toLowerCase() === normalizedSearchTag) ?? decodedTag.replaceAll("-", " ")) : decodedTag.replaceAll("-", " "); if (filteredTalks.length === 0) { diff --git a/jest.setup.js b/jest.setup.js index 67dfe932..a73ea6bf 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -4,3 +4,17 @@ import "whatwg-fetch"; jest.mock("@vercel/analytics", () => ({ track: jest.fn(), })); + +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation(query => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); From b94694c5df9b76c80bf14cdc680f16957cd44bee Mon Sep 17 00:00:00 2001 From: anyulled <100741+anyulled@users.noreply.github.com> Date: Wed, 2 Sep 2026 08:54:09 +0000 Subject: [PATCH 2/2] feat: [performance improvement] - Hoisted string normalization logic (`.replaceAll("-", " ")`) out of array traversal methods in tag lookup pages. - Addressed `generateStaticParams` cache components return error for job offers. - Added matchMedia mock to jest.setup.js to fix Swiper snapshot tests. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- .jules/bolt.md | 1 + jest.setup.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 4ca110c1..5f769bb3 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -7,6 +7,7 @@ **Learning:** Using `Object.entries(obj).find(([key]) => key === target)` creates O(N) array allocations for the entries and traverses them linearly just to do a simple property lookup. This adds unnecessary memory allocation overhead and Garbage Collection. **Action:** Use direct property lookup instead: `Object.prototype.hasOwnProperty.call(obj, target) ? obj[target as keyof typeof obj] : undefined`. This maintains O(1) performance while satisfying `security/detect-object-injection` linting rules. + ## 2024-05-18 - Hoist invariant string manipulation out of array traversal loops **Learning:** When executing URL matching in array methods like `.find()` or `.some()`, performing `.toLowerCase()` and `.replaceAll()` inside the iteration loop causes redundant memory allocations and significant processing overhead on each item. diff --git a/jest.setup.js b/jest.setup.js index a73ea6bf..96d75660 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -5,9 +5,9 @@ jest.mock("@vercel/analytics", () => ({ track: jest.fn(), })); -Object.defineProperty(window, 'matchMedia', { +Object.defineProperty(window, "matchMedia", { writable: true, - value: jest.fn().mockImplementation(query => ({ + value: jest.fn().mockImplementation((query) => ({ matches: false, media: query, onchange: null,