svelte-adapter-firebase: bug: ssrServer ENOENT firestore.proto
Describe the Bug
Have previously released/deployed without any problems. Tried to release tonight and when loading a page that relies on a load function with a Firebase call, it fails. Other pages seem to work.
This is the load function:
import { fetchProducts } from "$lib/stripeutils";
export async function load({ page, fetch, session, stuff }) {
const products = await fetchProducts();
return {
props: {
products,
},
};
}
This is the fetchProducts function
import { firestore, functions } from "$lib/firebase/client";
import { getDocs, query, where, orderBy, doc, addDoc, collection, onSnapshot } from 'firebase/firestore';
[...]
export async function fetchProducts() {
let products = {
[...]
};
const docSnap = await getDocs(query(
collection(firestore(), "products"),
where("active", "==", true),
orderBy("metadata.order")
));
await Promise.all(docSnap.docs.map(async (doc) => {
let product = {
[...]
};
const priceSnap = await getDocs(query(
collection(doc.ref, "prices"),
where("active", "==", true)
));
priceSnap.docs.forEach((pdoc) => {
const price = {
[...]
};
product.prices = [price, ...product.prices];
});
const type = product.metadata.type || "addon";
products[type].items.push(product);
}));
return products;
}
The firestore function
import { initializeApp, getApps } from "firebase/app";
import { getFirestore } from 'firebase/firestore';
[...]
const config = {
[...]
};
function firebase() {
return getApps().length === 0 ? initializeApp(config) : getApps()[0];
}
function firestore() {
return getFirestore(firebase());
}
The errors:
ssrServer
[2021-10-28T07:36:58.392Z] @firebase/firestore: Firestore (9.0.0): INTERNAL UNHANDLED ERROR: Error: ENOENT: no such file or directory, open '/workspace/ssrServer/src/protos/google/firestore/v1/firestore.proto'
Error: ENOENT: no such file or directory, open '/workspace/ssrServer/src/protos/google/firestore/v1/firestore.proto'
at Object.openSync (fs.js:498:3)
at Object.readFileSync (fs.js:394:35)
at fetch2 (/workspace/ssrServer/index.js:11082:30)
at Root2.load2 [as load] (/workspace/ssrServer/index.js:11111:11)
at Root2.loadSync (/workspace/ssrServer/index.js:11121:19)
at Object.loadProtosWithOptionsSync (/workspace/ssrServer/index.js:14289:31)
at Object.loadSync (/workspace/ssrServer/index.js:14440:33)
at loadProtos (/workspace/ssrServer/index.js:106181:43)
at newConnection (/workspace/ssrServer/index.js:106185:20)
at OnlineComponentProvider2.createDatastore (/workspace/ssrServer/index.js:109513:26)
Steps to Reproduce
Have previously deployed without issue, however this is my first release where I’ve used a Firestore call inside a page’s load function. Mainly looking for a place to start my debugging for something like this.
Expected Behaviour
Code should work fine?
svelte-adapter-firebase version
0.9.2
sveltejs/kit version
1.0.0.next.160
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 23 (11 by maintainers)
This is exactly what I mean when I say Firebase still has many bugs when working with Vite/Kit. I have not been pursuing resolving those bugs here for the
firebaseSDKs because they’re not yet worked out upstream.The dynamic import of the lib client-side is what I do for all
firebaselibs, withloaddata coming from Kit endpoints that usefirebase-admin. It is the only way I have been able to get this all to work as of ~3 months ago and I haven’t revisited since.This is what I was testing with:
Importantly I was using
firebase-admin@9.12.0at the time and whenv10released did not upgrade because it had issues.v9didn’t require anything special. While I generally do recommend updating to the latest packages, server-side code is less critical andfirebase-admin@9is very stablesvelte-adapter-firebaseoutputs code to the terminal on first run which you need to add to your Cloud Functionsindex.jsfile, wrap the code there. Looking at the e2e test as an example:https://github.com/jthegedus/svelte-adapter-firebase/blob/main/tests/end-to-end/scaffold/functions/index.js
This way you can see the errors when the call the the Kit Server fails.
Logically, sure, actually, maybe.
Updating Kit actually updates Vite, the Svelte-Vite Plugin, which all effect how code is bundled. The adapters currently then bundle the Vite SSR bundle again using esbuild. So there can be issues between those. You haven’t shared your Kit
package.json:dependencieswhich include yourfirebaseimports, I imagine those are version ranges with^and not pinned to specific versions, so as you dev, reinstall deps, update deps yourfirebaseversion may have also changed where the bug could be introduced in that lib and how it is compiled by either Vite or esbuild.I watch the Kit changelog & PRs for breakages to the adapter API and update accordingly. I currently only test to ensure the Kit todo template works as expected once parsed through the adapter. There is a specific compatibility table of Kit & adapter versions in the readme, so sticking to those might help.
I do not currently test how
firebasepackages & their usage in Kit work in the tests here. I do consume Kit & this adapter for my own projects which do use Firebase.I have been unable to get Firestore working in the way you describe, ever, in any version of Kit & this adapter. With the
firebaseandfirebase-adminlibs going through rewrites to better support ESM for usage in ESM-based tools like Vite, I decided not to delve into their specific issues and debug them. Kit, this adapter, Vite, Vite Svelte Plugin & both Client & Server Firebase libs are all being actively developed. Even though Firebase v9 lib is officially released with ESM support, ESM issues surface regularly and effect Vite projects, which in turn would effect Kit.As I mentioned in my first response
So the aspect of Kit & this adapter that effect SSR code generation is going to change again, so we could spend all week debugging this to only have our efforts rendered useless in a weeks time.
Further suggestions:
svelte.config.jsand seeing what happens:vite: { ssr: { external: ['firebase'] }I’ve not see people do this before, it may have been a workaround during a beta release of thefirebase@9packageloadand into the Kit endpoint (usingfirebase-adminin endpoint) as I know that worksYou can ignore this.
I would try bumping your Cloud Function Node.js version from
14to16and seeing what happens.If that doesn’t work I have this to say: using
firestorein load can have issues, as I said before you can move it to a Kit endpoint and mitigate most of the issues.If the error is coming from
firebase/firestorepackage, my recommendation is to not use thefirebaselib forfirestorein code that can run on the server.loadcan run in SSR and on the Client. While thefirebase@9.0.0lib can be used in Node.js environments as well as web, it should only be used when on on the web. Firestore data fetch should be performed by usingfirebase-admin@10.0.0on the server side.So in your
loadfunction, you should first check if the execution environment is Server or Client and usefirebase-adminto getfirestoreon the server &firebaseto getfirestoreon the client (web).This matters because the packages are different with
firebase-adminspecifically targeting Node.js envs. The authentication for each of the libs is also different:Using the Client lib on the Server raises questions around whether the query bypasses the sec rules on the Firestore server or not, and also, if it does go through the security rules, how can the SSR environment know which user initiated the request.
Given these factors, I recommend NOT using the Client (web) firestore libs on the Server and switching the use of the
firebasevsfirebase-adminpackages depending on the Kit$app/envbrowser value (I have found I need to dynamically import these libs and that code splitting cannot accurately remove each one from the other bundle, causing errors).It is possible to have an authenticated user pass their auth token to the initial page call that executes the page SSR, so the web lib can be used in SSR envs and know which users initiated the request and perform security rules appropriately, however this wiring needs to be done manually within the Kit request lifecycle and requires handling Firebase auth tokens yourself, which defeats the point of the Firebase.
Server data fetch on SSR
loadshould be of data that does not require an auth token using thefirebase-adminlib.Client data fetch on client
loadshould use thefirebaselib.Hope this helps you debug.
Many people have had issues with including Firestore directly in
load, it can usually be mitigated by performing the Firestore data load in a Kit endpoint and then fetching that kit endpoint like any other REST APICorrect, although the SSR code runs on the Cloud Functions, all dependencies for the SSR code are compiled in-line during build phase so you shouldn’t need to touch your Cloud Function deps for the Kit APIs or SSR code.
I would suggest starting with updates to both SvelteKit and the adapter. There have been quite a few versions released since those versions you list in the issue. Also, there will be some breaking changes from Kit for the adapter API relatively soon which will affect the compilation of the SSR code, so I expect behaviour to change again in another breaking change.
I assume I don’t need to manually manage dependencies in
functions/package.json. Firestore isn’t in there (but also neither is anything else I use in my site)