RxJS operator and other utils catching offline errors in Angular apps and PWA.
You know the Angular async
pipe, right? Amazing tool, but there is one big issue with it:by letting Angular automatically subscribing and unsubscribing your Observable
or Promise
, you can't handle the error callback.
Problem is: in a web app, especially in a Progressive Web App (PWA),a lot of your Observable
or Promise
are about HTTP requests,and they will inevitably fail when the user is offline (or the server is inaccessible).
So if you want to get the benefice of the async
pipe without breaking your app, you need to catch offline errors on every page. Painful.
So here it is: a RxJS operator catching offline errors for you, so you can use the async
pipe everywhere!
There are also other tools for offline management, like online status helpers and guards.
Install with npm or another package manager:
# Angular 12
npm install @ngx-pwa/offline@12
# Angular 11
npm install @ngx-pwa/offline@11
# Angular 10
npm install @ngx-pwa/offline@10
Then you just have to inject the Network
service at least once, for example in AppComponent
:
import { Network } from '@ngx-pwa/offline';
@Component()
export class AppComponent {
constructor(protected network: Network) {}
}
Note: you may not use the service itself and just the RxJS operator, but an injection is required in all cases to setup the service.
Just use the catchOffline
RxJS operator:
import { catchOffline } from '@ngx-pwa/offline';
@Component({
selector: 'some-page',
template: `
<presentation-component [data]="data$ | async"></presentation-component>
`
})
export class SomePageComponent implements OnInit {
data$: Observable<Data>;
constructor(protected someService: SomeService) {}
ngOnInit() {
this.data$ = this.someService.getData().pipe(catchOffline());
}
}
As it may cause a redirection, your app must use Angular router (RouterModule.forRoot()
).
By default, catchOffline
will redirect to:
/offline
if the user is offline (no Internet connection),/unavailable
if the service is inaccessible (5xx HTTP errors).Note: creating the corresponding routes and components in your app is up to you,as the lib can't decide the content and design of these pages for you.
If you want to change the redirection URLs:
import { OfflineModule } from '@ngx-pwa/offline';
@NgModule({
imports: [
OfflineModule.forRoot({
routeOffline: '/oops/offline',
routeUnavailable: '/oops/unavailable',
})
]
})
export class AppModule {}
Note: you need to provide the full URL, so the leading /
is required.
To check online status at some point:
import { Network } from '@ngx-pwa/offline';
@Component({
template: `
<online-component *ngIf="online"></online-component>
<offline-component *ngIf="!online"></offline-component>
`
})
export class SomePageComponent implements OnInit {
online = this.network.online;
constructor(protected network: Network) {}
}
To observe when online status changes:
import { Network } from '@ngx-pwa/offline';
@Component({
template: `
<online-component *ngIf="online$ | async; else offline"></online-component>
<ng-template #offline>
<offline-component></offline-component>
</ng-template>
`
})
export class SomePageComponent implements OnInit {
online$ = this.network.onlineChanges;
constructor(protected network: Network) {}
}
Notes:
async
pipe twice on the same Observable
. The example above shows you how to manage those situations in the proper way,Observable
does not auto-complete. Then you should either use the async
pipe as above for automatic unsubscription, either you should unsubscribe manually (in ngOnDestroy
method in most cases),Guards catching offline errors are also available, for CanActivate
, CanActivateChild
and CanLoad
. For example:
import { OnlineGuard } from '@ngx-pwa/offline';
const routes: Routes = [
{ path: 'some-page', component: SomePageComponent, canActivate: [OnlineGuard] }
];
By default, guards will redirect to the /offline
page (so your app must use Angular router: RouterModule.forRoot()
).If you just want to block the navigation:
import { OfflineModule } from '@ngx-pwa/offline';
@NgModule({
imports: [
OfflineModule.forRoot({ guardsRedirect: false })
]
})
export class AppModule {}
This lib supports the last stable version of Angular.
This module supports AoT pre-compiling and Ivy.
This module supports Universal server-side rendering.
MIT
Progressive Web App A production grade progressive web app, to hit the ground running. Setup $ npm install ENV Variables NODE_ENV (build-dependent) development: modules are bundled as is production: m
该插件利用 Workbox 为网站添加对 PWA 的支持。该插件仅在针对生产环境构建时生成 Service Worker,并允许你创建一个 完全兼容 PWA 的文档站点,以提供对离线和安装到浏览器的支持。 安装 npm Yarn npm install --save @docusaurus/plugin-pwa yarn add @docusaurus/plugin-pwa 配置 在 ./
什么是PWA PWA是Progressive Web App的英文缩写, 翻译过来就是渐进式增强WEB应用, 是Google 在2016年提出的概念,2017年落地的web技术。目的就是在移动端利用提供的标准化框架,在网页应用中实现和原生应用相近的用户体验的渐进式网页应用。 可靠——即时加载,即使在不确定的网络条件下也不会受到影响。 当用户从主屏幕启动时,service work可以立即加载渐进式
Jekyll PWA Plugin PWA support for Jekyll This plugin provides PWA support for Jekyll. Generate a service worker and provides precache and runtime cache with Google Workbox. Google Workbox has already
什么是 PWA PWA (Progressive Web Apps) 是一种 Web App 新模型,并不是具体指某一种前沿的技术或者某一个单一的知识点,我们从英文缩写来看就能看出来,这是一个渐进式的 Web App,是通过一系列新的 Web 特性,配合优秀的 UI 交互设计,逐步的增强 Web App 的用户体验。 用户的手机现在几乎被各种大大小小形形色色的 App 给攻占了,手机的容量是有上限
Progressive Web App, 简称 PWA,是提升 Web App 的体验的一种新方法,能给用户原生应用的体验。