CloudCannon / pagefind

Static low-bandwidth search at scale
https://pagefind.app
MIT License
3.22k stars 97 forks source link

[Question] Pagefind language detection at page init may be stale #596

Closed gustaveWPM closed 2 months ago

gustaveWPM commented 2 months ago

Hello,

The documentation of Pagefind says:

When Pagefind initializes in the browser it will check the same lang attribute and load the appropriate index.

https://pagefind.app/docs/multilingual/

But what happens if I have something like an i18n lib with reactive hooks, whether in React, VueJS, whatever? :/ It may change the html lang attribute without a page reload.

What should I do to ensure this lang attribute detection is never stale?

bglw commented 2 months ago

In cases where you've changed the language, you'll need to reinitialize Pagefind. You can see a similar tip for how to do that here: https://github.com/CloudCannon/pagefind/issues/593#issuecomment-2046188207

As long as the lang attribute is set on the html document, then re-initializing will pull the new language and load the new indexes.

gustaveWPM commented 2 months ago

In cases where you've changed the language, you'll need to reinitialize Pagefind. You can see a similar tip for how to do that here: #593 (comment)

As long as the lang attribute is set on the html document, then re-initializing will pull the new language and load the new indexes.

Wow, thank you! Will give it a look to this.

I think it would be a good idea to document this on the same page, to show an example of which "Standard" way we should use Pagefind in this context. ^^'

gustaveWPM commented 2 months ago

Oh, well, I'm not using the PagefindUI. https://github.com/Tirraa/dashboard_rtm/blob/main/src/components/hooks/usePagefind.ts

( Btw, got a lot of inspiration from: https://www.petemillspaugh.com/nextjs-search-with-pagefind )


EDIT:

Tried

        // @ts-ignore generated after build
        const freshPagefind = await import(/* webpackIgnore: true */ '/pagefind/pagefind.js');
        window.pagefind = undefined;
        window.pagefind = freshPagefind;

And also

        // @ts-ignore generated after build
        const freshPagefind = await import(/* webpackIgnore: true */ '/pagefind/pagefind.js');
        await freshPagefind.init(currentLocale);
        window.pagefind = undefined;
        window.pagefind = freshPagefind;

But the index is still stale.

EDIT2: Oh, okay. Will try this.

https://pagefind.app/docs/api/#re-initializing-the-search-api

gustaveWPM commented 2 months ago

Update: okay, I'm dumb. This seems to work properly.

function usePagefind(currentLocale: LanguageFlag) {
  useEffect(() => {
    async function loadPagefind() {
      try {
        // @ts-ignore generated after build
        const freshPagefind = await import(/* webpackIgnore: true */ '/pagefind/pagefind.js');
        window.pagefind = freshPagefind;
        await window.pagefind.destroy();
        await window.pagefind.init();
      } catch (error) {
        console.warn('Pagefind failed to load, search will not work');
        window.pagefind = { debouncedSearch: () => ({ results: [] }), search: () => ({ results: [] }), destroy: () => {}, init: () => {} };
      }
    }
    loadPagefind();
  }, [currentLocale]);
}

Am I doing something wrong here?


EDIT:

function usePagefind(currentLocale: LanguageFlag) {
  useEffect(() => {
    async function bootOrRebootPagefind() {
      async function bootPagefind() {
        // @ts-ignore generated after build
        const pagefindInstance = await import(/* webpackIgnore: true */ '/pagefind/pagefind.js');
        window.pagefind = pagefindInstance;
      }

      async function rebootPagefind() {
        await window.pagefind.destroy();
        await window.pagefind.init();
      }

      try {
        if (typeof window.pagefind !== 'undefined') {
          try {
            await rebootPagefind();
            return;
          } catch {
            await bootPagefind();
          }
        }
        await bootPagefind();
      } catch (error) {
        console.warn('Pagefind failed to load, search will not work');
        window.pagefind = { debouncedSearch: () => ({ results: [] }), search: () => ({ results: [] }) };
      }
    }
    bootOrRebootPagefind();
  }, [currentLocale]);
}
bglw commented 2 months ago

Re-initializing should work fine — and you shouldn't need to import a freshPagefind again.

The browser will actually de-dupe that for you, so doing another await import will return the exact same instance, which is why you previous example would have shown no change.

In this case, if you have an existing window.pagefind, you can just do

await window.pagefind.destroy();
await window.pagefind.init();

Without importing or reassigning anything

gustaveWPM commented 2 months ago

Re-initializing should work fine — and you shouldn't need to import a freshPagefind again.

The browser will actually de-dupe that for you, so doing another await import will return the exact same instance, which is why you previous example would have shown no change.

In this case, if you have an existing window.pagefind, you can just do

await window.pagefind.destroy();
await window.pagefind.init();

Without importing or reassigning anything

Yep, it likely hits the cache. I was just wondering if there were any on-load tricky side-effects. Thank you for your help!

gustaveWPM commented 2 months ago

It seems to be good for me now. Should we close this issue, or should I rename it according to some potential documentation updates? @bglw

bglw commented 2 months ago

I'll close this out and keep any documentation changes in mind when I'm next changing those files 🙂