From 0c36989cc7481adae05690427697bfd5687257b0 Mon Sep 17 00:00:00 2001 From: Simon M Date: Sat, 6 Apr 2024 01:56:28 +0100 Subject: [PATCH] Functions & apps docs updated --- docs/nx-firebase-applications.md | 2 + docs/nx-firebase-functions.md | 102 ++++++++++++++++++++++--------- docs/nx-libraries.md | 7 +-- 3 files changed, 79 insertions(+), 32 deletions(-) diff --git a/docs/nx-firebase-applications.md b/docs/nx-firebase-applications.md index 5b202e7..319a9ae 100644 --- a/docs/nx-firebase-applications.md +++ b/docs/nx-firebase-applications.md @@ -17,6 +17,7 @@ OR | `name` | required | the project name for your firebase app | | `--directory=dir` | optional | the directory this app will be located in | | `--project=proj` | optional | the `--project` option that will be used for firebase CLI commands | +| `--projectNameAndRootFormat` | optional | `derived` or `as-provided` see [projectNameAndRootFormat](https://nx.dev/nx-api/node/generators/application#projectnameandrootformat) | ## About Firebase Apps @@ -31,6 +32,7 @@ When a new Nx Firebase application project is generated in the workspace it will - Default `database.rules.json` for Firebase realtime database - Default `storage.rules` for Firebase storage rules - Default `public/index.html` for Firebase hosting - _you can delete this if your firebase configuration for hosting points elsewhere_. +- Default `public/404.html` for Firebase hosting - _you can delete this if your firebase configuration for hosting points elsewhere_. - Default [environment variables](./nx-firebase-functions-environment.md) for your firebase functions **And in the workspace root:** diff --git a/docs/nx-firebase-functions.md b/docs/nx-firebase-functions.md index a529ec2..1fea17a 100644 --- a/docs/nx-firebase-functions.md +++ b/docs/nx-firebase-functions.md @@ -2,15 +2,15 @@ - [Firebase Functions](#firebase-functions) - [Nx-Firebase Functions](#nx-firebase-functions) - - [Generating a new function](#generating-a-new-function) - - [Firebase Function Projects](#firebase-function-projects) - - [Building a firebase function](#building-a-firebase-function) - - [Deploying a firebase function](#deploying-a-firebase-function) - - [Testing \& Linting your firebase function](#testing--linting-your-firebase-function) - - [Bulk operations for functions](#bulk-operations-for-functions) + - [Generating a new function](#generating-a-new-function) + - [Building a Firebase function](#building-a-firebase-function) + - [Firebase Function Dependencies \& Package Managers](#firebase-function-dependencies--package-managers) + - [Deploying a Firebase function](#deploying-a-firebase-function) + - [Testing \& Linting your firebase function](#testing--linting-your-firebase-function) + - [Managing Functions in your Workspace](#managing-functions-in-your-workspace) - [Functions \& Nx-Firebase Applications](#functions--nx-firebase-applications) - [How Nx-Firebase function apps are linked to Nx-Firebase apps](#how-nx-firebase-function-apps-are-linked-to-nx-firebase-apps) - - [Functions \& Firebase Config](#functions--firebase-config) + - [Functions \& Firebase Config Codebases](#functions--firebase-config-codebases) - [Functions \& ESBuild](#functions--esbuild) - [Using ES Modules output](#using-es-modules-output) - [Using CommonJS output](#using-commonjs-output) @@ -20,9 +20,30 @@ ## Nx-Firebase Functions -Since v2.x of the plugin, Nx-Firebase functions are now generated as individual applications, separately to the Nx-Firebase application. +Nx-Firebase functions are generated as individual Nx application projects, separately to the Nx-Firebase application. -### Generating a new function +* This allows for multiple functions to be generated in a single workspace, each with their own `src/main.ts` entry point and `package.json` file. + +* The default `src/main.ts` template is the same one generated by the Firebase CLI and defaults to using 2nd gen cloud functions. This file is of course just a starting point and can be modified as needed. + +* Each function project is a buildable Typescript node-based application, which is compiled and bundled using [esbuild](#functions--esbuild). + +* Each function project can export one or more firebase cloud functions. + +* Each function project must be linked to a single [Firebase application project](./nx-firebase-applications.md) in the workspace, which ensures all functions can be managed by the nx-firebase plugin. + +* Functions can import code from [Nx shared libraries](./nx-libraries.md) and `esbuild` will tree-shake and bundle the code into a single output file. + +* You rename or move Firebase function projects in your Nx workspace, and use the plugin [sync](./nx-firebase-sync.md) command to keep your `firebase.json` configuration file in sync. + +* Functions can be [tested](#testing--linting-your-firebase-function), [linted](#testing--linting-your-firebase-function), [built](#building-a-firebase-function) and [deployed](#deploying-a-firebase-function) using the Nx CLI + +[package dependencies](#firebase-function-dependencies-package-managers) + +* Functions support deployment with `npm`, `pnpm` or `yarn` package managers. + + +## Generating a new function Generate a new Firebase function using: @@ -38,50 +59,72 @@ OR | `--app=` | required | the firebase app this function will be a dependency of | | `--directory=dir` | optional | the directory this function will be located in | | `--format=<'cjs' or 'esm'>` | default 'esm' | specify if esbuild should generated commonJs or ES6 output | +| `--runTime=` | optional | the nodejs runtime you wish to use for this function - 14, 16, 18, 20 | +| `--tags` | optional | tags to set on the new project | +| `--setParserOptionsProject` | optional | set the parserOptions.project in the tsconfig.json file | +| `--projectNameAndRootFormat` | optional | `derived` or `as-provided` (see Nx docs for [projectNameAndRootFormat](https://nx.dev/nx-api/node/generators/application#projectnameandrootformat)) | -### Firebase Function Projects -Firebase function application projects are buildable node Typescript applications, which are compiled and bundled using `esbuild`. +## Building a Firebase function -The entry point module for function projects is `src/main.ts`. +To build your firebase function use this command: -The default `main.ts` template is the same one generated by the Firebase CLI and defaults to using 2nd gen cloud functions. This file is of course just a starting point and can be modified as needed. +- **`nx build your-firebase-function-project-name`** -> Newly generated function projects may not deploy out-of-the-box. For some reason the default Firebase CLI template for `main.ts` does not include code to call `initalizeApp()` so this has been added as a comment to the nx-firebase plugin version of the template. **This call must be enabled in order to successfully deploy a function.** +This will use `esbuild` to compile & bundle the input function Typescript source code to: -### Building a firebase function +- `dist/apps/your-firebase-function-project-name/main.js` - The bundled function code, in a single ESM format output file +- `dist/apps/your-firebase-function-project-name/package.json` - The ESM format package file for firebase CLI to process and deploy -To build your firebase function use this command: +## Firebase Function Dependencies & Package Managers -- **`nx build your-firebase-function-project-name`** +When building a function, Nx will automatically generate a `package.json` file in the output `dist` directory, which contains all package dependencies used by the function. -This will use `esbuild` to compile & bundle the input function Typescript source code to: +Nx will also generate a pruned `package-lock.json`, `yarn.lock` or `pnpm-lock.yaml` file in the function project root, depending on the package manager used in the workspace, which ensures your deployed function has exactly the same dependencies in the cloud as it does locally. + +## Deploying a Firebase function -- `dist/apps//main.js` - The bundled function code, in a single ESM format output file -- `dist/apps//package.json` - The ESM format package file for firebase CLI to process and deploy +To deploy all of your firebase function projects use: -### Deploying a firebase function +- **`nx deploy your-firebase-app-name --only:functions`** -To deploy your firebase function use this command: +To deploy one of your firebase function projects use this command: - **`nx deploy your-firebase-function-name`** -Your function will be deployed by the Firebase CLI. +To deploy a single function from within a firebase function project that exports multiple functions, use this command: -### Testing & Linting your firebase function +- **`nx deploy --only functions::function-name`** + +Where `` is whatever name you gave your nx-firebase:function project. + +> **IMPORTANT NOTE: Newly generated function projects do not deploy out-of-the-box. This is because the default Firebase CLI template for `main.ts` does not include code to call `initalizeApp()` so you will need to add this yourself:** + +``` + import { initializeApp } from "firebase-admin/app"; + initializeApp() +``` + +## Testing & Linting your firebase function - **`nx test your-firebase-function-name`** - **`nx lint your-firebase-function-name`** -### Bulk operations for functions +## Managing Functions in your Workspace -You can use the parent Firebase app to test, lint, build, watch and deploy all of your functions at once. +You can use the parent Firebase app to build, test, lint, watch and deploy all of your functions at once. + +- **`nx build your-firebase-app-name`** +- **`nx test your-firebase-app-name`** +- **`nx lint your-firebase-app-name`** +- **`nx watch your-firebase-app-name`** +- **`nx deploy your-firebase-app-name`** Note that there is no `serve` target for individual function projects, since serving only makes sense at a firebase app level with the Firebase Emulator suite, so use the following command instead: - **`nx serve your-firebase-app-name`** -See [here](./nx-firebase-applications.md#nx-firebase-application-project-targets) for more details. +See [Firebase Application Targets](./nx-firebase-applications.md#nx-firebase-application-project-targets) for more details. ## Functions & Nx-Firebase Applications @@ -98,7 +141,7 @@ The Nx-firebase plugin requires that Firebase function projects must always be a - Firebase function apps can export either just one or multiple firebase cloud functions - When running the Firebase emulator using `serve`, **all** firebase function applications are built using `watch` mode, so local development is much more convenient -### Functions & Firebase Config +### Functions & Firebase Config Codebases When new Firebase function applications are generated in the workspace: @@ -133,6 +176,7 @@ If you still use Node `require()` in your Typescript function code, the default Note that using `cjs` output may prevent tree-shaking optimizations. + ### Why ESBuild? While Webpack and Rollup are viable options for bundling node applications: @@ -144,6 +188,8 @@ While Webpack and Rollup are viable options for bundling node applications: If you want to try Webpack or Rollup, just change your `build` target in the function's `project.json` accordingly. +> The Nx Webpack bundler may be required for projects that require Typescript decorators such as NextJS. + ### Why not minify? This plugin does not set or recommend the minify option for esbuild. diff --git a/docs/nx-libraries.md b/docs/nx-libraries.md index a9f7116..d05f537 100644 --- a/docs/nx-libraries.md +++ b/docs/nx-libraries.md @@ -6,11 +6,10 @@ Nx-Firebase supports use of Nx Libraries within functions code. To use a shared library with an Nx Firebase Function Application, simply create a Typescript Nx node library in your workspace: -**`nx g @nx/js:lib mylib --importPath="@myorg/mylib`** +**`nx g @nx/js:lib mylib --importPath="@myorg/mylib [--bundler=]`** > _Note: The `--importPath` option is highly recommended to ensure the correct typescript aliases and npm package configurations for your library._ -Since v2.x of the plugin, functions are bundled with esbuild, so ## Importing a library @@ -32,10 +31,10 @@ OR ## Nx Library Notes -Since v2 of the plugin now uses `esbuild` to bundle function code, we gain a few benefits: +[Firebase functions](./nx-firebase-functions.md) use `esbuild` to bundle function code, we gain a few benefits: - Nx takes care of ensuring all necessary dependencies will be also built. -- It no longer matters if libraries are buildable or non-buildable +- It does not matter if libraries are buildable or non-buildable, as `esbuild` builds from Typescript sources, however buildable libraries may be preferred since `esbuild` does not do type checking of imported libraries. - We do not have to worry about how we structure libraries anymore for optimal function runtime. - For instance, we can use barrel imports freely, since `esbuild` will treeshake unused code and inline imports into the bundled output `main.js` - We can create as many libraries as we wish for our functions to use, and organise them in whatever makes most sense for the workspace