Sharing code between Firebase Functions and React - node.js

I'm using Firebase functions with a React application. I have some non-trivial code that I don't want to duplicate, so I want to share it between the deployed functions and my React client. I've got this working locally in my React client (though I haven't tried deploying) - but I can't deploy my functions.
The first thing I tried was npm link. This worked locally, but the functions won't deploy (which makes sense, since this leaves no dependency in your package.json). Then I tried npm install ../shared/ - this looked promising because it did leave a dependency in package.json with a file: prefix - but Firebase still won't deploy with this (error below).
My project directory structure looks like this:
/ProjectDir
firebase.json
package.json (for the react app)
/src
* (react source files)
/functions
package.json (for firebase functions)
index.js
/shared
package.json (for the shared module)
index.js
My shared module package.json (extraneous details omitted):
{
"name": "myshared",
"scripts": {
},
"dependencies": {
},
"devDependencies": {
},
"engines": {
"node": "8"
},
"private": true,
"version": "0.0.1"
}
My firebase functions package.json (extraneous details omitted):
{
"name": "functions",
"scripts": {
},
"dependencies": {
"myshared": "file:../shared",
},
"devDependencies": {
},
"engines": {
"node": "8"
},
"private": true
}
When I try to deploy with:
firebase deploy --only functions
It's telling me it can't load the module:
Function failed on loading user code. Error message: Code in file index.js can't be loaded.
Did you list all required modules in the package.json dependencies?
And I don't think the issue is how I export/imported my code- but just in case:
The export:
exports.myFunc = () => { some code };
The import (functions/index.js)
const myFunc = require('myshared');
And in my react code:
import { myFunc } from 'myshared';
So far the searching I've done hasn't yielded anything that works. Someone did mention entering the shared module path in firebase.json, but I couldn't find any details (including in the firebase docs) that show what that would look like. Thanks for any tips to get this going.

I found a solution. I'm not sure if it's the only or even the best solution, but it seems to work for this scenario, and is easy. As Doug noted above, Firebase doesn't want to upload anything not in the functions directory. The solution was to simply make my shared module a subdirectory under functions (ie ./functions/shared/index.js). I can then import into my functions like a normal js file. However, my shared folder also has a package.json, for use as a dependency to the react app. I install it using:
npm install ./functions/shared
This creates a dependency in my react app, which seems to resolve correctly. I've created a production build without errors. I haven't deployed the react app yet, but I don't think this would be an issue.

Another solution is to create a symlink. In terminal, under /ProjectDir, execute:
ln -s shared functions/shared
cd functions
npm i ./shared

Related

change the path of asset files in jest

