Angular 无法注册 ServiceWorker : A bad HTTP response code (404) was received when fetching the script

标签 angular firebase firebase-cloud-messaging firebase-notifications angular-service-worker

我正在使用 Firebase 在 Angular PWA 中执行推送通知,我正在点击一个链接来执行此操作。 https://medium.com/@tariqueejaz/progressive-web-app-push-notifications-making-the-web-app-more-native-in-nature-a167af22e004

我正在使用 Angular 6 并为所有内容设置了代码。当我尝试运行它时,它会显示一个弹出窗口 enter image description here .

点击允许按钮后,控制台报错:

Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script." code : "messaging/failed-serviceworker-registration" message : "Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. (messaging/failed-serviceworker-registration)." stack : "FirebaseError: Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. (messaging/failed-serviceworker-registration).↵ at http://localhost:4200/vendor.js:106604:32↵ at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:4200/polyfills.js:2710:26)↵ at Object.onInvoke (http://localhost:4200/vendor.js:35701:33)↵ at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:4200/polyfills.js:2709:32)↵ at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (http://localhost:4200/polyfills.js:2460:43)↵ at http://localhost:4200/polyfills.js:3194:34↵ at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:2743:31)↵ at Object.onInvokeTask (http://localhost:4200/vendor.js:35692:33)↵ at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:2742:36)↵ at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (http://localhost:4200/polyfills.js:2510:47)" proto : Error

我的项目结构是: enter image description here

我的应用程序和环境文件夹包含以下文件: enter image description here

我的 app.component.ts 文件是

import {Component, OnInit} from '@angular/core';
import * as firebase from 'firebase';
import {AngularFireDatabase, AngularFireList} from 'angularfire2/database';
//import {AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable} from 'angularfire2/database-deprecated';
import {PushService} from './push.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {


  // Declare the variables used
  messaging: any
  token: any  // Stores the current token ID instance generated
  items: AngularFireList<any[]>
  itemsDisplay: AngularFireList<any[]> // List observable for template view (Optional. items itself can be used)
  itemsArr: any[] // Stores the token IDs retrieved from the firebase database 
  hideToken: boolean = false

  // Notificayion object
  pushData: any = {
    'notification': {
      "title": "Background Message Title",
      "body": "Background Message Body"
    },
    "to": ""
  }

  constructor(public db: AngularFireDatabase, private pushService: PushService) {

    // Creates a Firebase List Observable and calls the data in it
    this.itemsDisplay = db.list('/items')

    // Declaring the property value of messaging
    this.messaging = firebase.messaging();

    // Check for token refresh
    this.messaging.onTokenRefresh(function() {
      this.messaging.getToken()
        .then(function(refreshedToken) {
          console.log('Token refreshed.');
        })
        .catch(function(err) {
          console.log('Unable to retrieve refreshed token ', err);
        });
    });
    // Obtaining the firebase data and retrieving token ID values separately
    this.itemsArr = []  // Reinitialize the array to prevent data duplication
    this.items = this.db.list('/items');
    this.items.valueChanges().subscribe(snapshots => {

      console.log(snapshots);
      //snapshots.forEach(snapshot => {
      //  console.log("Hey ,, snapshot......"+snapshot);
      //  this.itemsArr.push(snapshot);
      // });
    });
    // console.log(this.itemsArr)
  }

  // Check for duplicates in token subscription
  checkToken(token, arr) {
    console.log("Inside check token function")
    console.log(arr)
    console.log(token)
    let counter: number = 0
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] === token) {
        counter++
      }
    }
    console.log("Counter value", counter)
    return counter
  }

  // Generate Push through an event
  generatePush() {
    console.log("Inside push function")
    console.log(this.pushData.to)
    if (this.pushData.to === "") {
      console.log("No token available")
      return
    }
    this.pushService.generatePush(this.pushData)
      .subscribe(data => {console.log("Succesfully Posted")}, err => console.log(err))
  }

  // Function to get the data from Firebase Database
  getDataFromFb() {
    this.hideToken = true
  }

  ngOnInit() {
    // Prompt user to grant permission for notifications on loading components
    const self = this
    this.items = this.db.list('/items') 
    this.messaging.requestPermission()
      .then(function() {
        console.log('Notification permission granted.');
        self.messaging.getToken()
          .then(function(currentToken) {
            if (currentToken) {
              self.token = currentToken
              self.pushData.to = self.token
              console.log(self.pushData.to)

              // Set a timeout so as to enable all the data to be loaded
              setTimeout(() => {
                if (self.checkToken(self.token, self.itemsArr) === 0) {
                  console.log("Push occurrence")
                  // self.items.push({tokenID: currentToken})
                } else {
                  console.log("User is already subscribed")
                }
              }, 6500)
              // Displays the current token data
              console.log("currentToken: ", currentToken);
              console.log("Stored token: ", self.token);
            } else {
              // Show permission request.
              console.log('No Instance ID token available. Request permission to generate one.');
            }
          })
          .catch(function(err) {
            console.log('An error occurred while retrieving token.', err);
          });
      })
      .catch(function(err) {
        console.log('Unable to get permission to notify. ', err);
      })

    // Handle incoming messages. Called when:
    // - a message is received while the app has focus
    // - the user clicks on an app notification created by a sevice worker `messaging.setBackgroundMessageHandler` handler.
    this.messaging.onMessage(function(payload) {
      console.log("Message received. ", payload);
    });
  }

}

我的 firebase-messaging-sw.js 文件是:

importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-messaging.js');

