I found an issue on Firebase CLI repo that I could work on. The issue involved a hardcoded Node.js version in the generated package.json
file when the command firebase init functions
is executed. Moreover, there was no warning when a Node.js version in use is deprecated in Google Cloud Functions.
Getting started
To be honest, I had no idea how to approach this issue at first, so I decided to follow the contributing guide. It was very detailed and straightforward, so I had no problem setting up firebase-tools
. Unlike the previous open source projects, I had to sign Google's Contributor License Agreement (CLA) before I could contribute to Firebase CLI. Thanks to the intuitive folder structure of the project, I could identify which files to be modified.
Dynamically set Node version
Based on the folder structure, firebase init functions
should execute the code inside firebase-tools/src/init/features/functions/<language>.js
(<language>
is the programming language selected for your project). I made a comment on the issue to discuss my approach. Thankfully, I got some super helpful recommendations from Daniel, the author of the issue.
Basically, the package.json
file is generated from a pre-written template. To set the right Node.js version, I needed the logic to identify it and replace the hardcoded version with it dynamically.
First, I replaced the hardcoded version with a template string inside package.json
template file:
"engines": {
"node": "{{NODE_VERSION}}"
},
Then, a reliable function to detect Node.js version was implemented:
export function getNodeVersionString(): string {
return process.versions.node.split(".")[0];
}
Lastly, before writing package.json
file to a dev's machine, I just need to replace the template string with the detected Node.js version like this:
const nodeEngineVersion = getNodeVersionString();
if (useLint) {
return PACKAGE_LINTING_TEMPLATE.replace(/{{NODE_VERSION}}/g, nodeEngineVersion);
}
return PACKAGE_NO_LINTING_TEMPLATE.replace(/{{NODE_VERSION}}/g, nodeEngineVersion);
-
PACKAGE_LINTING_TEMPLATE: the content of
package.json
file with ESLint -
PACKAGE_NO_LINTING_TEMPLATE: the content of
package.json
file without ESLint
Handle deprecated Node versions
The logic to warn developers of deprecated Node.js versions was still missing, so I discussed my approach with Daniel again. I intended to use a function that I found in their codebase, isDeprecatedRuntime()
, to perform the check.
Luckily, Daniel pointed out a small bug in my approach and suggested a better one, which was to use isValidRuntime()
instead. I finally got the last piece as:
if (!isValidRuntime(`nodejs${nodeEngineVersion}`)) {
utils.logWarning(`Node ${nodeEngineVersion} is no longer supported in Google Cloud Functions.`);
utils.logWarning(
"See https://firebase.google.com/docs/functions/manage-functions for more details"
);
}
Final thoughts
I've never had to fix my code for a PR as much as this one. Thanks to their code review, I've learned a few good practices along with how I could avoid pitfalls by discussing my approach and getting feedback before actually coding it.
Issue: https://github.com/firebase/firebase-tools/issues/3407
PR: https://github.com/firebase/firebase-tools/pull/3894
Firebase: https://firebase.google.com
Top comments (0)