Git Product home page Git Product logo

jthegedus / svelte-adapter-firebase Goto Github PK

View Code? Open in Web Editor NEW
284.0 21.0 34.0 1.72 MB

SvelteKit adapter for Firebase Hosting rewrites to Cloud Functions for a Svelte SSR experience

Home Page: https://github.com/jthegedus/svelte-adapter-firebase

License: MIT License

JavaScript 83.84% Shell 16.16%
svelte sveltekit firebase ssr serverless cloud-functions sveltekit-adapter svelte-adapter cloud-run

svelte-adapter-firebase's Introduction

⚠️ WARNING: Firebase have introduced first-party support for Web Frameworks. SvelteKit support is experimental. This adapter may be deprecated in future as it cannot support the same level of integration as the official team and tooling. Use at your own risk.

SvelteKit adapter Firebase social preview

svelte-adapter-firebase

GitHub Release npm Tests CodeQL

Firebase adapter for SvelteKit.

Utilise the Firebase Hosting CDN with dynamic content served by SvelteKit on Cloud Functions!

✔️ SSR on Cloud Functions
✔️ Integrates with existing Cloud Functions!
✔️ Local production testing with Firebase Emulator
✔️ Mitigate cold-starts with minInstances
✔️ Multiple Hosting Sites

Contents

Setup

The adapter reads firebase.json to determine output dirs for Server scripts & Static assets, without this file the adapter cannot know how your Firebase app is configured. Hosting & Cloud Functions are required.

In your standard SvelteKit project:

  • npm install --save-dev svelte-adapter-firebase
  • add adapter to svelte.config.js:
+import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
+   adapter: firebase(),
  },
};
  • Setup firebase.json with firebase init.
  • npm run build. Read and repeat, the output is meant as a guide. IE: after your first build, you need to manually add the produced Cloud Function in index.js

Beta Adapter Version Compatibility

This adapter has not been tested beyond the versions listed below, use at your own risk:

Adapter Version SvelteKit Version
0.15.0 1.1.1
0.14.5 1.0.0-next.587
0.14.4 1.0.0-next.443
0.14.3 1.0.0-next.443
0.14.2 1.0.0-next.405
0.14.0 1.0.0-next.330
0.13.1 1.0.0-next.180
0.13.0 1.0.0-next.168
0.12.x 1.0.0-next.165
0.11.x 1.0.0-next.155
NA 1.0.0-next.152-154
0.10.x 1.0.0-next.132
0.9.1 1.0.0-next.122
0.9.0 1.0.0-next.120
0.8.x 1.0.0-next.111
NA 1.0.0-next.109-110
0.7.x 1.0.0-next.107
0.6.x 1.0.0-next.103
0.5.x 1.0.0-next.54
0.4.x 1.0.0-next.46
0.3.x 1.0.0-next.27

Note: only the versions listed have been tested together, if others happen to work, it is just coincidence. This is beta software after all.

Configuration Overview

Adapter options:

  • esbuildBuildOptions
    • function to return an esbuild.BuildOptions object
    • default: see defaultOptions object in src/index.js
  • firebaseJsonPath
    • path to your firebase.json file, relative from where svelte build is called
    • default: ./firebase.json
  • target
    • required when firebase.json:hosting is an array (contains many site configurations)
    • default: undefined
  • sourceRewriteMatch

Adapter output:

  • static assets (images, CSS, Client-side JavaScript) of your SvelteKit app output to the directory defined by firebase.json:hosting.public
  • server assets (SSR JavaScript) output alongside your Cloud Functions defined by firebase.json:functions.source

Details

Setup outlines the steps most commonly used with a single SvelteKit app. Here we go into the details of each configuration and how it interacts with the firebase.json config.

The 3 step process is:

  1. select Hosting config from firebase.json. If more than one site present in config, match svelte.config.js:target field with either firebase.json:hosting[].site or .target fields.
  2. output static assets to the directory in the public field
  3. identify the rewrite rule for SSR to determine Cloud Function output. The rewrite rule is determined by a lookup of the rewrites.source against sourceRewriteMatch

firebase.json Configurations

Due to the relaxed rules of firebase.json we can have many valid configs. At a minimum, one or more Hosting sites is required with an associated Functions config if a Cloud Function rewrite is used. These are the combintations:

single Hosting site with Cloud Function rewrite
{
  "hosting": {
    "public": "<someDir>",
    "rewrites": [
      {
        "source": "**",
        "function": "<functionName>"
      }
    ]
  },
  "functions": {
    "source": "<anotherDir>"
  }
}
multiple Hosting site with Cloud Function rewrite
{
  "hosting": [
    {
      "site": "blog",
      "public": "<someDir>",
      "rewrites": [
        {
          "source": "**",
          "function": "<functionName>"
        }
      ]
    },
    {
      // another site config
    }
  ],
  "functions": {
    "source": "<anotherDir>"
  }
}

To correctly lookup the blog site, target will need to be set in svelte.config.js:

import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
    adapter: firebase({ target: "blog" }),
  },
};

Adapter Configurations

Detailed examples of the adapter configuration options.

All options:

import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
    adapter: firebase({
      esbuildBuildOptions: (defaultOptions: BuildOptions) => Promise<BuildOptions> | BuildOptions,
      firebaseJsonPath: "",
      target: "svelte-func-single-site",
      sourceRewriteMatch: "",
    }),
  },
};
esbuildBuildOptions

As an escape hatch, you may optionally specify a function which will receive the final esbuild options generated by this adapter and returns a modified esbuild configuration. The result of this function will be passed as-is to esbuild. The function can be async.

For example, you may wish to add plugins, or configure the format to bundle to ESM (defaults to CJS):