firebase.initializeApp({
  'messagingSenderId': '850143277209' // run it again show me error
});

var messaging = firebase.messaging();
currentMessage = new BehaviorSubject(null);

// Handle Background Notifications

// If you would like to customize notifications that are received in the background (Web app is closed or not in browser focus) then you should implement this optional method
messaging.setBackgroundMessageHandler(function (payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  // Customize notification here
  var notificationTitle = 'Background Message Title';
  var notificationOptions = {
    body: 'Background Message body.'

  };

  return self.registration.showNotification(notificationTitle,
    notificationOptions);




});

我的 Angular.json 文件是:

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "newProjectRoot": "projects",
    "projects": {
        "beautyOfSoul": {
            "root": "",
            "sourceRoot": "src",
            "projectType": "application",
            "prefix": "app",
            "schematics": {
                "@schematics/angular:component": {
                    "styleext": "scss"
                }
            },
            "architect": {
                "build": {
                    "builder": "@angular-devkit/build-angular:browser",
                    "options": {
                        "outputPath": "dist/beautyOfSoul",
                        "index": "src/index.html",
                        "main": "src/main.ts",
                        "polyfills": "src/polyfills.ts",
                        "tsConfig": "src/tsconfig.app.json",
                        "assets": [
                            "src/favicon.ico",
                            "src/assets",
                            "src/assets/manifest.json",
                            "src/manifest.json",
                            "src/firebase-messaging-sw.js"
                        ],
                        "styles": [
                            "src/styles.scss"
                        ],
                        "scripts": []
                    },
                    "configurations": {
                        "production": {
                            "fileReplacements": {
                                "replace": "src/environments/environment.ts",
                                "with": "src/environments/environment.prod.ts"
                            }],
                            "optimization": true,
                            "outputHashing": "all",
                            "sourceMap": false,
                            "extractCss": true,
                            "namedChunks": false,
                            "aot": true,
                            "extractLicenses": true,
                            "vendorChunk": false,
                            "buildOptimizer": true,
                            "serviceWorker": true
                        }
                    }
                },
                "serve": {
                    "builder": "@angular-devkit/build-angular:dev-server",
                    "options": {
                        "browserTarget": "beautyOfSoul:build"
                    },
                    "configurations": {
                        "production": {
                            "browserTarget": "beautyOfSoul:build:production"
                        }
                    }
                },
                "extract-i18n": {
                    "builder": "@angular-devkit/build-angular:extract-i18n",
                    "options": {
                        "browserTarget": "beautyOfSoul:build"
                    }
                },
                "test": {
                    "builder": "@angular-devkit/build-angular:karma",
                    "options": {
                        "main": "src/test.ts",
                        "polyfills": "src/polyfills.ts",
                        "tsConfig": "src/tsconfig.spec.json",
                        "karmaConfig": "src/karma.conf.js",
                        "styles": [
                            "src/styles.scss"
                        ],
                        "scripts": [],
                        "assets": [
                            "src/favicon.ico",
                            "src/assets",
                            "src/manifest.json",
                            "src/firebase-messaging-sw.js"
                        ]
                    }
                },
                "lint": {
                    "builder": "@angular-devkit/build-angular:tslint",
                    "options": {
                        "tsConfig": [
                            "src/tsconfig.app.json",
                            "src/tsconfig.spec.json"
                        ],
                        "exclude": [
                            "**/node_modules/**"
                        ]
                    }
                }
            }
        },
        "beautyOfSoul-e2e": {
            "root": "e2e/",
            "projectType": "application",
            "architect": {
                "e2e": {
                    "builder": "@angular-devkit/build-angular:protractor",
                    "options": {
                        "protractorConfig": "e2e/protractor.conf.js",
                        "devServerTarget": "beautyOfSoul:serve"
                    },
                    "configurations": {
                        "production": {
                            "devServerTarget": "beautyOfSoul:serve:production"
                        }
                    }
                },
                "lint": {
                    "builder": "@angular-devkit/build-angular:tslint",
                    "options": {
                        "tsConfig": "e2e/tsconfig.e2e.json",
                        "exclude": [
                            "**/node_modules/**"
                        ]
                    }
                }
            }
        }
    },
    "defaultProject": "beautyOfSoul"
}

我的网络选项卡是: enter image description here

我的 service worker 选项卡是:

enter image description here

最佳答案

我在 React 项目中遇到了类似的问题,对我来说,解决方案是手动将我自己的 js 文件注册为 serviceworker。

navigator.serviceWorker.register('./your-serviceworker-file.js')
.then((registration) => {
  messaging.useServiceWorker(registration);

  // Request permission and get token.....
});

在 firebase 初始化中运行该代码为我解决了这个问题。

关于Angular 无法注册 ServiceWorker : A bad HTTP response code (404) was received when fetching the script,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50856040/

相关文章:

node.js - "ERROR in window is not defined"webpack 上的 webpack 一般错误 --mode=production --env.prod

firebase - Firestore 安全规则中更新字段的数量

android - request.auth.uid 中会有什么?

javascript - 使用 Re-base 时 Firebase 在 React 中绑定(bind)和解除绑定(bind)

javascript - 如何在没有 'new' 关键字的情况下将 JS 代码转换为 Kotlin

angular - 隐藏 ngx 高级饼图图例

javascript - 如何设置最小和最大剩余边距?

javascript - Meteor/w Angular 2.0 db 不起作用

android - 无法解析符号 "FirebaseMessagingService"

android - 当我不使用 Firebase 云消息传递提供 "to"参数时出现 400 错误