mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-15 06:35:20 -07:00
fix(search): prevent pagefind filter hangs
Resolve the Pagefind browser loader in Vite dev and cap filter-only result hydration so broad filters render promptly instead of stalling behind thousands of fragment fetches.
This commit is contained in:
parent
e1da6eb880
commit
a1ae595717
2 changed files with 85 additions and 2 deletions
|
|
@ -366,6 +366,9 @@ export default {
|
|||
...this.filterQueryList
|
||||
].filter( Boolean ).join(' ')
|
||||
},
|
||||
pagefindResultLimit () {
|
||||
return Math.max( this.initialList.length, 25 )
|
||||
},
|
||||
pagefindFilters () {
|
||||
const filters = new SearchFilters()
|
||||
filters.setFromStringArray( this.filterQueryList )
|
||||
|
|
@ -518,10 +521,20 @@ export default {
|
|||
return null
|
||||
}
|
||||
|
||||
const resultData = await Promise.all( ( pagefindQuery.results || [] ).map( async result => {
|
||||
const limitedResults = ( pagefindQuery.results || [] ).slice( 0, this.pagefindResultLimit )
|
||||
const settledResultData = await Promise.allSettled( limitedResults.map( async result => {
|
||||
return await result.data()
|
||||
} ) )
|
||||
|
||||
const resultData = settledResultData.flatMap( settledResult => {
|
||||
if ( settledResult.status === 'fulfilled' ) {
|
||||
return [ settledResult.value ]
|
||||
}
|
||||
|
||||
console.warn('Failed to load Pagefind result data', settledResult.reason)
|
||||
return []
|
||||
} )
|
||||
|
||||
return resultData.map( data => {
|
||||
return mapPagefindDataToListing( data, {
|
||||
highlightTerms: this.inputTerms
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ import {
|
|||
pagefindScriptURL
|
||||
} from '~/helpers/pagefind/config.js'
|
||||
|
||||
const pagefindGlobalKey = '__doesItArmPagefind'
|
||||
const pagefindLoaderPromiseKey = '__doesItArmPagefindLoaderPromise'
|
||||
const pagefindLoaderTimeoutMs = 10 * 1000
|
||||
|
||||
function escapeHtml ( text = '' ) {
|
||||
return text
|
||||
.replaceAll('&', '&')
|
||||
|
|
@ -70,6 +74,72 @@ export function mapPagefindDataToListing ( resultData, {
|
|||
}
|
||||
}
|
||||
|
||||
function getPagefindModuleSource () {
|
||||
return [
|
||||
`import * as pagefindModule from ${ JSON.stringify( pagefindScriptURL ) }`,
|
||||
`globalThis.${ pagefindGlobalKey } = pagefindModule.default || pagefindModule`
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
function waitForPagefindGlobal () {
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
if ( globalThis[ pagefindGlobalKey ] ) {
|
||||
resolve( globalThis[ pagefindGlobalKey ] )
|
||||
return
|
||||
}
|
||||
|
||||
const startedAt = Date.now()
|
||||
const timer = setInterval( () => {
|
||||
if ( globalThis[ pagefindGlobalKey ] ) {
|
||||
clearInterval( timer )
|
||||
resolve( globalThis[ pagefindGlobalKey ] )
|
||||
return
|
||||
}
|
||||
|
||||
if ( Date.now() - startedAt >= pagefindLoaderTimeoutMs ) {
|
||||
clearInterval( timer )
|
||||
reject( new Error(`Timed out waiting for Pagefind browser module at ${ pagefindScriptURL }`) )
|
||||
}
|
||||
}, 20 )
|
||||
} )
|
||||
}
|
||||
|
||||
async function loadPagefindBrowserModule () {
|
||||
if ( typeof document === 'undefined' ) {
|
||||
throw new Error('PagefindClient can only load in a browser document')
|
||||
}
|
||||
|
||||
if ( globalThis[ pagefindGlobalKey ] ) {
|
||||
return globalThis[ pagefindGlobalKey ]
|
||||
}
|
||||
|
||||
if ( !globalThis[ pagefindLoaderPromiseKey ] ) {
|
||||
globalThis[ pagefindLoaderPromiseKey ] = new Promise( async ( resolve, reject ) => {
|
||||
const script = document.createElement('script')
|
||||
|
||||
script.async = true
|
||||
script.type = 'module'
|
||||
script.textContent = getPagefindModuleSource()
|
||||
|
||||
script.onerror = () => {
|
||||
delete globalThis[ pagefindLoaderPromiseKey ]
|
||||
reject( new Error(`Failed to load Pagefind browser module from ${ pagefindScriptURL }`) )
|
||||
}
|
||||
|
||||
document.head.append( script )
|
||||
|
||||
try {
|
||||
resolve( await waitForPagefindGlobal() )
|
||||
} catch ( err ) {
|
||||
delete globalThis[ pagefindLoaderPromiseKey ]
|
||||
reject( err )
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
||||
return await globalThis[ pagefindLoaderPromiseKey ]
|
||||
}
|
||||
|
||||
export class PagefindClient {
|
||||
constructor ( options = {} ) {
|
||||
this.bundlePath = options.bundlePath || pagefindBundleRelativeURL
|
||||
|
|
@ -100,7 +170,7 @@ export class PagefindClient {
|
|||
async loadPagefindScript () {
|
||||
if ( this.pagefind ) return
|
||||
|
||||
const pagefindModule = await import(/* @vite-ignore */ pagefindScriptURL)
|
||||
const pagefindModule = await loadPagefindBrowserModule()
|
||||
this.pagefind = pagefindModule.default || pagefindModule
|
||||
|
||||
this.pagefind.options({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue