Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing the service worker config #307

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0bf7aca
Fixing the service worker config
jamesdaniels Sep 5, 2024
1a3307e
Simplify things
jamesdaniels Sep 5, 2024
e642b45
Already covered by -log
jamesdaniels Sep 5, 2024
91ac291
Dont crash service worker on network failures
jamesdaniels Sep 5, 2024
6845143
Cleanup
jamesdaniels Sep 5, 2024
4be2a4b
Use magic url for sw sync
jamesdaniels Sep 7, 2024
1eb7b81
More small cleanup
jamesdaniels Sep 10, 2024
19c921e
Add comments
jamesdaniels Sep 10, 2024
9d2a344
Forgot miniify
jamesdaniels Sep 10, 2024
9d754b7
Eslint
jamesdaniels Sep 10, 2024
790a11d
Use implied unsubscribe
jamesdaniels Sep 10, 2024
b36ad74
Port fixes from -end
jamesdaniels Sep 10, 2024
0486af0
Sync up with -end
jamesdaniels Sep 10, 2024
b069869
more cleanup
jamesdaniels Sep 10, 2024
27171b6
Use prettier
jamesdaniels Sep 10, 2024
3cc2f61
Double quotes less disruptive
jamesdaniels Sep 10, 2024
01f3633
es5 commas
jamesdaniels Sep 10, 2024
c21592f
-start es5 comma
jamesdaniels Sep 10, 2024
a5043e3
Safety settings, runconfig
jamesdaniels Sep 11, 2024
0b5eac4
Permit deployment on IDX out of box
jamesdaniels Sep 11, 2024
6f203ac
IDX template
jamesdaniels Sep 11, 2024
4a388c1
mv to $out
jamesdaniels Sep 11, 2024
be3151a
Fix concurrently in idx
jamesdaniels Sep 11, 2024
8dc7441
IDX template
jamesdaniels Sep 11, 2024
69fa0ee
cleanup those files
jamesdaniels Sep 11, 2024
951693b
Gitignore .env
jamesdaniels Sep 11, 2024
019d4e6
Dont need npx incantation, idx bug
jamesdaniels Sep 11, 2024
63daf20
IDX setup
jamesdaniels Sep 11, 2024
7ccf1e7
Small fix
jamesdaniels Sep 11, 2024
3a5d21b
asdf
jamesdaniels Sep 11, 2024
edabad6
Trying no params
jamesdaniels Sep 11, 2024
7482172
Whoops
jamesdaniels Sep 11, 2024
cfa84a2
Firebase setup
jamesdaniels Sep 11, 2024
23ecd94
bad sub
jamesdaniels Sep 11, 2024
f7b3387
firebase use on both
jamesdaniels Sep 11, 2024
106a45d
Early exit on head req too
jamesdaniels Oct 3, 2024
509ec26
next-start
jamesdaniels Oct 3, 2024
5bc7c73
Simplify, no router no state
jamesdaniels Oct 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
**/.firebaserc
**/node_modules/
**/.DS_Store
**/*-debug.log
**/.DS_Store

**/node_modules/
**/package-lock.json
**/pnpm-lock.yaml
**/yarn.lock
3 changes: 2 additions & 1 deletion nextjs-end/.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=""
NEXT_PUBLIC_FIREBASE_PROJECT_ID=""
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=""
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=""
NEXT_PUBLIC_FIREBASE_APP_ID=""
NEXT_PUBLIC_FIREBASE_APP_ID=""
GEMINI_API_KEY=""
6 changes: 6 additions & 0 deletions nextjs-end/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": ["eslint:recommended", "next", "prettier"],
"rules": {
"@next/next/no-img-element": "off"
}
}
4 changes: 3 additions & 1 deletion nextjs-end/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
lib/firebase/config.js
public/auth-service-worker.js
.next/
.firebase/
node_modules/
node_modules/
.env
29 changes: 29 additions & 0 deletions nextjs-end/.idx/dev.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{ pkgs }: {
channel = "stable-23.11";
packages = [
pkgs.nodejs_20
];
env = {
NEXT_TELEMETRY_DISABLED = "1";
};
idx.workspace = {
onStart = {
npm-install = "npm ci --no-audit --prefer-offline --no-progress --timing";
default.openFiles = [".env"];
};
onCreate = {
firebase-setup = "firebase use && firebase use \$(curl -s -H \"Metadata-Flavor: Google\" http://metadata.google.internal/computeMetadata/v1/project/project-id)";
};
};
idx.extensions = [
];
idx.previews = {
enable = true;
previews = {
web = {
command = ["npm" "run" "dev" "--" "--port" "$PORT" "--hostname" "0.0.0.0"];
manager = "web";
};
};
};
}
3 changes: 3 additions & 0 deletions nextjs-end/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"trailingComma": "es5"
}
5 changes: 4 additions & 1 deletion nextjs-end/apphosting.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ env:
- variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
value: TODO
- variable: NEXT_PUBLIC_FIREBASE_APP_ID
value: TODO
value: TODO
runConfig:
minInstances: 0
maxInstances: 2
100 changes: 71 additions & 29 deletions nextjs-end/auth-service-worker.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,86 @@
import { initializeApp } from "firebase/app";
import { getAuth, getIdToken } from "firebase/auth";
import { getInstallations, getToken } from "firebase/installations";

// this is set during install
let firebaseConfig;

self.addEventListener('install', event => {
// extract firebase config from query string
const serializedFirebaseConfig = new URL(location).searchParams.get('firebaseConfig');

if (!serializedFirebaseConfig) {
throw new Error('Firebase Config object not found in service worker query string.');
}

firebaseConfig = JSON.parse(serializedFirebaseConfig);
import { getAuth, getIdToken, onAuthStateChanged } from "firebase/auth";

// extract firebase config from query string
const serializedFirebaseConfig = new URLSearchParams(self.location.search).get(
"firebaseConfig"
);
if (!serializedFirebaseConfig) {
throw new Error(
"Firebase Config object not found in service worker query string."
);
}

const firebaseConfig = JSON.parse(serializedFirebaseConfig);

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);

self.addEventListener("install", () => {
console.log("Service worker installed with Firebase config", firebaseConfig);
self.skipWaiting();
});

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

self.addEventListener("fetch", (event) => {
const { origin } = new URL(event.request.url);
const { origin, pathname } = new URL(event.request.url);
if (origin !== self.location.origin) return;
// Use a magic url to ensure that auth state is in sync between
// the client and the sw, this helps with actions such as router.refresh();
if (pathname.startsWith("/__/auth/wait/")) {
const uid = pathname.split("/").at(-1);
event.respondWith(waitForMatchingUid(uid));
return;
}
if (pathname.startsWith("/_next/")) return;
// Don't add headers to GET/HEAD requests or those with an extension—this
// helps with css, images, fonts, json, etc.
if (
(event.request.method === "GET" || event.request.method === "HEAD") &&
pathname.includes(".")
) {
return;
}
event.respondWith(fetchWithFirebaseHeaders(event.request));
});

async function fetchWithFirebaseHeaders(request) {
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const installations = getInstallations(app);
const headers = new Headers(request.headers);
const [authIdToken, installationToken] = await Promise.all([
getAuthIdToken(auth),
getToken(installations),
]);
headers.append("Firebase-Instance-ID-Token", installationToken);
if (authIdToken) headers.append("Authorization", `Bearer ${authIdToken}`);
const newRequest = new Request(request, { headers });
return await fetch(newRequest);
const authIdToken = await getAuthIdToken();
if (authIdToken) {
const headers = new Headers(request.headers);
headers.append("Authorization", `Bearer ${authIdToken}`);
request = new Request(request, { headers });
}
return await fetch(request).catch((reason) => {
console.error(reason);
return new Response("Fail.", {
status: 500,
headers: { "content-type": "text/html" },
});
});
}

async function waitForMatchingUid(_uid) {
const uid = _uid === "undefined" ? undefined : _uid;
await auth.authStateReady();
await new Promise((resolve) => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
if (user?.uid === uid) {
unsubscribe();
resolve();
}
});
});
return new Response(undefined, {
status: 200,
headers: { "cache-control": "no-store" },
});
}

async function getAuthIdToken(auth) {
async function getAuthIdToken() {
await auth.authStateReady();
if (!auth.currentUser) return;
return await getIdToken(auth.currentUser);
Expand Down
6 changes: 1 addition & 5 deletions nextjs-end/firebase.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@
},
"hosting": {
"source": ".",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"frameworksBackend": {
"region": "us-central1"
}
Expand Down
11 changes: 11 additions & 0 deletions nextjs-end/idx-template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "Integrate Firebase with a Next.js app",
"description": "In this codelab, you'll learn how to integrate Firebase with a Next.js web app called Friendly Eats, which is a website for restaurant reviews.",
"categories": ["Web", "Firebase", "Google Codelabs"],
"icon_image_url": "https://firebase.google.com/_static/firebase/images/icon.svg",
"publisher": "Google LLC",
"host": {
"virtualization": true
},
"params": []
}
13 changes: 13 additions & 0 deletions nextjs-end/idx-template.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{ pkgs, ... }: {
packages = [
pkgs.nodejs_20
pkgs.j2cli
pkgs.nixfmt
];
bootstrap = ''
npx -y giget gh:firebase/friendlyeats-web/nextjs-end#jamesdaniels_fixServiceWorkers "$WS_NAME"
rm "$WS_NAME/idx-template.json"
rm "$WS_NAME/idx-template.nix"
mv "$WS_NAME" "$out"
'';
}
10 changes: 5 additions & 5 deletions nextjs-end/jsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
6 changes: 3 additions & 3 deletions nextjs-end/next.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
serverActions: true,
}
eslint: {
ignoreDuringBuilds: true,
},
};

module.exports = nextConfig;
Loading