Skip to content

Instantly share code, notes, and snippets.

@JamieCurnow
Last active July 29, 2023 20:58
Show Gist options
  • Save JamieCurnow/374e69a2c3dd3b4952f967aa00a02938 to your computer and use it in GitHub Desktop.
Save JamieCurnow/374e69a2c3dd3b4952f967aa00a02938 to your computer and use it in GitHub Desktop.
Using firebase web framework with Nuxt 3
// preset/entry.ts
import '#internal/nitro/virtual/polyfill'
import { toNodeListener } from 'h3'
import { trapUnhandledNodeErrors } from './utils'
const nitroApp = useNitroApp()
export const listener = toNodeListener(nitroApp.h3App)
/** @deprecated use new `listener` export instead */
export const handler = listener
// Trap unhandled errors
trapUnhandledNodeErrors()
{
"hosting": {
"source": ".",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"frameworksBackend": {
"region": "europe-west1",
"minInstances": 0,
"maxInstances": 4,
"concurrency": 80
}
}
}
// preset/index.ts
import { fileURLToPath } from 'node:url'
import { createRequire } from 'node:module'
import type { NitroPreset } from 'nitropack'
import { join, resolve } from 'pathe'
import { globby } from 'globby'
import { readPackageJSON } from 'pkg-types'
import { writeFile } from './utils'
export default <NitroPreset>{
extends: 'node',
entry: fileURLToPath(new URL('./entry.ts', import.meta.url)),
// serveStatic: true,
hooks: {
async compiled(nitro) {
const _require = createRequire(import.meta.url)
const jsons = await globby(join(nitro.options.output.serverDir, 'node_modules/**/package.json'))
const prefixLength = `${nitro.options.output.serverDir}/node_modules/`.length
const suffixLength = '/package.json'.length
const dependencies = jsons.reduce((obj, packageJson) => {
const dirname = packageJson.slice(prefixLength, -suffixLength)
if (!dirname.includes('node_modules')) {
obj[dirname] = _require(packageJson).version
}
return obj
}, {} as Record<string, string>)
const getPackageVersion = async (id: string) => {
const pkg = await readPackageJSON(id, {
url: nitro.options.nodeModulesDirs
})
return pkg.version
}
await writeFile(
resolve(nitro.options.output.serverDir, 'package.json'),
JSON.stringify(
{
name: 'nitro-output',
version: '0.0.0',
private: true,
dependencies: {
'firebase-functions-test': 'latest',
'firebase-admin': await getPackageVersion('firebase-admin'),
'firebase-functions': await getPackageVersion('firebase-functions'),
...dependencies
}
},
null,
2
)
)
}
}
}
export default defineNuxtConfig({
ssr: true,
nitro: {
preset: resolve(__dirname, 'preset/index.ts')
}
})
// preset/utils.ts
import fsp from 'node:fs/promises'
import { dirname } from 'pathe'
export function trapUnhandledNodeErrors() {
if (process.env.DEBUG) {
process.on('unhandledRejection', (err) => console.error('[nitro] [unhandledRejection]', err))
process.on('uncaughtException', (err) => console.error('[nitro] [uncaughtException]', err))
} else {
process.on('unhandledRejection', (err) => console.error('[nitro] [unhandledRejection] ' + err))
process.on('uncaughtException', (err) => console.error('[nitro] [uncaughtException] ' + err))
}
}
export async function writeFile(file: string, contents: Buffer | string) {
await fsp.mkdir(dirname(file), { recursive: true })
await fsp.writeFile(file, contents, typeof contents === 'string' ? 'utf8' : undefined)
}
@luc122c
Copy link

luc122c commented Jul 29, 2023

@JamieCurnow Thanks for this! I'm going to try it out. Probably worth adding import { resolve } from "pathe" to the top of nuxt.config.ts :)

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