So I want to run an e2e test using jest. I'm using nx monorepo architecture, and I have all my assets in a library folder and also nestjs microservices for my backend. I have all my proto files for my microservices in the library, and when I want to load them in my microservices, I do it like this :
protoPath: join(__dirname, 'assets-shared/job.proto'),
and in my workspace.json in my build i change the assets-shared like this:
"targets": {
"build": {
"options": {
"assets": [
{
"input": "libs/backend/shared/src/lib/assets",
"glob": "**/*",
"output": "assets-shared"
}
]
},
all is good, but when I run the test and when it wants to import and give value to it, it doesn't change it, and I have this error which is trying in its folder and not the library folder
ENOENT: no such file or directory, open '/home/dev/Project/apps/backend/api/src/modules/product/assets-shared/job.proto'
I tried the moduleNameMapper to give the libs folder to it manually but no avail.
moduleNameMapper: {
'^.+\\.(proto)$':
'<rootDir>/libs/backend/shared/src/lib/assets/$1',
// '^assets-shared(.*)': '/libs/backend/shared/src/lib/assets/$1',
},
non of these two worked
Have you considered publishing the libraries to a private npm repository or something like artifactory e.g. #my-company/assets
The approach you are trying may work locally, but for a ci/cd pipeline it would be much better to have a versioned artifact in npm or artifactory

What is proper way to store code/functions that are used by both the frontend and backend?

My frontend Reactjs app is stored in one repository.
My backend Node.js app is stored in another repository.
There are some functions used by both. Where should store those functions so that both repositories can access them?
You can create a library that exports all of the functions you'll be needing, then publish it to NPM and add it to the dependencies of both projects' package.json. With NPM you can set your packages as private, too, in case you don't want your code/package to be publicly available.
The starting point would be to create a directory with all the functions you need, export them all in an index.js, and run npm init to create a package.json for your new project. You'll be guided for naming and assigning a version number, then publish with npm publish (you may need to create an account and run npm login first). Then in your frontend and backend projects you simply npm install <your-package> like any other npm package.
Your project directory may be as simple as...
myFunctions.js
index.js
package.json
myFunctions.js:
export const functionA = () => {
return "a"
}
export const functionB = () => {
return "b"
}
index.js:
export * from './myFunctions.js'
package.json (can be created with npm init:
{
"name": "my-functions",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Then in the directory run npm publish, and in your other projects you can run npm install my-functions.
And finally, in your other projects:
import { functionA } from 'my-functions';
// ...
functionA() // returns "a"
Creating a separate NPM package for your helper functions can certainly be a good solution, but I find them somewhat annoying to maintain across different repositories. I tend to try and avoid them.
There are certainly some functions in your application that do have purpose on both the front- and backend, but I would encourage you to look at these carefully to see if that logic can be the responsibility of one or the other (backend or frontend).
For example; if you have a function to parse a date and format it in a very specific way for your app then you can have that function live solely in the backend and leverage it to pass back the already converted value to the frontend - avoiding the burden of maintaining it in 2 places or in a separate package that then needs to be updated in 2 repositories.
Sometimes there's just no getting around it though, but I found that in most cases I can split them accordingly.

NestJS Monorepo Microservices - Cannot find module '#work/contracts/dist/adresses' or its corresponding type declarations

I'm trying to build a NestJS Monorepo service using Microservices architecture and TypeScript as primary language.
The monorepo project consists of two microservice apps - 'work' and 'workers'.
The 'work' service app is meant to power the 'workers' app that exists in the same NestJS monorepo project.
The problem is, when I start the 'work' app and try running the 'workers' app, it doesn't recognize the existence of the 'work' app or its path, and thus fails to run.
I get the error below.
src/application/work/load-address.ts:4:41 - error TS2307: Cannot find module '#work/contracts/dist/adresses' or its corresponding type declarations.
I'm using 'npm run start' to run the 'workers' app.
Thanks in advance!
The 'work' package.json file looks like this:
{
"name": "#work/create",
"version": "0.0.1",
...
...
}
The 'workers' package.json file looks like this:
{
"name": "#workers/contracts",
"version": "0.0.1",
...
...
}
And I import 'work' into 'workers' like this:
import { ADDRESS } from '#work/contracts/dist/adresses';

How to get snowpack to look inside a package for subpath

I am building a snowpack app right now, and I would like to import socket.io client in the frontend (For intellisense and offline dev testing). However, socket.io only exports the backend materials when using import ... from 'socket.io'.
Normally, I use
import { io } from 'socket.io/client-dist/socket.io.js';
Which gets all the correct files and exports, however, when building with snowpack I get this error:
Package exports for 'C:\dev\JS\Node+Browser\foo\node_modules\socket.io' do not define a './client-dist/socket.io.js' subpath
Which fails the build, stopping everything.
Right now, my snowpack.config is really bare bones:
module.exports = {
buildOptions: {
out: 'dist/client'
},
mount: {
"src/client": "/"
}
}
All of the rest of my modules run fine, because they are all imported with only import ... from 'module-name. I understand what the error is saying, but I cant find anything online or thing of anything to solve it. Does anyone know how to fix this?
NOTE: This is a "hacky" fix that I think is messy and can not be used for larger projects.
I patched this by editing the package.json of the socket.io package (In node_modules) to use a temporary export alias that was exactly the same as the real directory path:
node_modules/socket.io/package.json
"exports": {
".": [
{
"require": "./dist/index.js",
"import": "./wrapper.mjs"
},
"./src/index.js"
],
"./client-dist/socket.io": "./client-dist/socket.io.js",
"path-to-other-modules": "same-path"
},

How do I install npm packages on Google Cloud Functions?

I'm trying to create a simple function that:
fetches a JSON file from a public URL
does a little number crunching and spits out an answer.
I figured that Google Cloud Functions would be the perfect fit since I can code in JS and don`t have to worry about server deployment, etc.
I've never really used nodejs/npm so maybe this is the issue, but I tried reading online and they just mention
npm install package-name
I'm not sure where I can do this on the Google Cloud Functions page.
I'm currently using the inline editor and I have the following:
var fetch = require('node-fetch');
exports.test2 = (req, res) => {
fetch("myURLgoes here").then(function(response){
res.status(200).send('Success:'+response);
});
I get the following error:
Error: function crashed.Details:
fetch is not defined
From Google Cloud Platform console, go to your cloud functions.
You should have two files when creating or editing a functions:
- index.js: where you define your functions
- package.json: where you define your dependency.
Your package.json at the start is something like this:
{
"name": "sample-http",
"version": "0.0.1"
}
Add in your package.json all your module that you'd like to install with the command npm install as below:
{
"name": "sample-http",
"version": "0.0.1",
"dependencies": {
"#material-ui/core": "^4.1.1"
}
}
you can find the last version of the package on www.npmjs.com
You can run the npm command from the Google Cloud Shell (which you can access from the Google Cloud Console).

Resources