import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
    adapter: firebase({
      target: "svelte-func-single-site",
      esbuildBuildOptions(defaultOptions) {
        return {
          ...defaultOptions,
          target: "esm"
          plugins: [],
        };
      },
    })
  },
};

The default options for this version are as follows:

{
	entryPoints: ['.svelte-kit/firebase/handler.js'],
	outfile: `pathToOutputDir/index.js`,
	bundle: true,
	inject: ['pathTo/shims.js'],
	platform: 'node',
  target: `node${functionRuntimeVersion}`
}

where esbuild target is computed from the Node.js runtime version defined for your Cloud Functions.

firebaseJsonPath

If the firebase.json file is not in the directory you run svelte build, then you can set a relative path in svelte.config.js:

.gitignore
firebase.json
app/                    <-- svelte build run in this dir
	package.json
	svelte.config.js
	src/
anotherApp/
	index.html
	index.css
functions/
	package.json
	index.js
import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
    adapter: firebase({
      target: "svelte-func-single-site",
      firebaseJsonPath: "../firebase.json",
    }),
  },
};
target

If firebase.json:hosting is an array of sites, then each hosting config must list a site or target field that matches the adatper's target option. For example:

// firebase.json
{
  "hosting": [
    {
      "site": "blog",
      // or
      // "target": "blog",
      "public": "<someDir>",
      "rewrites": [
        {
          "source": "**",
          "run": {
            "serviceId": "<cloudRunServiceId>"
          }
        }
      ]
    },
    {
      "site": "adminPanel",
      // or
      // "target": "adminPanel",
      "public": "<anotherDir>"
    }
  ]
}
import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
    adapter: firebase({ target: "blog" }),
    target: "#svelte",
  },
};

The Firebase config & adapter config match (firebase.json:hosting[0].site === adapter target), so therefore we know which Firebase Hosting site you want to build the SvelteKit site for.

sourceRewriteMatch

If the rewrite source pattern is not **, then svelte.config.js sourceRewriteMatch will need to be set to match your desired rewrite rule. For example:

// firebase.json
{
  "hosting": {
    "public": "<someDir>",
    "rewrites": [
      {
        "source": "/blog/**",
        "run": {
          "serviceId": "<cloudRunServiceId>"
        }
      }
    ]
  }
}
import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
    adapter: firebase({ sourceRewriteMatch: "/blog/**" }),
    target: "#svelte",
  },
};

How it works

Given

  • the following firebase.json configuration
  • a standard SvelteKit app structure
  • the default svelte-adapter-firebase config
// firebase.json
{
  "hosting": {
    "public": "myApp",
    "rewrites": [
      {
        "source": "**",
        "function": "ssrServer"
      }
    ],
    "predeploy": ["npm run build"]
  },
  "functions": {
    "source": "functions"
  }
}

the following Server & Static assets dirs are created:

firebase.json ("public": "myApp")
package.json
svelte.config.js
src/
	app.html
	routes/
		index.svelte
functions/
	package.json ("main": "index.js")
	index.js
	sveltekit/		<-- Server Assets dir (code to be imported to you Cloud Function)
myApp/				<-- Static Assets to go to Firebase Hosting CDN
  • firebase.json:functions.source dir is used to find functions/package.json whose main field is used to find the Cloud Function build dir. This is used as the server asset output dir.
TypeScript Cloud Functions

Because we use the above method to determine the output dir, the server assets are output to the correct place when using TypeScript.

firebase.json ("public": "myApp")
package.json
svelte.config.js
src/
  app.html
  routes/
    index.svelte
functions/
  package.json ("main": "lib/index.js")
  index.ts
  lib/
    index.js
    sveltekit/	<-- Server assets output to functions/lib
myApp/				<-- Static assets to go to Firebase Hosting CDN
Output with Multiple Sites

In a multi-site setup, the site or target field from hosting config in firebase.json is used as the server output dir:

firebase.json ("site": "myCoolSite","public": "myApp")
package.json
svelte.config.js
src/
	app.html
	routes/
		index.svelte
functions/
	package.json
	index.js
	myCoolSite/		<-- Server assets
myApp/				<-- Static assets to go to Firebase Hosting CDN

The final piece is to write the actual Cloud Function source code to reference the output server assets. The code is printed during svelte build and should be placed in your index.js or index.ts manually.

This is a flexible solution that allows integrating with other Cloud Functions in your project. You can edit the provided code as you see fit. The import/require of the generated code will not change unless you change the firebase.json:hosting.site or package.json:main fields, so you shouldn't need to update this code after adding it.

Firebase Emulator local Testing

Test your production build locally before pushing to git or deploying!

  • build your app: svelte-kit build
  • install Function dependencies: pnpm install --prefix functions
  • start the emulator: firebase emulators:start

Deployment

firebase deploy 🎉

Caveats

  • Using firebase.json:hosting[].site is preferred to firebase.json:hosting[].target as Firebase Deploy Targets only supports Hosting, Storage & Databases and not Functions. This means you can use Deploy targets target field to identify your site for the adapter to build, but you CANNOT use Deploy Targes when deploying as you need to deploy the Hosting & Functions at the same time for this solution to work as expected.
  • Firebase Hosting Preview Channels currently lacks first-party support for SSR applications. This adapter doesn't attempt to remedy this issue and doesn't produce a different SSR Function for preview channel deployments.
  • ⚠️ Cloud Function rewrites only support us-central1, other regions will error. The official warning about this can be found in these docs.

Non-goals

Write Cloud Function code directly into .js file instead of printing in console.

