Files
homepage/src/lib/components/search.worker.js
T
Alexander 229d2fca33 implement Web Worker-based search to eliminate input lag
Replace synchronous DOM manipulation with Web Worker + Svelte reactive state for recipe search. This moves text normalization and filtering off the main thread, ensuring zero input lag while typing. Search now runs in parallel with UI rendering, improving performance significantly for 240+ recipes.

- Add search.worker.js for background search processing
- Update Search.svelte to use Web Worker with $state runes
- Update +page.svelte with reactive filtering based on worker results
- Add language-aware recipe data synchronization for proper English/German search
- Migrate to Svelte 5 event handlers (onsubmit, onclick)
2025-12-31 14:09:22 +01:00

61 lines
1.6 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Web Worker for recipe search
* Handles text normalization and filtering off the main thread
*/
let recipes = [];
self.onmessage = (e) => {
const { type, data } = e.data;
if (type === 'init') {
// Initialize worker with recipe data
recipes = data.recipes || [];
self.postMessage({ type: 'ready' });
}
if (type === 'search') {
const query = data.query;
// Empty query = show all recipes
if (!query || query.trim().length === 0) {
self.postMessage({
type: 'results',
matchedIds: recipes.map(r => r._id),
matchedCategories: new Set(recipes.map(r => r.category))
});
return;
}
// Normalize and split search query
const searchText = query.toLowerCase().trim()
.normalize('NFD')
.replace(/\p{Diacritic}/gu, "");
const searchTerms = searchText.split(" ").filter(term => term.length > 0);
// Filter recipes
const matched = recipes.filter(recipe => {
// Build searchable string from recipe data
const searchString = [
recipe.name || '',
recipe.description || '',
...(recipe.tags || [])
].join(' ')
.toLowerCase()
.normalize('NFD')
.replace(/\p{Diacritic}/gu, "")
.replace(/­|­/g, ''); // Remove soft hyphens
// All search terms must match
return searchTerms.every(term => searchString.includes(term));
});
// Return matched recipe IDs and categories with results
self.postMessage({
type: 'results',
matchedIds: matched.map(r => r._id),
matchedCategories: new Set(matched.map(r => r.category))
});
}
};