Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass NODE_OPTIONS when spawning firebase-functions to enable TS support in the emulator #6112

Open
gustavopch opened this issue Jul 11, 2023 · 6 comments · May be fixed by #6191
Open

Pass NODE_OPTIONS when spawning firebase-functions to enable TS support in the emulator #6112

gustavopch opened this issue Jul 11, 2023 · 6 comments · May be fixed by #6191

Comments

@gustavopch
Copy link

gustavopch commented Jul 11, 2023

const env: NodeJS.ProcessEnv = {
...envs,
PORT: port,
FUNCTIONS_CONTROL_API: "true",
HOME: process.env.HOME,
PATH: process.env.PATH,
NODE_ENV: process.env.NODE_ENV,
// Web Frameworks fails without this environment variable
__FIREBASE_FRAMEWORKS_ENTRY__: process.env.__FIREBASE_FRAMEWORKS_ENTRY__,
};

By adding NODE_OPTIONS: process.env.NODE_OPTIONS, we'll be able to enable TS support in userland in the emulator simply by installing @esbuild-kit/esm-loader (or anything similar) and using the following script to run:

NODE_OPTIONS='--loader=@esbuild-kit/esm-loader' firebase emulators:start

Solves: #5633

@joehan
Copy link
Contributor

joehan commented Jul 11, 2023

Passing this along to @taeold from the Cloud Function for Firebase team. My initial thought is that this is reasonable but low prioirity, as in production, Cloud Function will require compiled TS and we don't like to deviate from production behavior in the emulator

@gustavopch
Copy link
Author

gustavopch commented Jul 11, 2023

People using TS currently need to:

  1. Transpile on the fly while in the emulator
  2. Transpile before deploying

This change would allow them to simplify the first part, which is the most complex of the two, so it would already be a huge win for DX. And it's a 1 line change that won't affect anything architecture-wise. It doesn't even need to be thought as a way to enable TS support. It's just an improvement in compatibility with Node.js in general.


Now, thinking about production, why not use a loader too so it's possible to enable built-in support for TS in a way that won't affect a lot of the architecture and take ages to implement? Even if the performance is not great (I'm not sure about that though because @esbuild-kit/esm-loader caches the modules as they're loaded for the first time), people that actually care a lot about performance would still be able to transpile to JS the way they do today. And then in the future Firebase can still replace the loader with actual transpilation if needed without anyone even knowing because it will be an implementation detail.

I mean: make it work, then make it fast (supposing the loader is actually slower).

@trevor-rex
Copy link

People using TS currently need to:

  1. Transpile on the fly while in the emulator
  2. Transpile before deploying

This change would allow them to simplify the first part, which is the most complex of the two, so it would already be a huge win for DX. And it's a 1 line change that won't affect anything architecture-wise. It doesn't even need to be thought as a way to enable TS support. It's just an improvement in compatibility with Node.js in general.

Now, thinking about production, why not use a loader too so it's possible to enable built-in support for TS in a way that won't affect a lot of the architecture and take ages to implement? Even if the performance is not great (I'm not sure about that though because @esbuild-kit/esm-loader caches the modules as they're loaded for the first time), people that actually care a lot about performance would still be able to transpile to JS the way they do today. And then in the future Firebase can still replace the loader with actual transpilation if needed without anyone even knowing because it will be an implementation detail.

I mean: make it work, then make it fast (supposing the loader is actually slower).

Our team handles automatic transpilation during while the emulators are running by adding
./node_modules/typescript/bin/tsc -w &
to the script that starts up our functions emulators, but perhaps your use case is a bit different (I don't know the full scope of what NODE_OPTIONS accomplishes here).

@gustavopch
Copy link
Author

NODE_OPTIONS allows to pass arguments that will be appended to node when it runs. With that, I can pass --loader=@esbuild-kit/esm-loader to make Node.js understand .ts imports. This approach doesn't require a separate process watching the file tree and emitting transpiled files.

@taeold
Copy link
Contributor

taeold commented Jul 26, 2023

I understand @joehan point, but I think @gustavopch approach here is pretty elegant.

IIUC, the suggested patch doesn't alter the runtime behavior of CF3 function - it only affects how the function code is loaded during deployment analysis time. It's a low cost change that no impact to most users, but a huge devx win for folks like @gustavopch who know what they are doing.

@gustavopch if you have a patch already at hand feel free to share a PR with us. Otherwise, I'll get one going soon.

gustavopch added a commit to gustavopch/firebase-tools that referenced this issue Jul 26, 2023
@dominics
Copy link

dominics commented Oct 5, 2023

Hello team, please also consider the use case of passing flags such as NODE_OPTIONS="--trace-deprecation" - there are a lot of flags like that one that are useful (dozens listed in node --help, like --trace-warnings or --trace-sync-io)

For example, I currently receive the following error from Node upon starting my Firebase functions, both in production and in the emulator, and I'd like to track down which NPM module (among thousands) is using the deprecated constructor mentioned:

(node:7471) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
(Use `node --trace-deprecation ...` to show where the warning was created)

With the attached fix, I can easily add this flag and receive the stack trace. WIthout it, I'm kinda lost! There's no easy way to grep for Buffer() inside a normal node_modules/ and find which package is causing the error (in my case, it was pubnub -> superagent-proxy -> proxy-agent -> pac-proxy-agent -> get-uri -> ftp!). Manually applying @gustavopch's patch helped immensely

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

Successfully merging a pull request may close this issue.

6 participants