simondotm / nx-firebase

Firebase plugin for Nx Monorepos
https://www.npmjs.com/package/@simondotm/nx-firebase
MIT License
175 stars 31 forks source link

Plugin V2.0.0 roadmap #113

Closed simondotm closed 1 year ago

simondotm commented 1 year ago

Hi folks, I'm considering some changes to the plugin. Would be great to hear any feedback.

Here are my thoughts for the next major release:

  1. Plugin nx g @simondotm/nx-firebase:app generator will no longer scaffold functions by default
  2. The firebase app will be the same, and will contain all the deploy serve build commands etc.
  3. Instead there will be a separate nx g @simondotm/nx-firebase:function functions app generator
  4. The functions app generator will create a node style app that when built, will be bundled (using ~rollup~/~webpack~/esbuild)
  5. These functions apps can contain & export one or more firebase function
  6. There will no longer be any requirement for imported libraries to be buildable
  7. The current approach of building libraries and copying them to the deployment folder will be removed
rosslavery commented 1 year ago

Just jumping in to say this LGTM -- curious about what you mean by #4 and #7 though.

By bundling, would that impact how the function is deployed? I believe the "non-NX" way that the firebase CLI does it is simply with tsc non-bundled.

simondotm commented 1 year ago

Thanks for the feedback @rosslavery. I've been trialling bundles in my own project for a while now, as I was wanting to have a more granular approach to creating & using functions, rather than the existing approach of one node app exporting all functions.

I've tried out webpack, rollup and esbuild and the solution I've found to be best is esbuild. It's great and it 'just works' with Nx.

It compiles libraries from source (so they don't have to be buildable anymore), and it supports both es6 modules (which I'm now using) and commonjs too (with es6 having the advantage that compiled functions contain only the code actually referenced in the exported function thanks to tree shaking).

By bundling, would that impact how the function is deployed?

Turns out that it doesn't, if anything it simplifies it, and optimizes too. As long as there's a main.js and a package.json file in the dist folder, firebase CLI is happy. Of course, bundling means all project libs are directly inlined into main.js so no need for all that separate lib assembly process prior to deploy.

I've made a bit of progress getting this plugin migrated to it, hoping to have something to show soon.

simondotm commented 1 year ago

The recipe is quite simple if anyone wants to try hacking it around a bit:

Install @nx/esbuild plugin

Create a node app in your project:

nx g @nx/node:app myfunction--directory=functions --bundler=esbuild --framework=none --e2eTestRunner=none

Then change the project.json build target to something like:

    "build": {
      "executor": "@nx/esbuild:esbuild",
      "outputs": ["{options.outputPath}"],
      "options": {
        "platform": "node",
        "outputPath": "dist/apps/functions/myfunction",
        "main": "apps/functions/myfunction/src/main.ts",
        "tsConfig": "apps/functions/myfunction/tsconfig.app.json",
        "assets": ["apps/functions/myfunction/src/assets"],
        "generatePackageJson": true,
        "target": "node16",
        "esbuildOptions": {
          "logLevel": "info"
        }
      }
    },   

And then in your firebase.json config:

  ...
"functions": [
    {
        "source": "dist/apps/functions/myfunction",
        "codebase": "functions-myfunction",
        "runtime": "nodejs16"
    }
 ],
...

Now running nx build functions-myfunction will bundle your function code to dist and firebase deploy --only functions should work fine.

This is all ottomh so might be in need of tweaks here and there, but thats the general idea.

Next version of plugin will handle all this boilerplate for us. 👍

simondotm commented 1 year ago

Also, bundling works much better with --watch, and supports detection of changes to libraries when serving the app on the emulator.

simondotm commented 1 year ago

Closing in favour of #116