impierce / identity-wallet

A Tauri-based Identity Wallet for people to manage Decentralized Identities and Verifiable Credentials.
https://www.impierce.com
Apache License 2.0
17 stars 4 forks source link

[Bug] Blank screen in dev #188

Closed maiertech closed 2 months ago

maiertech commented 2 months ago

Description

This bug happens when running UniMe in dev as desktop app when navigating in the credentials of the Ferris profile. Occasionally, I see a blank screen after some interactions.

Hardware Specification

Operating system: macOS RAM: Cores: Device:

Steps to Reproduce the Bug

It's not reliably reproducible but it happens regularly.

Expected Behaviour

There should not be any blank screens.

Actual Behaviour

To continue with dev, I can right-click and choose reload. It may take several reload attempts until the blank screen goes away. Occasionally, I need to restart the dev server.

Errors

Vite CSS nesting error:

[vite:css] Nested CSS was detected, but CSS nesting has not been configured correctly.
Please enable a CSS nesting plugin *before* Tailwind in your configuration.
See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting
3  |      flex: 1;
4  |  
5  |      &:focus {
   |       ^
6  |        position: relative;
7  |      }
[vite:css] Nested CSS was detected, but CSS nesting has not been configured correctly.
Please enable a CSS nesting plugin *before* Tailwind in your configuration.
See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting
1  |  .trigger.s-W5HspqYnXoFG{flex:1;&:focus {
   |                                  ^
2  |        position: relative;
3  |      };&:focus-visible {

Vite dependency optimization error:

5:09:56 PM [vite] ✨ new dependencies optimized: @lottiefiles/lottie-player, tailwind-merge, @tauri-apps/api/path, @tauri-apps/plugin-fs
5:09:56 PM [vite] ✨ optimized dependencies changed. reloading
maiertech commented 2 months ago

Prior PRs:

maiertech commented 2 months ago

Above Tailwind CSS nesting config warning is separate from the blank screen issue. The warning can be fixed by adding

 'tailwindcss/nesting': {},

as first entry to postcss.config.js. But this does not make the blank screen go away.

maiertech commented 2 months ago

The blank screen is caused by an undefined state after Vite lazily (and somewhat randomly) optimizes dependencies, triggering a page reload. You can replicate this manually: right click → reload. But be aware that when you manually reload the app it is expected behavior that you will lose your app state. And you should not expect an app to recover gracefully when it loses its state.

You can trigger Vite dependency optimizations by removing the node_modules folder and running npm i. There is a high chance that Vite will optimize a dependency the next time you run the app and trigger a page reload.

For a page reload, the expected behavior is that the browser renders the app from scratch (from cache). But it looks like Vite can intercept the reload because the component tree does not get unmounted, and onMount lifecycle methods do not to run. But the state, including the store, is lost.

Subsequently, Vite seems to try to use HMR to recover the page. However, because of the undefined app state, this fails with this error:

"Unrecoverable HMR error in <+page>: next update will trigger a full reload"

The action [App] Get state to send the backend state to the frontend is dispatched in the root layout's onMount. However, onMount does not run on a page reload in this case. That's why the state is undefined the reload erased it. One idea to resolve this issue is to dispatch the [App] Get state action when the state is undefined. We could, e.g., subscribe to the state in the root layout and dispatch the action when the state is undefined. But there is no guarantee that the state updates fast enough before we get the unrecoverable HMR error. This solution would rely on SvelteKit internals that we do not understand.

Another approach could be to type the state as AppState | undefined when defining the store. Currently, the state is typed as AppState. Under normal circumstances, the state, which we get from the backend, cannot be undefined. But then in this case it is undefined. Since all components are written under the assumption that the state is never undefined typing the state as AppState | undefined would require a major refactoring.

Yet another approach is to initialize the store with a valid empty state instead of undefined. Since this empty state is valid, the app should be able to handle this state without throwing any errors. The downside of this approach is that whenever the backend state changes, you have to update the empty state used to initialize the store. This would avoid a blank screen often, but not always. E.g. if you happen to be on a credential page when Vite triggers a reload, you would still see a blank page. This is because the parametrized rout is unable to find data to render in the empty state.

Finally, we could ask Vite to optimize certain dependencies in advance to avoid deferred dependency optimizations. Vite normally optimized dependencies it did not find during an initial crawl. But for most of the dependencies it optimizes lazily, it's not obvious why it could not find them. If we add a list of dependencies for Vite to optimize in advance, the question is whether the list is complete enough to make the blank page problem go away.

And finally finally, maybe this issue will go away with Vite 5 after updating SvelteKit to v2 in #194.