Skip to content

Commit

Permalink
Functions & apps docs updated
Browse files Browse the repository at this point in the history
  • Loading branch information
simondotm committed Apr 6, 2024
1 parent 673c80b commit 0c36989
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 32 deletions.
2 changes: 2 additions & 0 deletions docs/nx-firebase-applications.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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:**
Expand Down
102 changes: 74 additions & 28 deletions docs/nx-firebase-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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:

Expand All @@ -38,50 +59,72 @@ OR
| `--app=<app-project-name>` | 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=<node versions>` | 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/<function-project-name>/main.js` - The bundled function code, in a single ESM format output file
- `dist/apps/<function-project-name>/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 <codebase> --only functions:<codebase>:function-name`**

Where `<codebase>` 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

Expand All @@ -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:

Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand Down
7 changes: 3 additions & 4 deletions docs/nx-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -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=<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

Expand All @@ -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
Expand Down

0 comments on commit 0c36989

Please sign in to comment.