Firebase Cloud Functions have a long history of people configuring their index files completely differently, some even generating them from directories. Accommodating these would be a headache. Instead, all we look for is a match against this string, ${name} =, where name is your Cloud Functions name. We may make this configurable to a specific file in future.

Additionally, this allows for users to customise their Firebase Cloud Function API like runWith() options for memory/CPU, min/max Instances and VPC/Ingress/Egress configuration settings, without complex support for options in the adapter. This keeps the Function config where it should, close to the userland code.

Handle the deployment of the app to Firebase.

Firebase apps consist of many different services with the CLI providing optional deployments. We do not want to dictate full deployments with your frontend nor perform partial deployments if it does not fit your app. The only option then is to leave it to you 🎉

FAQ

Why is the Cloud Function code output to the terminal for me to add manually instead of being written to functions/index.js?

See non-goals Write Cloud Function code directly into .js file instead of printing in console.

Firebase libs in SvelteKit

As recommended in the SvelteKit FAQ, please use Firebase JS SDK v9 as the older version of the SDK has issues and a larger bundle size.

Cold Starts

Since the purpose of using this adapter is to leverage the Firebase Hosting CDN, you should consider improving the user experience with targetted caching/TTLs.

If cold start are still an issue for your application, Cloud Functions has support for minInstances which will keep X number of instances warm. From the docs:

A minimum number of instances kept running incur billing costs at idle rates. Typically, to keep one idle function instance warm costs less than $6.00 a month. The Firebase CLI provides a cost estimate at deployment time for functions with reserved minimum instances. Refer to Cloud Functions Pricing to calculate costs.

-Firebase docs

To implement this, configure your runWith options like so:

const myRuntimeOptions = {
	memory: "1GB",
+	minInstances: 1,
}
exports.myFunc = functions.runWith(myRuntimeOptions).https.onRequest(async (request, response) => {
	...
});

Note: this is still single concurrency (if an instance does not exist to handle a request when it hits the backend a new Function instance is created). Watch this space!

  • 1.0.0 will not be published until the SvelteKit Adapter API is declared stable and SvelteKit is released for general use.

Contributing

Contributions of any kind welcome, just follow the guidelines!

Short version:

git clone https://github.com/jthegedus/svelte-adapter-firebase.git
asdf install
pnpm i

See asdf to install set it up.

external contributions

While building this adapter some issues were found with upstream components, these are captured here should someone wish to contribute them:

  • Cloud Function validation code linked in utils.js is from two different sources which indicates that it is being validated by firebase-tools in two separate places. PR a fix there.

svelte-adapter-firebase's People

Contributors

andrewlester avatar co3k avatar daylilyfield avatar github-actions[bot] avatar jthegedus avatar kleber-swf avatar koheing avatar nielsvandermolen avatar nushio avatar pham avatar quantuminformation avatar sebmade avatar semantic-release-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svelte-adapter-firebase's Issues

test: integration scenarios

Is your feature request related to a problem? Please describe.

Currently the CICD pipeline for integration tests only caters to two examples, though we have many more usage scenarios.

Describe the solution you'd like

Include more examples

Describe alternatives you've considered

Additional context

Module not installable with npm

Describe the bug
Current version 0.6.1 is not installable with npm. When I use pnpm it works. However the container does not build on CloudRun because it also has this problem.

To Reproduce

  1. Initialize svelte kit demo app
  2. Add "svelte-adapter-firebase": "^0.6.1" as devDependency in package.json
  3. run npm i
  4. See error

Expected behavior
npm install should work and container should build on CloudRun

Screenshots
image
image

"self" is not defined when trying to use getfunctions/httpscallable API from firebase

Describe the bug
Well I don't if it's a bug or if I'm doing something wrong, but I keep getting all these crazy errors and build fails when I try to use/import firebase functions from any client side script. I have a multitude of Firebase Functions (besides the svelte kit one) that I'd like to utilize, but I have no idea how, any help would be greatly appreciated.

To Reproduce
Steps to reproduce the behavior:

  1. Add import { getFunctions, httpsCallable } from 'firebase/functions'; to any client side script (even firebase/compat/functions gave the same following errors)
  2. Run npm run build
  3. See error
    Expected behavior
    A build success message and the ability to use firebase's httpscallable API on some client rendered scripts, like for signup/login

Screenshots

Additional context
Error message below:
Adapter configuration:
{"firebaseJson":"firebase.json","sourceRewriteMatch":"**"}
Writing Cloud Function server assets to:
functions/sveltekit
Erasing static asset dir before processing:
public
Writing client application to:
public
Prerendering static pages to:
public

