簡體   English   中英

使用 firebase 托管和功能的 Service Worker 注冊失敗

[英]Service Worker registration fails with firebase hosting and functions

Service Worker 未注冊到由在 Firebase Functions 上運行的 Nuxt.js(通用)構建的應用程序。

我目前正在嘗試使用 Nuxt.js 通用模式和 Firebase 函數構建原型 Web 應用程序。 該應用程序使用帶有 nuxt 官方 pwa 模塊的 service worker 來管理登錄用戶的會話,以便客戶端可以將帶有授權標頭的請求發送到服務器,服務器將通過 Firebase 身份驗證驗證用戶會話。

我已經嘗試使用yarn run buildyarn run start在本地服務器上運行它,並確保 service worker 已正確注冊並完美運行。 但是,當我嘗試使用firebase serve檢查相同的操作時,我在瀏覽器上收到以下錯誤。

A bad HTTP response code (404) was received when fetching the script.
Failed to load resource: net::ERR_INVALID_RESPONSE
dcbac67bb39a765db27a.js:1 Service worker registration failed: TypeError: Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script.

我還發現 service worker 不會將會話數據發送到服務器。 當我使用firebase deploy源代碼部署到生產中時,復制了完全相同的東西。

當我使用yarn create nuxt-appyarn run build和 firebase firebase serve完全清理項目時,它甚至會發生。 “sw.js”文件指示 Chrome 開發者工具上的失敗狀態。

我不確定它是否擔心,但我的 Firebase 使用 Spark 計划。

我的項目樹。

.
├── firebase.json
├── firestore.indexes.json
├── firestore.rules
├── functions
│   ├── index.js
│   ├── nuxt
│   │   ├── App.js
│   │   ├── axios.js
│   │   ├── client.js
│   │   ├── components
│   │   ├── dist
│   │   ├── empty.js
│   │   ├── index.js
│   │   ├── loading.html
│   │   ├── middleware.js
│   │   ├── router.js
│   │   ├── server.js
│   │   ├── store.js
│   │   ├── sw.plugin.js
│   │   ├── sw.template.js
│   │   ├── utils.js
│   │   └── views
│   ├── package-lock.json
│   ├── package.json
│   └── yarn.lock
├── public
└── src
    ├── assets
    ├── components
    ├── jest.config.js
    ├── layouts
    ├── middleware
    ├── nuxt.config.js
    ├── package.json
    ├── pages
    ├── plugins
    ├── server
    ├── static
    │   └── sw.js
    ├── store
    └── test
    └── yarn.lock

源代碼/靜態/sw.js

importScripts('/_nuxt/workbox.4c4f5ca6.js')

workbox.precaching.precacheAndRoute([
  {
    "url": "/_nuxt/021e1640b53136b75c48.js",
    "revision": "2753e747206d803c793b59a324c1931b"
  },
  {
    "url": "/_nuxt/03c9e340d8692d1403a9.js",
    "revision": "2b882d73d20a0b2cfd318e9e05d3496e"
  },
  {
    "url": "/_nuxt/78bddfa6b6a4919b78d6.js",
    "revision": "70312f6623089e3b4aa6454120c1e177"
  },
  {
    "url": "/_nuxt/85c817abccdd40162004.js",
    "revision": "45448f8709d01af59bb125a1d06be23a"
  },
  {
    "url": "/_nuxt/8654a518d0f3e326c9a6.js",
    "revision": "a42426f5e7b458acc6fdf0e9e48c7d35"
  },
  {
    "url": "/_nuxt/95b421159066eff9e318.js",
    "revision": "efd1643042f804defa7212979867558a"
  },
  {
    "url": "/_nuxt/9b487bf2df1190b68565.js",
    "revision": "78837d0e624deccc85761b44f9ede9be"
  },
  {
    "url": "/_nuxt/ce59381752309c170d41.js",
    "revision": "d3e50bf27891c4efa6dff5076a0772a6"
  },
  {
    "url": "/_nuxt/d8fa6ae5ca14331879f6.js",
    "revision": "5da6698c9359df803243ecc44519b610"
  },
  {
    "url": "/_nuxt/dcbac67bb39a765db27a.js",
    "revision": "9505aa84ddb2a70b826d324433daff36"
  },
  {
    "url": "/_nuxt/dee89eef613849499c7f.js",
    "revision": "43117ed819efe3d00c963dd655894d5f"
  }
], {
  "cacheId": "justtest",
  "directoryIndex": "/",
  "cleanUrls": false
})

workbox.clientsClaim()
workbox.skipWaiting()

workbox.routing.registerRoute(new RegExp('/_nuxt/.*'), workbox.strategies.cacheFirst({}), 'GET')

workbox.routing.registerRoute(new RegExp('/.*'), workbox.strategies.networkFirst({}), 'GET')

函數/index.js

const functions = require("firebase-functions")
const { Nuxt } = require("nuxt")
const express = require("express")
const app = express()

const nuxt = new Nuxt({ buildDir: "nuxt", dev: false })

function handleRequest(req, res) {
  res.setHeader('Cache-Control', 'private')
  return new Promise((resolve, reject) => {
    nuxt.render(req, res, promise => {
      promise.then(resolve).catch(reject)
    })
  })
}

app.use(handleRequest)

exports.ssr = functions.https.onRequest(app)

預期行為是當我使用 firebase firebase servefirebase deploy運行應用程序時 sw.js 工作正常。

我設法找到了解決方案。 我可能誤解了服務人員的行為。
我只是留下我的解決方案,以便我可以幫助有同樣情況的人。

首先,我根本不知道 service worker js 文件/static/sw.js ,因為它是由yarn run build自動創建的,當我使用yarn run start運行應用程序時一切正常。 因此我認為我根本不必關心那個文件。

但是我發現/static目錄中的所有文件都必須放在/public目錄中,該目錄將由 firebase 托管托管,以便客戶端可以找到它們並下載它們。 我想當我使用yarn run start時, /static目錄中的文件將由開發服務器托管。

我還意識到服務工作者是靜態 javascript 文件,它們必須由 firebase 托管而不是由 firebase 函數托管。 我曾經嘗試將它們放在dist/client中,但這沒有任何意義。 它必須放在/public目錄中。

我終於讓它與以下項目樹一起工作。 當我運行yarn run build時,我將/src/static中的所有內容復制到/public以使用 firebase 托管來托管它們。

.
├── firebase.json
├── functions
│   ├── index.js
│   ├── nuxt
│   │   ├── App.js
│   │   ├── axios.js
│   │   ├── client.js
│   │   ├── components
│   │   ├── dist
│   │   ├── empty.js
│   │   ├── index.js
│   │   ├── loading.html
│   │   ├── middleware.js
│   │   ├── router.js
│   │   ├── server.js
│   │   ├── store.js
│   │   ├── sw.plugin.js
│   │   ├── sw.template.js
│   │   ├── utils.js
│   │   └── views
│   ├── package-lock.json
│   ├── package.json
│   └── yarn.lock
├── public
│   ├── favicon.ico
│   ├── sw-firebase-auth.js
│   └── sw.js
└── src
    ├── assets
    ├── components
    ├── layouts
    ├── middleware
    ├── nuxt.config.js
    ├── package.json
    ├── pages
    ├── plugins
    ├── server
    ├── static
    │   ├── favicon.ico
    │   ├── sw-firebase-auth.js
    │   └── sw.js
    ├── store
    └── yarn.lock

這是我的sw-firebase-auth.js (我用 Browserify 編譯這個腳本來工作。)

var firebase = require('firebase')

// Initialize the Firebase app in the service worker script.
firebase.initializeApp({
  apiKey: '*************',
  authDomain: '*************',
  databaseURL: '*************',
  projectId: '*************',
  storageBucket: '*************',
  messagingSenderId: '*************'
})

/**
 * Returns a promise that resolves with an ID token if available.
 * @return {!Promise<?string>} The promise that resolves with an ID token if
 *     available. Otherwise, the promise resolves with null.
 */
const getIdToken = () => {
  return new Promise((resolve) => {
    const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
      unsubscribe();
      if (user) {
        user.getIdToken().then((idToken) => {
          resolve(idToken)
        }, () => {
          resolve(null)
        });
      } else {
        resolve(null)
      }
    })
  })
}

const getOriginFromUrl = (url) => {
  const pathArray = url.split('/');
  const protocol = pathArray[0];
  const host = pathArray[2];
  return protocol + '//' + host;
};

self.addEventListener('fetch', (event) => {
  const requestProcessor = (idToken) => {
    let req = event.request;
    if (self.location.origin == getOriginFromUrl(event.request.url) &&
        (self.location.protocol == 'https:' ||
         self.location.hostname == 'localhost') &&
        idToken) {
      const headers = new Headers();
      for (let entry of req.headers.entries()) {
        headers.append(entry[0], entry[1]);
      }
      headers.append('Authorization', 'Bearer ' + idToken);
      try {
        req = new Request(req.url, {
          method: req.method,
          headers: headers,
          mode: 'same-origin',
          credentials: req.credentials,
          cache: req.cache,
          redirect: req.redirect,
          referrer: req.referrer,
          body: req.body,
          bodyUsed: req.bodyUsed,
          context: req.context
        });
      } catch (e) {
        console.log(e)
      }
    }
    return fetch(req);
  };
  event.respondWith(getIdToken().then(requestProcessor, requestProcessor));
});

self.addEventListener('activate', event => {
  event.waitUntil(clients.claim());
})

這也是nuxt.conf.js中的工作箱配置。 它與使用importScripts的官方 pwa-module 配合得很好。

  workbox: {
    importScripts: [
      'sw-firebase-auth.js'
    ]
  }

我希望這會對某人有所幫助。

2020 年 6 月的 Nuxt.js 開發人員

如果您使用 SSR 部署 Nuxt.js 2.12.2 項目,您的項目目錄中可能有.nuxt文件夾。 刪除它,如果需要,從nuxt.config.js配置 Workbox 並運行nuxt buildnpm run buildyarn build

如果它在本地機器上工作,您可以嘗試清除服務器上的緩存以確保所有舊的.nuxt文件夾都消失並重新部署項目。

希望這有幫助✨

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM