亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Angular PWA 更新太慢

Angular PWA 更新太慢

翻過高山走不出你 2022-06-16 10:09:10
我有一個 Angular 8 PWA 應用程序正在生產中。我會定期進行大量更新,因此我需要找到一種方法讓用戶在打開應用程序時獲取這些更新。如果沒有特殊操作,應用程序將不會更新。如果您在瀏覽器上打開該應用程序,它將顯示您上次打開該應用程序時的版本,即使我已將新捆綁包推送到生產環境。這似乎是 PWA 功能的不幸結果。我正在使用 AWS Amplify 進行托管。為了解決這個問題(我在這里問了一個問題),我嘗試使用 swUpdate。問題是它工作得太慢了。如果有更新,它將重新加載瀏覽器——但這需要一段時間。用戶打開應用程序后通常需要幾秒鐘才能重新加載。因此,您打開應用程序,4 到 6 秒后應用程序重新加載新版本。有沒有辦法讓 swUpdate 更快?或者另一種加載新應用版本的方法?這是我的代碼,我認為這是一個簡單的實現:app.component.ts:import { Component } from '@angular/core';import { SwUpdate } from '@angular/service-worker';@Component({  selector: 'app-root',  templateUrl: './app.component.html',  styleUrls: ['./app.component.scss']})export class AppComponent {   constructor(private swUpdate: SwUpdate) {   title = 'Great App'   swUpdate.available.subscribe(event => {        swUpdate.activateUpdate().then(() => {            window.location.reload();            console.log('there is an Update! Reloading now.')      });    })   if (!this.swUpdate.isEnabled) {      console.log('Not going to update');    } }但這并不能很好地工作,因為重新加載通常會在用戶進入應用程序后幾秒鐘發生(即使在良好的互聯網連接情況下)。我知道我也可以向人們顯示一條消息,說“想用新版本刷新嗎?” 但這并不能解決當前 swUpdate 工作速度有多慢的根本問題。
查看完整描述

3 回答

?
回首憶惘然

TA貢獻1847條經驗 獲得超11個贊

對于仍然遇到此問題的任何人,這是我為減少延遲所做的事情:

  • 在 APP_INITIALIZER 而不是 AppComponent 中檢查更新,以便更早完成檢查

  • 使用checkForUpdate方法

在你app.module.ts添加一個初始化函數:

{ provide: APP_INITIALIZER, useFactory: checkForUpdates, multi: true, deps: [SwUpdate /* Add whatever dependency is required here */] },

該函數應如下所示:

export const checkForUpdates = (swUpdate: SwUpdate): (() => Promise<any>) => {

  return (): Promise<void> =>

    new Promise((resolve) => {

      swUpdate.checkForUpdate();

      

      swUpdate.available.subscribe(() => {

          window.location.reload();

      });


      resolve();

    });

};

我不確定是否需要 APP_INITIALIZER 和 checkForUpdate,但這樣我將延遲減少到 1-2 秒(而不是 5-10 秒甚至更多)


查看完整回答
反對 回復 2022-06-16
?
白豬掌柜的

TA貢獻1893條經驗 獲得超10個贊

我使用 Carrm 和 NeNad 的兩個答案在我的 Angular 應用程序中創建一個頁面來管理更新。


我還使用@saithodev/ts-appversion包來管理版本。


稍后,我創建了一個腳本來更新每個構建的應用程序版本并將其顯示在該頁面上 (appversionupdate.mjs)。


然后,在 package.json 中,我將腳本設置為與 npm run 一起使用。


這樣,當我構建和部署項目時,版本會根據需要進行更新。


我知道 OP 并沒有要求所有這些,但它可能對社區有用。


menu.component.html


<mat-toolbar color="accent" fxLayout="row" fxLayoutAlign="space-between center" class="top-bar">

    <div fxLayout="row" fxLayoutAlign="start center">

        <h1>Atualiza??o do app</h1>

    </div>


</mat-toolbar>


<main>

    <div>

        <h2>Vers?o do app instalada: {{versao}}</h2>

    </div>


    <h3>Status da atualiza??o</h3>

    <!-- lista sem numera??o em HTML -->

    <ul>

        <li *ngFor="let mensagem of mensagens">

            {{mensagem}}

        </li>

    </ul>


    <button mat-raised-button color="accent" (click)="atualizarApp();" class="botao">Atualizar app</button>

</main>

menu.component.ts


import { Component, OnInit } from '@angular/core';

import { SwUpdate } from '@angular/service-worker';


import { versions } from 'src/_versions';


@Component({

  selector: 'app-menu',

  templateUrl: './menu.component.html',

  styleUrls: ['./menu.component.scss']

})

export class MenuComponent implements OnInit {


  mensagens: string[] = [];

  versao: string = 'Vers?o ainda n?o carregada pelo sistema.';


  constructor(

    private readonly swUpdate: SwUpdate,

    ) { }


  ngOnInit(): void {

    this.atualizarApp();

    this.versao = versions.version;

  }


  async atualizarApp() {

    this.mensagens?.push(`${this.getFormattedDate()} Iniciando atualiza??o do app.`);

    try {

      // Check if Service Worker is supported by the Browser

      if (this.swUpdate.isEnabled) {

        this.mensagens?.push(`${this.getFormattedDate()} Verificado que este navegador suporta a atualiza??o do app.`);

        const isNewVersion = await this.swUpdate.checkForUpdate();

        this.mensagens?.push(`${this.getFormattedDate()} Verificando se há nova vers?o a ser baixada.`);

        // Check if the new version is available

        if (isNewVersion) {

          this.mensagens?.push(`${this.getFormattedDate()} Nova vers?o do app encontrada. Fazendo download.`);

          const isNewVersionActivated = await this.swUpdate.activateUpdate();

          // Check if the new version is activated and reload the app if it is

          if (isNewVersionActivated) {

            this.mensagens?.push(`${this.getFormattedDate()} Nova vers?o baixada e instalada.`);

            window.location.reload();

          }

        } else {

          this.mensagens?.push(`${this.getFormattedDate()} O Materiale app já está atualizado.`);

        }

      } else {

        this.mensagens?.push(`${this.getFormattedDate()} Verificado que este navegador n?o suporta a atualiza??o do app automática e outras funcionalidades.`);

        this.mensagens?.push(`${this.getFormattedDate()} Por favor, atualize o navegador para a vers?o mais recente. Baixe preferencialmente o Google Chrome.`);

      }


    } catch (error) {

      this.mensagens?.push(`${this.getFormattedDate()} Houve algum error ao tentar atualizar o app. Mensagem de erro: ${error}`);

      this.mensagens?.push(`${this.getFormattedDate()} é possível que este navegador n?o seja compatível. Por favor, atualize o navegador para a vers?o mais recente. Baixe preferencialmente o Google Chrome.`);

      this.mensagens?.push(`${this.getFormattedDate()} Mensagem de erro: ${error}`);

      //window.location.reload();

    }


  }


  getFormattedDate(): string {

    var date = new Date();

    var str = `${date.getDate()}/${(date.getMonth() + 1)}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;

    return str;

}


}

appversionupdate.mjs


import fs from 'fs';


//console.log("Atualizado versao do app");


var obj = JSON.parse(fs.readFileSync('package.json', 'utf8'));


var version = obj.version;

var major = version.split('.')[0];

var minor = version.split('.')[1];

var patch = version.split('.')[2];


var minor_updated = Number(minor) +1;

var version_updated = major + '.' + minor_updated + '.' + patch;


console.log("Nova versao: " + version_updated);


obj.version = version_updated;


let data = JSON.stringify(obj, null, 2);


fs.writeFileSync('package.json', data);

包.json


{

  "name": "testeapp",

  "version": "0.14.0",

  "scripts": {

    "ng": "ng",

    "prestart": "ts-appversion",

    "start": "ng serve",

    "prebuild": "ts-appversion",

    "build": "ng build",

    "watch": "ng build --watch --configuration development",

    "test": "ng test",

    "bd": "node ./appversionupdate.mjs && npm run build && firebase deploy"

  },


查看完整回答
反對 回復 2022-06-16
?
繁華開滿天機

TA貢獻1816條經驗 獲得超4個贊

問題

Angular 中的 Service Worker 有 4 種不同的注冊策略,這決定了它何時向瀏覽器注冊。

  1. registerWhenStable:<timeout>: 應用程序穩定后立即注冊(沒有掛起的微/宏任務),但不遲于毫秒。如果應用程序在幾毫秒后還沒有穩定下來(例如,由于重復的異步任務),無論如何都會注冊 ServiceWorker。如果省略,ServiceWorker 將僅在應用程序穩定后注冊。

  2. registerImmediately: 立即注冊。

  3. registerWithDelay:<timeout>: 注冊延遲毫秒。例如,使用 registerWithDelay:5000 在 5 秒后注冊 ServiceWorker。如果省略,則默認為 0,一旦所有待處理的微任務完成,它將盡快注冊 ServiceWorker,但仍然是異步的。

  4. An Observable factory function: 一個返回 Observable 的函數。該函數將在運行時用于獲取和訂閱 Observable,并且只要發出第一個值,就會注冊 ServiceWorker。

注意: Angular默認registerWhenStable:30000使用. 這意味著它將首先等待應用程序穩定,然后它會注冊一個 Service Worker(或者如果應用程序在此之前沒有穩定,它將在 30 秒后注冊 Service Worker)。

解決方案

registerWhenStable:30000您可以設置registerImmediately策略而不是 default 。然后,您可以例如添加APP_INITIALIZER并在其中檢查是否有新版本并加載它。在這種情況下,如果有新版本可用,用戶將看不到舊版本。

app.module.ts

import { APP_INITIALIZER } from '@angular/core';

import { ServiceWorkerModule, SwUpdate } from '@angular/service-worker';

...

function initializeApp(): Promise<any> {

  return new Promise(async (resolve, reject) => {

    try {

      // Check if Service Worker is supported by the Browser

      if (this.swUpdate.isEnabled) {

        const isNewVersion = await this.swUpdate.checkForUpdate();

        // Check if the new version is available

        if (isNewVersion) {

          const isNewVersionActivated = await this.swUpdate.activateUpdate();

          // Check if the new version is activated and reload the app if it is

          if (isNewVersionActivated) window.location.reload();

          resolve(true);

        }

        resolve(true);

      }

      resolve(true);

    } catch (error) {

      window.location.reload();

    }

  });

}


...


@NgModule({

  ...

  imports: [

    ...,

    ServiceWorkerModule.register('ngsw-worker.js', {

      enabled: environment.production,

      registrationStrategy: 'registerImmediately',

    }),

  ],

  providers: [

    ...,

    { provide: APP_INITIALIZER, useFactory: initializeApp, deps: [SwUpdate], multi: true },

  ],

})

export class AppModule {}


查看完整回答
反對 回復 2022-06-16
  • 3 回答
  • 0 關注
  • 147 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號