Unpoly keeps your application usable as the user's connection becomes flaky or goes away entirely. A failed request never replaces your page with the browser's error screen. Instead you decide what happens: show a message, offer a retry, or serve pages the user has already visited from the cache.
When the server does respond, but with an error code, see Handling error responses.
In a vanilla HTML document, clicking a link while offline will replace your app with a standard error screen, no questions asked:
Chrome's "No internet" page, with suggestions to check the network cables and reconnect to Wi-Fi,
and the error code ERR_INTERNET_DISCONNECTED.
Interacting with an Unpoly-enhanced link or form while offline will not change the page.
Instead Unpoly emits an up:fragment:offline event and lets you decide how to handle the connection loss.
Without a listener, the page stays as it is and the user gets no feedback, so most apps
should register one.
A global listener can offer to retry the failed update by calling event.retry():
up.on('up:fragment:offline', function(event) {
if (confirm('You are offline. Retry?')) event.retry() // mark: event.retry()
})
To handle connection loss for a single link or form, pass an { onOffline } option
to the rendering function. The callback receives the same event:
up.follow(link, {
onOffline(event) {
if (confirm('You are offline. Retry?')) event.retry()
}
})
In HTML, set an [up-on-offline] attribute with a JavaScript snippet:
<a href="/bids" up-follow up-on-offline="alert('You are offline. Please try again later.')"> <!-- mark: up-on-offline -->
Post bid
</a>
Instead of retrying, the listener may also render something else, like an offline notice:
up.on('up:fragment:offline', function(event) {
up.render(event.renderOptions.target, { content: "You are offline." })
})
Requests made with up.request() are not rendered, so they emit no up:fragment:offline event.
Their promise rejects with an up.Offline error, and an up:request:offline event is emitted.
Even without a connection, cached content remains navigable for 90 minutes. This means that an offline user can instantly access pages that they already visited this session.
While offline, cache revalidation of expired content will fail.
When revalidation fails, or when accessing uncached content, Unpoly runs onOffline() callbacks and emits up:fragment:offline.
The page will not be changed unless your code says so.
You can use an [up-preload="insert"] attribute
to eagerly preload links as soon as they are inserted into the DOM. This way they remain navigable while offline:
<a href="/menu" up-layer="new drawer" up-preload="insert">≡ Menu</a> <!-- mark: up-preload="insert" -->
While Unpoly lets you handle disconnects, some parts are missing for full "offline" support:
For a comprehensive offline experience (cold start) we recommend a service worker.
Often the device reports a connection, but we're effectively offline:
Unpoly handles flaky connections with timeouts. A request that times out also runs onOffline() callbacks and emits up:fragment:offline.
This means that your disconnect handling covers flaky connections as well.
All requests have a default timeout of 90 seconds.
You may use different timeouts for individual requests by passing a { timeout } option
or by setting an [up-timeout] attribute:
<a href="/report" up-follow up-timeout="10000">Generate report</a> <!-- mark: up-timeout="10000" -->
Even with a good connection, your server may take long to render an expensive page. This is what happens while the user waits:
up:network:late
and shows the progress bar.up:request:loaded. For a request that renders a fragment,
up:fragment:loaded follows, and the response is processed like any other.up:request:offline
and up:fragment:offline, as it would for a disconnect.
Since no response arrived, up:fragment:loaded is not emitted.Once no slow requests are left, Unpoly emits up:network:recover and hides the progress bar.
While the user waits, you can also show loading state within the targeted fragment.
Tip Your coding agent can search these docs locally with the Unpoly agent skill