self is not defined
ReferenceError: self is not defined
at file:///Users/jd/Documents/github/svelte-adapter-firebase_example/.svelte-kit/output/server/app.js:13520:30
at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
at async Loader.import (node:internal/modules/esm/loader:178:24)
at async prerender (file:///Users/jd/Documents/github/svelte-adapter-firebase_example/node_modules/.pnpm/@sveltejs[email protected][email protected]/node_modules/@sveltejs/kit/dist/chunks/index7.js:80:14)
at async Object.prerender (file:///Users/jd/Documents/github/svelte-adapter-firebase_example/node_modules/.pnpm/@sveltejs[email protected][email protected]/node_modules/@sveltejs/kit/dist/chunks/index7.js:312:5)
at async adapt (file:///Users/jd/Documents/github/svelte-adapter-firebase_example/node_modules/.pnpm/svelte-adapter-firebase@0.8.4_@sveltejs[email protected]/node_modules/svelte-adapter-firebase/src/index.js:51:4)
at async adapt (file:///Users/jd/Documents/github/svelte-adapter-firebase_example/node_modules/.pnpm/@sveltejs[email protected][email protected]/node_modules/@sveltejs/kit/dist/chunks/index7.js:338:2)
at async file:///Users/jd/Documents/github/svelte-adapter-firebase_example/node_modules/.pnpm/@sveltejs[email protected][email protected]/node_modules/@sveltejs/kit/dist/cli.js:656:5

Semantic Release GitHub asset config

Describe the bug

Semantic Release is uploading the whole repo to GitHub releases instead of just the required adapter files

Expected behavior

Only the required set of files should be uploaded.

Only file and data URLs are supported by the default ESM loader.

I'm having trouble running "npm run build" on my Windows.

How do I solve this?

Just testing "svelte-adapter-firebase/examples/functions_single_site /".

Only file and data URLs are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'p:'
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only file and data URLs are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'p:'
at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:782:11)
at Loader.resolve (internal/modules/esm/loader.js:86:40)
at Loader.getModuleJob (internal/modules/esm/loader.js:230:28)
at Loader.import (internal/modules/esm/loader.js:165:28)
at importModuleDynamically (internal/modules/esm/translators.js:114:35)
at exports.importModuleDynamicallyCallback (internal/process/esm_loader.js:30:14)
at adapt (file:///P:/LEFRANK/kit-firebase/node_modules/svelte-adapter-firebase/src/index.js:28:43)
at adapt (file:///P:/LEFRANK/kit-firebase/node_modules/@sveltejs/kit/dist/chunks/index5.js:322:8)
at file:///P:/LEFRANK/kit-firebase/node_modules/@sveltejs/kit/dist/cli.js:616:11

Undefined bugs

Describe the bug

I'm getting errors during firebase deploy, with latest version:

> Using svelte-adapter-firebase
> Cannot read property 'minor' of undefined
TypeError: Cannot read property 'minor' of undefined
    at adapt (file:///workspaces/my-app2/node_modules/svelte-adapter-firebase/src/index.js:30:14)

Then I downgraded to 0.7.6 which is prior to this to fix it and now I get:

> Using svelte-adapter-firebase
> utils.rimraf is not a function
TypeError: utils.rimraf is not a function
    at prepareEntrypoint (file:///workspaces/my-app2/node_modules/svelte-adapter-firebase/src/index.js:164:8)

I'm clearly doing something wrong, but not sure what...?

Package.json repo details

Is your feature request related to a problem? Please describe.

The package does not have links to this repo or keywords so discovery is bad when searching these platforms. This is visible within npmjs - https://www.npmjs.com/package/svelte-adapter-firebase

Describe the solution you'd like

Add:

  • keywords
  • repo details
  • bug report details

Describe alternatives you've considered

Additional context

Failing tests

Describe the bug

Tests are failing due to

Uncaught exception in tests/index.test.js

/home/jthegedus/projects/svelte-adapter-firebase/src/index.js:7
import {copy} from '@sveltejs/app-utils/files';
^^^^^^

SyntaxError: Cannot use import statement outside a module

To resolve this, we should correctly label our index file as a module, re-jig the microbundle compilation to ensure the correct packages are inlined, etc.

ci: run workflows once on each PR

Is your feature request related to a problem? Please describe.

Workflows run twice on each commit to a PR; push and pull_request.

Describe the solution you'd like

Run workflows once per commit on PRs.

Describe alternatives you've considered

Additional context

Svelte App in subdirectory

Describe the bug
The functions folder is not correctly resolved relative to firebase.json, when the Svelte app is placed in a subdirectory.

> ENOENT: no such file or directory, open 'functions/package.json'

The example in the README does not work.
https://github.com/jthegedus/svelte-adapter-firebase/blob/main/README.md#adapter-configurations

To Reproduce

  1. Place the Svelte Kit application in subfolder, e.g. svelte_app.
  2. Configure Svelte adapter adapter: firebaseAdapter({ firebaseJson: "../firebase.json" }),

Expected behavior
package.json should be looked for at ../functions/package.json instead of functions/package.json.

Error adding adapter: Malformed svelte.config.js SyntaxError: Unexpected token '.'

Describe the bug

When I add the line import firebase from "svelte-adapter-firebase"; I get the following error:

Malformed svelte.config.js
SyntaxError: Unexpected token '.'
    at Loader.moduleStrategy (internal/modules/esm/translators.js:140:18)

To Reproduce

$ npm init svelte@next sveltekit-firebase-test

In package.json fix the @sveltejs/kit version

  "devDependencies": {
    "@sveltejs/kit": "1.0.0-next.107",
$ npm install

$ firebase init

$ npm install --save-dev svelte-adapter-firebase

Add the line

import firebase from "svelte-adapter-firebase";

at the beginning of svelte.config.js

run npm run build

$ npm run build

> [email protected] build /home/sas/devel/apps/glas-it/apps/keyosk/tmp/sveltekit-firebase-test
> svelte-kit build

Malformed svelte.config.js
SyntaxError: Unexpected token '.'
    at Loader.moduleStrategy (internal/modules/esm/translators.js:140:18)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `svelte-kit build`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/sas/.npm/_logs/2021-05-25T20_59_11_043Z-debug.log

Expected behavior

The build to run ok

Additional context

package.json

{
  "name": "~TODO~",
  "version": "0.0.1",
  "scripts": {
    "dev": "svelte-kit dev",
    "build": "svelte-kit build",
    "preview": "svelte-kit preview"
  },
  "devDependencies": {
    "@sveltejs/kit": "1.0.0-next.107",
    "svelte": "^3.34.0",
    "svelte-adapter-firebase": "^0.7.7"
  },
  "type": "module",
  "dependencies": {
    "@fontsource/fira-mono": "^4.2.2",
    "@lukeed/uuid": "^2.0.0",
    "cookie": "^0.4.1"
  }
}
$ node --version
v12.22.1

$ npm --version
6.14.12

Note: there's a github repo with the example producing the above erro at https://github.com/opensas/sveltekit-firebase-adapter-error

Cannot destructure property 'hostingSite' of 'undefined' as it is undefined.

Describe the bug

For my version of node v14.15.4 I get an error when running svelte-kit adapt:

Cannot destructure property 'hostingSite' of 'undefined' as it is undefined.

I was able to work around this by destructuring later on:

async function adapter(builder, params = {}) {

  const {
    hostingSite = null,
    sourceRewriteMatch = '**',
    firebaseJson = 'firebase.json',
    cloudRunBuildDir = null
  } = params;

After the above it looks like adapt works correctly.

docs: explain/examples of Firebase Admin/Client SDKs in SvelteKit

Is your feature request related to a problem? Please describe.

The use of the Firebase Client SDK and Firebase Admin SDK is confusing for a lot of people.

Describe the solution you'd like

Explain the difference between the SDKs and when/how they should be used in the SvelteKit lifecycle.

Describe alternatives you've considered

Additional context

Related #100

docs: include image of architecture design

Is your feature request related to a problem? Please describe.

To better express some of the file shuffling and the architecture of the deployment, include some images.

Describe the solution you'd like

Describe alternatives you've considered

Additional context

docs: TypeScript Support & Example

Describe the bug

TypeScript may cause issues because our SvelteKit app is already built when the build output lands in functions/lib/<site name>/.

How should this be recommended to users? If they include the compiled relative import in the uncompiled TS then the app may attempt to be recompiled by the TS compilation of the functions, which we do not want 🤔

EG:

// functions/src/index.ts
svelteKit = require("../lib/<site name>/handler").sveltekitServer;` 

This relative dir will be correct in the compiled code in functions/lib/index.js, but if the SvelteKit code is also passed through the TS compiler then we may have issues.

Cannot make the SvelteKit default demo application to run on firebase: timeout when POSTing a new todo

Describe the bug

After creating a new SvelteKit project with the default demo app, intialized and firebase (firebase init) and installed the svelte-adapter-firebase, the ssrServer functions dies with a timeout error on the logs.

To Reproduce

Create a new SvelteKit Application,

npm init svelte@next adapter-error`
cd adapter-error
npm install

Choose SvelteKit demo app and leave all the other options by default

Go to firebase console and create a new project (https://console.firebase.google.com/), unselect google analytics

Add a web app adapter-error-app

Install firebase-tools

npm install -g [email protected]

Got a nasty error using the lastest version: [email protected]

firebase init

choose functions and hosting

use an existing project, and choose the one you created before

accept all options by default

Note: check that the node version in function/package.json is 14

install the adapter:

npm install --save-dev svelte-adapter-firebase

update svelte.config.js

import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
    adapter: firebase(),
    target: "#svelte",
  },
};

update package.json

	"scripts": {
		"dev": "svelte-kit dev",
		"build": "npx rimraf myApp && svelte-kit build --verbose"
  }

update firebase.json

{
  "hosting": {
    "public": "myApp",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "function": "ssrServer"
      }
    ],
    "predeploy": ["npm run build"]
  },
  "functions": {
    "source": "functions"
  }
}

Deploy your app

firebase deploy

Follow the message on the terminal and add the following code to functions/index.js

  let ssrServerServer;
  exports.ssrServer = functions.https.onRequest(async (request, response) => {
        if (!ssrServerServer) {
                functions.logger.info("Initializing SvelteKit SSR Handler");
                ssrServerServer = require("./ssrServer/index").default;
                functions.logger.info("SvelteKit SSR Handler initialised!");
        }
        functions.logger.info("Requested resource: " + request.originalUrl);
        return ssrServerServer(request, response);
  });

Remember to change your plan to Blaze (pay-as-you-go)

Deploy your app

firebase deploy

Visit your app and try to post a new todo

The todo will not be added

If you check the logs from the google cloud console for the ssrServer function you'll see a time out

2021-05-26T23:43:25.085548695Z
ssrServerl9woaz02tpei Function execution took 60003 ms, finished with status: 'timeout'
Function execution took 60003 ms, finished with status: 'timeout'

image

If you try it locally with firebase serve you'll get the same error with more detailed information in the terminal

image

I tried allocating 1GB of memory but the error persists

Expected behavior

The demo app should work fine, the post should be processed without errors

Container crashes on cloud run

Container crashes on cloud run

To Reproduce

  • Use SvelteKit v1.0.0-next.94 and the current version of svelte-adapter-firebase.
  • Build the SvelteKit demo app with firebase adapter (for cloud run)
  • Deploy the demo app to cloud run with gcloud beta run deploy mysitessr --platform managed --region us-central1 --source .mysitessr --allow-unauthenticated
  • Goto /todos on the deployed app -> 500 error in the client and Cannot find package '@sveltejs/kit' imported from /workspace/app.mjs in the cloud run logs (detailed logs in the screenshot below)

This was also reproducible with other projects than the demo app. There the Cannot find package '@sveltejs/kit' imported from /workspace/app.mjs was returned back to the client.

Expected behavior
Container should work and not crash

Screenshots
image

docs: faq explanations are giving an impression of incompleteness

Describe the bug

The FAQ about "Firebase libs in SvelteKit routes" gives the wrong impressions.

  • it should be clear about using v9 SDK in the same way as the SvelteKit FAQ
  • it should not say the SvelteKit endpoints are not supported, because they are

Other FAQ improvements:

Non-goals improvements:

- this adapter (consider the cost/benefit).
+ this adapter (consider the cost/benefit to implement this feature well)

To Reproduce

Expected behavior

For the docs to be useful and not cause confusion
Screenshots

Additional context

SvelteKit as peerDep

Is your feature request related to a problem? Please describe.

SvelteKit did this - sveltejs/kit#1505

Not sure if required here or an optimisation for the first-party adapters (Vercel).

Describe the solution you'd like

Describe alternatives you've considered

Additional context

Cloud Run Deployment not working if Svelte Kit package.json dependencies are empty.

Describe the bug
A new SvelteKit projects package.json file does not have a dependency field.
Using the adapter fails in these cases:

> Cannot set property '@google-cloud/functions-framework' of undefined
TypeError: Cannot set property '@google-cloud/functions-framework' of undefined
    at adaptToCloudRun (/Users/lschmierer/Receipe App/svelte_firebase_demo/svelte_app/node_modules/svelte-adapter-firebase/dist/cli.js:289:60)
    at adapt (/Users/lschmierer/Receipe App/svelte_firebase_demo/svelte_app/node_modules/svelte-adapter-firebase/dist/cli.js:197:5)
    at adapt (file:///Users/lschmierer/Receipe%20App/svelte_firebase_demo/svelte_app/node_modules/@sveltejs/kit/dist/chunks/index5.js:765:8)
    at file:///Users/lschmierer/Receipe%20App/svelte_firebase_demo/svelte_app/node_modules/@sveltejs/kit/dist/cli.js:598:11

I get " ExperimentalWarning" on first build

Hello

I found this amazing adapter, after 3 hours lost on trying doing it manually.

So I installed this adapter according to the docs. But when I tried building it, I got this error:

> npx -y rimraf build && svelte-kit build --verbose

(node:584860) ExperimentalWarning: The ESM module loader is experimental.
Malformed svelte.config.js
SyntaxError: Unexpected token '.'
    at Loader.moduleStrategy (internal/modules/esm/translators.js:88:18)

Process finished with exit code 1

I tried to tinker around with configuration, but nothing fixed that error.

svelte.config.js

import preprocess from 'svelte-preprocess';
import adapter from 'svelte-adapter-firebase';
//import adapter from '@sveltejs/adapter-node';
//import adapter from '@sveltejs/adapter-static';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://github.com/sveltejs/svelte-preprocess
	// for more information about preprocessors
	preprocess: preprocess(),

	kit: {
		// hydrate the <div id="svelte"> element in src/app.html
		target: '#svelte',
		ssr: true,
		files: {
			assets: 'static'
		},
		adapter: adapter({
			firebaseJson: './firebase.json',
			cloudRunBuildDir: 'build'
		})
	}
};

export default config:

just standard config file

firebase.json

{
  "hosting": {
    "public": "static",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
  "rewrites": [
      {
        "source": "**",
        "function": "ssr"
      }
    ]
  },
  "functions": {
    "source": "build",
    "runtime": "nodejs14"
  }
}

package.json

{
  "name": "FIMTradeSolutions",
  "main": "functions.js",
  "version": "0.0.1",
  "scripts": {
    "dev": "svelte-kit dev",
    "build:classic": "svelte-kit build",
    "preview": "svelte-kit preview",
    "build": "npx -y rimraf build && svelte-kit build --verbose"
  },
  "devDependencies": {
    "@sveltejs/adapter-node": "^1.0.0-next.20",
    "@sveltejs/adapter-static": "^1.0.0-next.9",
    "@sveltejs/kit": "next",
    "bootstrap": "^5.0.0",
    "firebase-functions": "^3.13.2",
    "node-sass": "^6.0.0",
    "sass": "^1.32.12",
    "svelte": "^3.34.0",
    "svelte-adapter-firebase": "^0.6.5",
    "svelte-preprocess": "^4.0.0",
    "sveltestrap": "^4.2.1",
    "tslib": "^2.0.0",
    "typescript": "^4.0.0"
  },
  "type": "module"
}

Project files

Project files

Conclusion

Building process usually works, when I tried replacing this adapter for node, it fixed the problem (but I can't deploy it to firebase, because ESM doesn't run on cloud functions).

I read this project documentation several times, unfortunately I couldn't find any misconfiguration, but maybe I just didn't notice.

BTW, despite this error, I love this adapter, after 3 hours of attempting to deploy svelteKit app to firebase, I'm glad that project like this exists.

Call to getRawBody waits indefinitely in handler.js

Describe the bug
The call to getRawBody in handler.js waits indefinitely when the request body is not undefined. This causes the SSR cloud function to stall and timeout when trying to render a route if the incoming request has a body.

body: await getRawBody(request)

To Reproduce
Create an endpoint that exports a post function, and try to access the body property of the LoadInput object. You'll find that the endpoint function never actually runs, when a request has a body, because it is never able to. I've only tested this in firebase cloud functions.

Expected behavior
The endpoint function gets run properly and can access the body of the request.

Additional context
The reason that the infinite await occurs is because getRawBody expects an IncomingMessage object, but it receives a Request object. This is due to Firebase's differences from other hosting services.

I have created a bad fix for this that only allows JSON data through, but you can see the premise of the solution:
https://github.com/AndrewLester/svelte-adapter-firebase/blob/c90d75dbd67a7652244f38dfd53548d8c3d24bd2/src/files/handler.js#L16

bug: issues deploying to Cloud Functions

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?

npx -y errors on npm versions less than 7

Describe the bug

npx -y on a version of npm less than v7 causes a git error. npm@7 ships with Node.js 16 which is very new and we should assume users are running Node.js 14 with npm@6.

Proposed Solution

Remove the -y from the documentation.

bug: ensure static resource destination differs from each of the sources

Describe the bug

This adapter takes the contents of svelte.config.js:kit.files.assets (default static) and .svelte-kit/output/client/** and outputs them to firebase.json:hosting.public.

We should ensure that svelte.config.js:kit.files.assets is != firebase.json:hosting.public.

An example of this configuration is in #55

Show config in adapter usage

Is your feature request related to a problem? Please describe.

The docs should also show usage of adapter options alongside zero-option usage it now shows.

Describe the solution you'd like

+import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		// hydrate the <div id="svelte"> element in src/app.html
+       adapter: firebase(),
		target: '#svelte'
	}
};

export default config;

With options:

+import firebase from "svelte-adapter-firebase";

/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		// hydrate the <div id="svelte"> element in src/app.html
-       adapter: firebase(),
+       adapter: firebase({ firebaseJson: '../firebase.json' }),
		target: '#svelte'
	}
};

export default config;

Describe alternatives you've considered

Additional context

docs: clearly explain dev, build, local test, local test with Firebase Emulator and production deployment flows

Is your feature request related to a problem? Please describe.

There are 5 stages during the dev > build > test > deploy cycle for SvelteKit apps. These can be confusing to users; what capabilities are utilised or available in each step?

These are the steps:

  1. dev: svelte-kit dev
  2. build prod (used for all subsequent steps): svelte-kit build
  3. test prod build locally without adapter environment: svelte-kit preview
  4. test prod build locally with adapter environment: see adapter docs
  5. deploy prod build to adapter environment: see adapter docs

Describe the solution you'd like

Summary each step and their purpose in a succinct way.

Describe in detail how to use each step where the adapter applies.

Describe alternatives you've considered

NA

Additional context

The official docs are going through improvements in this area, but documentation is required here to explain the functions of the Firebase adapter int his process.

Npm run build throws error

Describe the bug
When building a sveltekit project with the current version of the adapter an error is thrown.

To Reproduce
1.Initialize svelte kit demo app
2. Add "svelte-adapter-firebase": "^0.6.3" as devDependency in package.json and configure the adapter as described in the docs
3. npm i
4. npm run build -> error occurs

Expected behavior
Npm run build works without errors

Screenshots
image

Additional context
I was able to fix this locally by changing const pkgjson = JSON.parse(readFileSync(fileURLToPath(new URL('package.json', import.meta.url)), 'utf-8')); to const pkgjson = JSON.parse(readFileSync(fileURLToPath(new URL('./../package.json', import.meta.url)), 'utf-8')); in the index.js file.

bug: adapter logging output should guide the user with better examples

Describe the bug

Currently the logging output, especially the parseFirebaseConfiguration code, is not quite clear. It is meant as a guide, yet the wording and log level indicate the user has done something wrong. We should improve

  • the language
  • the log level used
  • add complete code snippets for missing components as the nomenclature of filename.ext:obj.ref is not as clear

To Reproduce

Expected behavior

Screenshots

Additional context

Svelte Fetch is not included on the Firebase build

Describe the bug
The todo page does not work when deploying the demo example project on Firebase with this adapter. It will throw: ReferenceError: fetch is not defined

To Reproduce
deploy the demo application on Firebase and go to the todos page

Expected behavior

That the fetch calls to the external API would work and no errors are thrown.

Screenshots

Additional context

There is some recent work in the official adapters to support Fetch
sveltejs/kit#1066
sveltejs/kit#1091

I am not sure if the solution is to ``import '@sveltejs/kit/install-fetch' or that we have to do something with node-fetch
sveltejs/kit#618 (comment)

feat: replace CF name lookup validation with require statement

Is your feature request related to a problem? Please describe.

Currently we validate whether a Cloud Function with the correct name is exported a string match on ${name} = here

if (!readFileSync(functionsEntrypoint, 'utf-8').includes(`${name} =`)) {

Describe the solution you'd like

A more robust and flexible solution would be to require the function from the package.json.mains export. If it is not found, it hard errors, and we can print the code required by the function. If it is found, then we know at least a function with the correct name exists (though not that it works).

Describe alternatives you've considered

Additional context

docs: include in SvelteKit list of adapters

Is your feature request related to a problem? Please describe.

SvelteKit lists adapters in the:

It would be good to get svelte-adapter-firebase listed there for visibility.

Describe the solution you'd like

PR a link to this project there.

Describe alternatives you've considered

Additional context

Support `target` in `firebase.json` configuration.

Is your feature request related to a problem? Please describe.
We have one source base deployed into two firebase projects as described here each with two sites. firebase.json includes a target which identifies the site after running firebase target:apply hosting TARGET_NAME RESOURCE_IDENTIFIER.

Describe the solution you'd like
We'd like to specify target in svelte.config.cjs instead of hostingSite:

module.exports = {
	preprocess: sveltePreprocess(),

	kit: {
		adapter: firebaseAdapter({firebaseJson: '../firebase.json', target: "fungi"}),

Describe alternatives you've considered
N/A

Additional context
N/A

docs: list non-goals

It is important to signal to users non-goals to reduce time wasted.

Non-goals:

  • writing Cloud Function code into function root .js file
  • handling deployment of your app, you should expect firebase deploy to work
  • supporting custom docker images (currently relying on Functions Framework and the Cloud Function Node14 buildpack. I may be convinced otherwise on this if it's not too much extra work, though it feels like duplication of the GCF buildpack image.

Cloud Run container can't be deployed because of devDependencies

Describe the bug
Cloud Run Container does not start because of several issues with dependencies/scripts.

To Reproduce
1.Initialize svelte kit demo app
2. Add "svelte-adapter-firebase": "^0.6.3" as devDependency in package.json and configure the adapter as described in the docs
3. npm i
4. fix #53 locally & build the project
5. deploy to cloud run

Expected behavior
Cloud Run container should start

Screenshots
image

Additional context
Removing the devDependencies from the generated package.json in .mysitessr and removing all scripts but the 'start' script seem to fix this problem (At least the container is deployed).

docs: include explanation of outputs of adapter

Is your feature request related to a problem? Please describe.

The adapter docs do not clearly describe that firebase.json:hosting.public field outputs a dir with all the static assets.

Describe the solution you'd like

Describe this more clearly in the "quickstart" and "adapter configuration" sections

Cannot install version 0.6+ with npm

Describe the bug
After installing with npm the following bug is triggered.

npm ERR! command sh -c npx -y only-allow pnpm                                                    
npm ERR! ║   Use "pnpm install" for installation in this project.                                              
npm ERR! ║   If you don't have pnpm, install it via "npm i -g pnpm".  
npm ERR! ║   For more details, go to https://pnpm.js.org/

To Reproduce
npm install --save-dev [email protected]

Expected behavior
The adapter should be able to be installed with npm

Additional context
It seems pnpm can not do anything npm can not do besides being a bit more efficient in caching. Therefore pnpm should not be a requirement to install the adapter?

This line in package.json is causing the issue:

  "scripts": {
    "preinstall": "npx -y only-allow pnpm",

The requested module 'firebase/app' is expected to be of type CommonJS, which does not support named exports

Describe the bug
I decided to use v9 of the Firebase API.

The biggest change to v8 is that you no longer need to load all the Firebase JS but just the functions that you are going to use.

Instead of

import firebase from "firebase/app"

it is called by

import { initializeApp } from 'firebase/app';

In development this works fine however when running the build with the Svelte adapter I get the following error:

> Using svelte-adapter-firebase
> The requested module 'firebase/app' is expected to be of type CommonJS, which does not support named exports. CommonJS modules can be imported by importing the default export.
For example:
import pkg from 'firebase/app';
const {getApp, initializeApp} = pkg;
file:///var/www/svelte/.svelte-kit/output/server/app.js:6
import {getApp, initializeApp} from "firebase/app";

To Reproduce
Steps to reproduce the behavior:

  1. Initiate an App with v9 logic
  2. Run a build with svelte adapter 0.6.3

Expected behavior
Being able to build without having to add something like import firebase from "firebase/app"

Additional context
I do not know where this error is triggered but it seems related to the adapter. The initial svelte build does seem to work. With the support of ESMBuild in #39 you would expect that it should work but maybe there is a hardcoded check on firebase/app that it is CommonJS somewhere?

fix: output Firebase Hosting deployment command on Cloud Run output suggestion

Is your feature request related to a problem? Please describe.

Cloud Run deploy command output makes no mention of requiring a firebase deploy --only hosting alongside it.

Describe the solution you'd like

Compute the minimum Firebase deployment command to output to the screen, with hostingSite support.

Describe alternatives you've considered

Additional context

test: e2e scenarios

Is your feature request related to a problem? Please describe.

It would be good to get some e2e tests that ensured the adapter output was in a working state once deployed to an environment.

Running svelte-kit build followed by the Firebase emulator should be possible in CI with some curls and assertions on the HTML responses.

Describe the solution you'd like

A self-contained CI implementation, preferrably using the Firebase emulator.

Describe alternatives you've considered

Deploying to an actual Firebase project.

Additional context

bug: ESM not supported in Node.js 14 environment

Describe the bug

Node.js 14 Google Cloud Function environment does not support ESM yet - GoogleCloudPlatform/functions-framework-nodejs#233

This support is required for Firebase Cloud Functions and if we want to use the same handler.js here for both Cloud Run and Cloud Functions.

Since the Vite SSR app.js file imports @sveltejs/kit/renderer via ESM import, and the @sveltejs/kit lib only outputs ESM, we cannot use SvelteKit in Cloud Functions.

Work arounds

Until this is supported, we have a some options:

  1. run the Vite SSR app.js file through Rollup and bundle/compile/transpile/transform the deps
  2. Deprecate Cloud Function support until this is resolved AND migrate Cloud Run support away from Functions Framework so we can recommend that approach in the meantime

I am likely going to go with 2. for now.

test: improve testing by removing error hashes, error codes?

Is your feature request related to a problem? Please describe.

We introduced error hashing in #80 as we are using console.log() over utils.log.* to output our own formatted guide logs to the user.

Currently, our actual error output is just > See above output. Error hash <hexcode>. This may suffice, but is not ideal for writing tests. One solution is to use proper error code as with Shellcheck - https://github.com/koalaman/shellcheck/wiki/SC1000

Describe the solution you'd like

  • tests to not dump console.log() guide data, especially during pre-commit hooks
  • replace error hash with error codes, like Shellcheck.
  • document error codes in the README under a new section "Error Codes" with each error in a details block
    • Is this better than using a Wiki for SEO?

Describe alternatives you've considered

NA
Additional context

NA

Force Node.js 14 Cloud Function runtime

Is your feature request related to a problem? Please describe.

SvelteKit should be deployed to Node.js 14 Cloud Functions. The template initialised by firebase init functions defaults to Node.js 12 so errors around this are likely to crop up. #47 is an example of not targetting v14.

Describe the solution you'd like

Error if Node.js 14 is not detected in either:

Describe alternatives you've considered

Additional context

The only reason I know of the firebase.json.functions.runtime field is from reading firebase-tools release notes religiously, not because it was easily found in the Firebase documentation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.