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

bug: issues deploying to Cloud Functions #6

Closed
jdgamble555 opened this issue Feb 6, 2021 · 14 comments · Fixed by #11
Closed

bug: issues deploying to Cloud Functions #6

jdgamble555 opened this issue Feb 6, 2021 · 14 comments · Fixed by #11

Comments

@jdgamble555
Copy link

jdgamble555 commented Feb 6, 2021

It is not clear what the actual firebase function should load in this case. Also, there is no sveltekit/ directory. I am assuming this is the build directory that svelte-kit build creates?

This is what I have in functions/src/index.ts, and I get a deployment error: Function failed on loading user code

const functions = require("firebase-functions");
const next = require("./build/index.js");
exports.ssr = functions.https.onRequest(next);

I also found two problems with build/index.js:

const app = require('./app.js'); 

// should be

const app = require(./app.cjs);

// and

const assets_handler = sirv('assets', {
	maxAge: 31536000,
	immutable: true
});

// is always an exact path, so it doesn't load correctly
// this works sometimes:

const assets_handler = sirv(__dirname + '/assets', {
	maxAge: 31536000,
	immutable: true
});

I am not sure what the firebase function should load, or how it should load it...

I feel like I am getting closer, but not sure what the code is supposed to be, and I func is not a function error when deploying...

Is this how the Firebase Function should look?

@jthegedus
Copy link
Owner

jthegedus commented Feb 7, 2021

It is not clear what the actual firebase function should load in this case. Also, there is no sveltekit/ directory. I am assuming this is the build directory that svelte-kit build creates?

The output directory of npm run adapt depends on your firebase.json config file. The functions.source is used to output the built app. This is so it is alongside your functions code as it needs to be deployed with it. The name of the folder is taken from firebase.json hosting.site or defaults to sveltkit if no specific name specified in the firebase config.

If you have a standard firebase config the output from npm run adapt should be functions/svelteKit.

Since you're using TypeScript, it will probably be functions/lib/svelteKit. It is sent straight to lib.

What should the function look like?

The adapter should actually output the code you need to include. This is an example, but the var names in your output will be specific to your config.

// functions/index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");

let svelteServer;
exports.svelteSSR = functions.https.onRequest(
	async (request, response) => {
		if (!svelteServer) {
			functions.logger.info("Initializing SvelteKit SSR Handler");
			svelteServer = require("./my-site/handler").sveltekitServer;
			functions.logger.info("SvelteKit SSR Handler initialised!");
		}

		return svelteServer(request, response);
	}
);

The .cjs changes came out with the latest 1.0.0-next.31 which I have not run this against yet. I could perhaps automate that, but this is super alpha so am not sure a good use of time. Thanks for debugging that. I am fixing now.

I have not used sirv in any code I touch or generate, so not sure where that issue is coming from.

@jthegedus
Copy link
Owner

If the require in your output does not include the TypeScript compiled dir (defaults to lib) then you may need to fix the require like so:

// functions/index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");

let svelteServer;
exports.svelteSSR = functions.https.onRequest(
	async (request, response) => {
		if (!svelteServer) {
			functions.logger.info("Initializing SvelteKit SSR Handler");
-			svelteServer = require("./my-site/handler").sveltekitServer;
+			svelteServer = require("../lib/my-site/handler").sveltekitServer;
			functions.logger.info("SvelteKit SSR Handler initialised!");
		}

		return svelteServer(request, response);
	}
);

Importantly, this tool doesn't modify anything in your setup, it just tries to put the compiled app where it needs to be in your Functions dir by reading the config of firebase.json and functions/package.json, so if you have customised those, then the example guides become harder to explain.

@jdgamble555
Copy link
Author

jdgamble555 commented Feb 7, 2021

I cannot get it to work with Typescript, but it works in Vanilla JS.

(You don't need to import firebase-admin, fwi)

Update - Problem

When running, I get:

Cannot read property 'hostingSite' of undefined

in (V.30) even when I only have one site. It says the problematic line is:

const ssrDirname = hostingSite != null ? hostingSite : 'sveltekit';
at adapter (C:\web projects\svelte-next-firebase\node_modules\svelte-adapter-firebase\src\index.js:132:3)

I also needed both of these for the firebase functions dependencies for anyone that comes across this:

  "@sveltejs/app-utils": "^1.0.0-next.0",
  "@sveltejs/kit": "^1.0.0-next.31",

@jthegedus
Copy link
Owner

jthegedus commented Feb 8, 2021

I cannot get it to work with Typescript, but it works in Vanilla JS.

Vanilla JS is the way I would recommend atm. I have created a ticket to indicate that TS is not working atm #8 and will track progress there. The short of it is, given SvelteKit already compiles your app, importing it from a TS CF may have that TS compile your app again. There's probably some config we can check for and warn the user that they need to add to get TS to ignore compilation, but that is another caveat that is Cloud Function specific. I recommend Cloud Run over Cloud Functions.


When running, I get:

Cannot read property 'hostingSite' of undefined
in (V.30) even when I only have one site. It says the problematic line is:

Can you share your svelte.config.cjs and package.json as I cannot reproduce this issues? 0.3.0 explicitely set hostingSite default value to null, so it shouldn't have a problem destructuring with a default value. What version of NodeJS are you using?


I also needed both of these for the firebase functions dependencies for anyone that comes across this:

Are you sure you need @sveltejs/kit? So we do need @sveltejs/kit, seems I didn't update the check to include this. The adapter itself performs a check for @sveltejs/app-utils and alerts if it is missing. The docs do mention this as caveats when compared to using Cloud Run which I recommend.

As package.json gains dependencies for your Svelte app you may need to copy some of these to functions/package.json depending on the server-side functionality and how SvelteKit bundles your dependencies.
This is a core reason for recommending Cloud Run for SSR as it's built & deployed separately from the rest of your Cloud Functions. This isolation enables dependency syncing etc.

@jthegedus
Copy link
Owner

I think I found why you may be having a terrible time with this. It seems there was a logging change, so most of the helpful parts of this tool are not logged when you run the adapter. (still does not explain your Cannot read property 'hostingSite' of undefined issue)

@jthegedus jthegedus changed the title deploy to firebase functions bug: issues deploying to Cloud Functions Feb 8, 2021
@jthegedus
Copy link
Owner

I fixed the logging issues in 0.3.1, please use that version when debugging your Cannot read property 'hostingSite' of undefined issue, thanks.

@jdgamble555
Copy link
Author

Hi, with version 0.3.1 I am still getting the error:

> Using svelte-adapter-firebase
> Cannot read property 'hostingSite' of undefined
TypeError: Cannot read property 'hostingSite' of undefined
    at adapter (C:\web projects\svelte-next-firebase\node_modules\svelte-adapter-firebase\src\index.js:134:3)
    at adapt (C:\web projects\svelte-next-firebase\node_modules\@sveltejs\kit\src\api\adapt\index.js:24:8)
    at C:\web projects\svelte-next-firebase\node_modules\@sveltejs\kit\src\cli.js:121:10

I am not using hostingSite or site as I do not have multiple sites...

@jdgamble555
Copy link
Author

Here is my project on github. I have not deployed to neither cloud functions nor cloud run. I am simply trying to get npm run adapt to compile, as I get the error above.

@jthegedus
Copy link
Owner

jthegedus commented Feb 8, 2021

Thanks for the link to your project. Your issue reproduces on my machine. I will try to resolve the issue this evening.

@jthegedus
Copy link
Owner

@jdgamble555 version 0.3.2 should hopefully resolve your issue. Now that the adapter logs properly you should find on a fresh project that it will guide you in all the issues you raised in this PR (exact code to add to your functions, required dependencies, or Cloud Run deploy command).

@jdgamble555
Copy link
Author

Thanks for looking at this. Progress, but No Go. Good to at least see a different error. I receive this error:

"hosting" does not contain at least one required match

Error with "firebase.json" config.
Expected Hosting config for site:
        "default" - did you mean to specify a specific site?
with config:
        "rewrites.*.source": "**"
for either a Function or Cloud Run service.

You can see I have hosting in my firebase.json.

I could be off here, but I believe the problem is that you are validating hosting to be an array if there is only one site, instead of an object. This line may need to be something like:

const firebaseSiteConfig = typeof firebaseConfig.hosting === 'object' ? firebaseConfig.hosting : ....

And this line should probably allow for an array or an object. I believe you could somehow use JOI.alternatives.try() for JOI.objects() or JOI.array(), although I am not very familiar with this package.

Again, I could be way off here...

@jthegedus
Copy link
Owner

jthegedus commented Feb 9, 2021

Your hosting config is incorrect. Rewrites is a nested field under a specific Hosting config, like this:

{
  "hosting": {
    "public": "static",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
+  "rewrites": [
+    {
+      "source": "**",
+      "function": "ssr"
+    }
+  ],
    "predeploy": ["npm run build", "npm run adapt"]
  },
-  "rewrites": [
-    {
-      "source": "**",
-      "function": "ssr"
-    }
-  ],
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ],
    "source": "functions"
  }
}

The error is saying that the default Hosting config (because there is only 1) does not have a rewrites entry that indicates an SSR rewrite via Functions or Cloud Run, which is correct because it has no rewrites at this time.

I could be off here, but I believe the problem is that you are validating hosting to be an array if there is only one site, instead of an object

I utilise a Joi feature to resolve this

// Joi.array.single converts the hosting field to an array if a single item is provided

@jdgamble555
Copy link
Author

And that fixed it. Don't know how I did that. Thanks!

Just side note: It would be cool if you created the firebase function automatically like you have here, but actually create the function when you run deploy. Angular universal does this.

Thanks!

@jthegedus
Copy link
Owner

And that fixed it. Don't know how I did that. Thanks!

Great!

It would be cool if you created the firebase function automatically

Given the history of people structuring their Functions every which way, I tried to reduce the restrictions and automation in favor of hints. The only requirement to make the log be quiet is that it finds a snippet of <functionName> =" in the index.js` output from the Functions dir.

I may look into an auto-generation option, but then I'd have to deal with find and replace on function renames etc. Since it is an event that isn't going to occur often I think this is a good balance for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants