Skip to content

Instantly share code, notes, and snippets.

@coehne
Last active May 23, 2024 14:26
Show Gist options
  • Save coehne/caf0b3934455d842dfbfe1f4c1544348 to your computer and use it in GitHub Desktop.
Save coehne/caf0b3934455d842dfbfe1f4c1544348 to your computer and use it in GitHub Desktop.
Host SvelteKit on Firebase Hosting with Framework Aware Hosting

SvelteKit + Firebase Hosting

These are instructions for setting up a SvelteKit demo project and deploying it to Firebase with framework aware hosting.

Installation steps

Setup SvelteKit

Setup a new SvelteKit project with:

npm create svelte@latest my-app

Use the assistant to configure your desired SvelteKit setup and run npm install afterwards.

Prepare Firebase CLI

Enable the web framework feature in the Firebase CLI with:

firebase experiments:enable webframeworks

Initialize Firebase hosting

Initialize the Firebase hosting with:

firebase init hosting

Follow the steps in the assistant to connect to an existing Firebase project or create a new one. Make sure the Blaze plan of Firebase is enabled for the project.

Configuring the cloud function

You can configure the the cloud function in the frameworksBackend object of your firebase.json file. It should be analog the the regular onRequest cloud function configuration.

A sample firebase.json configuration could look like:

{
	"hosting": {
		"source": ".",
		"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
		"frameworksBackend": {
			"region": "europe-west1",
			"invoker": "public"
		}
	}
}

Note: If you want to reduce the start-up time, you could also add "minInstances": 1 to the configuration. This will keep the cloud function warm. But be aware that this will cost you extra money.

Developing

Serve the app locally with:

firebase serve

or

firebase emulators:start

It will reflect your code changes. However, I still needed to manually reload the page in the browser to see the changes.

Deploying

I used the default auto adapter of SvelteKit which will be a bit lost in detecting a supported production environment. Nonetheless, deploying still worked for me.

Just run the firebase deploy command:

firebase deploy

It will try to enable all needed APIs for you which might take a while. Hence, there is a possibility that the first or even second deployment will fail. It might also throw an error like:

Ensure that the Cloud Functions service account has 'artifactregistry.repositories.list' and 'artifactregistry.repositories.get' permissions. You can add the permissions by granting the role 'roles/artifactregistry.reader'.

Just chill a bit and re-run the command. It should work after a few minutes since Firebase will take care of it in the background.

The deployment should now be successful!

Troubleshooting

I still got the following error when opening the URL of the deployed app:

Error: Forbidden
Your client does not have permission to get URL / from this server.

This is due to a missing permission to invoke the deployed function publicly. I did not test it but I think you can use the invoker property on the cloud function directly and set it to public. I only figured that out after I fixed it with the following command:

gcloud functions add-invoker-policy-binding functionName \ # Change this to your generated function name
      --region="europe-west1" \ # Change this to your region
      --member="allUsers" \
      --project="projectId" # Change this to your project id

Afterwards, the app should be accessible via the URL shown in the Firebase CLI output.

Terraform

If you use Terraform for your GCP setup, you might find it helpful to know that the deploy command will enable the following Google APIs: - cloudfunctions.googleapis.com - cloudbuild.googleapis.com - artifactregistry.googleapis.com

The cloud functions service account will also need the role roles/artifactregistry.reader.

Resources

@thortek
Copy link

thortek commented Jun 28, 2023

Thanks for posting this! I've been able to get a sample SvelteKit app deployed with Firebase hosting pretty much doing what you have described. But I haven't been able to figure out how to get my .env variables to work. Using $env/static/private as per the official SvelteKit docs does not appear to work. Have you tried to get any api keys or secrets working within your SvelteKit app deployed on Hosting?

@coehne
Copy link
Author

coehne commented Jun 29, 2023

Unfortunately not. I want to have a second look into that as well. I still also don't know if there might be a different way to provide the SveltKit backend in the cloud function with env/secret variables Docs and the frontend part via hosting. Probably in the .firebase dir which will be created on first deploy. But still don't know how and if the emulator will pick them up during dev.

Let me know if you figure something out, I will update the Gist as soon as I have new information about env/secret variables.

@thortek
Copy link

thortek commented Jun 29, 2023 via email

@gamcoh
Copy link

gamcoh commented Jul 4, 2023

Thank you for this post!

Unfortunately I couldn't manage to get it to work, even after following everything you posted, even after doing the bit from @thortek .

The web page displays a Internal server error, and I don't seem to find logs of that in google cloud (https://berouchim-habaim.web.app/).
Here's what I found:

TypeError: Cannot read properties of undefined (reading 'prerendering')
    at respond (file:///workspace/index.js:2175:14)
    at Server.respond (file:///workspace/index.js:2504:12)
    at handle (file:///workspace/node_modules/firebase-frameworks/dist/sveltekit/index.js:13:43)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

I thought maybe it was because I have a server file that uses some env with $env/static/private but even after modifying it to use the process.env it didn't work.

@royce-mathew
Copy link

This is how i've set up my Github workflow file to automatically use the environment variables from the secrets that I give it:

name: Deploy to Firebase Hosting on merge
'on':
  push:
    branches:
      - master
jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18]
    env: # Put your .env variables here
      TEST_VARIABLE: ${{ secrets.TEST_VARIABLE }}
      TEST_VARIABLE2: ${{ secrets.TEST_VARIABLE2 }}
    steps:
      - uses: actions/checkout@v3

      - uses: pnpm/action-setup@v2
        with:
          version: 8

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install

      - name: Deploy To Firebase
        uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_TEST }}'
          channelId: live
          projectId: test-id
        env:
          FIREBASE_CLI_EXPERIMENTS: webframeworks

@sebmade
Copy link

sebmade commented Nov 12, 2023

seems not managing the getClientAddress() function implemented in event (hooks -> handle -> event)
i've just patch @jthegedus/svelte-adapter-firebase on this specific implementation
this function is useful for example with Stripe when you manage payment with confirmation on server

@DomDumont
Copy link

Hi,
I got this error, even if I do not plan to use functions : Error: Your project budflash-cdd8b must be on the Blaze (pay-as-you-go) plan to complete this command. Required API cloudbuild.googleapis.com can't be enabled until the upgrade is complete. To upgrade, visit the following URL:

@royce-mathew
Copy link

You need to enable to Blaze plan on Firebase to be using the Firebase experimental hosting features.

@nicholasstephan
Copy link

Is there any official documentation on this? The Firebase Frameworks Hosting docs only talk about angular, next.js, and flutter.

@thortek
Copy link

thortek commented May 15, 2024 via email

@anhtuank7c
Copy link

I am not able to build and deploy with CI/CD workflow yet but manual deploy with firebase deploy work for me.
So I will stick with this method for a while, will fix CI/CD later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment