[英]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 build
和yarn 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-app
、 yarn 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 serve
和firebase 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'
]
}
我希望這會對某人有所幫助。
如果您使用 SSR 部署 Nuxt.js 2.12.2 項目,您的項目目錄中可能有.nuxt
文件夾。 刪除它,如果需要,從nuxt.config.js
配置 Workbox 並運行nuxt build
、 npm run build
或yarn build
。
如果它在本地機器上工作,您可以嘗試清除服務器上的緩存以確保所有舊的.nuxt
文件夾都消失並重新部署項目。
希望這有幫助✨
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.