-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle long sessions #87
Comments
This is very important to me because before my horrendous workaround we regularly broke checkout in the middle of people using it when we deployed. It was not pleasant and got loads of complaints. The way we do it now which is really, not fun at all, is:
It's crap and doesn't work if we deploy twice in quick succession as you have people still using the assets from the 1st deploy, when only the 2nd and 3rd deployment's files are present, but it's better than breaking people in the middle of purchasing every single deploy. I've read a bunch of stuff around solving this before my solution and there is some prior art from other frameworks/libraries:
Yeah, it's hard to think of a really good solution. |
I wonder if we could make any navigation be a server-side navigation instead of client-side navigation after you've had your page open for some configurable amount of time (e.g. > 24 hrs, if a new version of the app has been deployed, etc.). We're already talking about building a toggle between client-side and server-side navigation in #231 I think the best solution will probably depend on use case. We should make it possible that users can implement it how they like, but probably provide a good default option(s) |
Yeah, I like that idea, and I think it'd be fairly easy to establish a mechanism for knowing if a new version has been deployed (something as simple as a Perhaps if we exposed that mechanism via a store, we could make it easy for developers to show a toast: <script>
import Toast from '$components/Toast.svelte';
import { updated } = '$app/stores';
</script>
{#if $updated}
<Toast>
This version of the app is out of date — please
<button on:click={() => location.reload()}>reload</button>
to continue using it
</Toast>
{/if} |
For posterity, here was the corresponding Sapper issue: sveltejs/sapper#389 |
I could see users falling into various camps as to how to approach this issue. For us, we have an "your app is out of date" message. Which is great for "dashboard" type sites, but not so good for blogs etc. For Svelte, I've seen this handled with a I'd love to see this approach well documented in the My biggest concern with this issue isn't the the inner-workings, but rather the learning-curve. Most users will have to experience the issue before they start to look for a solution. For many it will be a heisenbug. I'm tempted to request that the default behaviour should be a little intrusive.
|
I've used a web-socket subscription (using Firebase RTDB) to a release version or timestamp to trigger the service-worker update check. That can then force a refresh or prompt the user, depending on the app itself and what they may be doing with it. Updates that don't require all the clients to update can use the regular service-worker check (when the app is restarted) and the release version or timestamp only updated when you need to force everyone to update to the latest ASAP. |
This problem exists for any web app that uses chunking with timestamps. For example, we have the same issue with Angular & Webpack. I haven't really solved it yet but I thought an elegant way of doing it would be a service worker that receive a list of chunks from the bundler and precaches them in background. This way the app is cached as one consistent build and continues working even if a new build has been uploaded. Just an idea. |
Would it help if the page is refreshed in the background? You could probably use the Page Visibility API to detect if a user is viewing the site. If not (e.g., they're on another tab) and there's a new version, force a reload. Then, the refresh is hidden to the user. https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API Don't think this will completely solve the issue (e.g., antony's checkout example above), but it should help limit the need for a "refresh the page" toast. |
I'm worried that a lot of suggestions in this thread presuppose an active server. I hope the use case of writing docs in SvelteKit, exporting the project to HTML, and throwing the result up on Surge/Netlify/etc won't get second class treatment. Simply reloading the page on navigation if the required files cannot be imported covers a lot of ground. The default code splitting is done on page boundaries, so this is when the error occurs most frequently. The different URL means we should be able to reload without impact; the only times this isn't true would also break if someone opened that link in a new tab. No polling or version numbers are required. The big cases where this approach fails:
|
The way I’ve usually handled this is to upload the pre-generated chunks to a separate static file service (usually S3). With filenames containing the MD5 of their contents, the chunks from multiple versions can coexist as long as needed, and older unchanged chunks can remain cached downstream. It’s slightly messy operationally, but for my purposes the simplicity and robustness is well worth it. Unfortunately, I’m not sure if this approach can be abstracted in a portable way. |
I think keeping old versions of chunks around is a working but highly inconvenient solution because this sort of compound versioning isn't natively available from (any that I know of) cloud providers. I think precaching chunks is the most elegant way. As long as they have the same or longer (than the html page itself) cache retention set, it will guarantee that full code tree is cached in the browser. If we know the chunk list from the bundler, we can inject |
Not seen mentioned here is making sure whatever solution for this works also for mobile progressive web apps. I've had trouble even intercepting errors and putting out a message that invokes window.location.reload(true). If browser reload is not working or the message says "reload the page" and they are in a PWA, it is confusing. With service workers and so on things get really difficult really quickly. See: https://deanhume.com/displaying-a-new-version-available-progressive-web-app/ |
For reference I was able to port my Sapper workaround into SvelteKit without much change (cf. sveltejs/sapper#389 (comment)). The idea remain to fetch every 10 seconds a static file The only change was to put the "scripts": {
"postinstall": "date '+%s%N' > static/_version"
} |
In Second-guessing the modern web, Tom MacWright makes several good points (I responded here).
The biggest, to me, is this one:
I wrote:
It would be great if there was some mechanism for solving (or at least alleviating) this problem. I think the 'include the site version in a cookie' approach is the most promising, but I haven't thought through any of the details.
The text was updated successfully, but these errors were encountered: