3

I'm working on a react app that uses Firebase Functions as its backend. My folder hierarchy is set up so that my functions project is inside the project for the react app:

/my-project
  /functions
    index.ts
    (...)
  /src
    App.tsx
    index.tsx
    (...)

I want to have Typescript typecheck the data I send to my Firebase Functions, and to do that it would be useful to be able to share code between my React App and my Functions.

For a while I was doing this just by symlinking a folder inside functions to one inside src, which worked for a while until I added enums. It turns out that symlinks under src are not actually supported by CRA, and the fact that it was working at all was a fluke.

In the past people seem to have gotten around this using react-app-rewired, customize-cra, and craco, but none of these are maintained anymore and none of them support CRA 5.0.

So, what should I do now?

Joel Newman
  • 125
  • 7
  • Maintaining the shared code in a [local npm module](https://stackoverflow.com/q/15806241/438273) (and installing it in each project) is a common technique. Also, have you tried [hard links](https://stackoverflow.com/q/185899/438273)? – jsejcksn Jun 07 '22 at 00:37
  • @jsejcksn Those both might work but they have major drawbacks. The shared code is in typescript, so I'd have to set up a typescript compiler in that local module too, and then rebuilt it every change. Hard links might work but it would probably cause issues with git, which I'd like to avoid as I'm collaborating on this with other people. – Joel Newman Jun 07 '22 at 00:52
  • Why do you think you need to compile the shared TypeScript modules independently? Isn’t compilation already part of your consuming projects’ build process? – jsejcksn Jun 07 '22 at 01:26
  • @jsejcksn I'm not sure what you mean. Typescript modules have to be compiled before they can be imported. Right now in my project, CRA is handling the typescript compilation for the Web App and Google's upload scripts are handling compilation for the Firebase Functions. If I split out the shared component into another package in the same repo, I'd have to compile it separately, no? If there's something else I could be doing could you explain it using the repro example app from my original post? – Joel Newman Jun 07 '22 at 15:38
  • “_Typescript modules have to be compiled before they can be imported_”: What does this mean? CRA handles importing TypeScript modules just like JavaScript modules. – jsejcksn Jun 07 '22 at 17:53
  • @jsejcksn so wait can you just drop a package.json into a folder with only typescript files in and then install it into the project and have it work? Because I tried that and it didn't work, and then impression I got online was that you had to compile it to js first. – Joel Newman Jun 07 '22 at 19:10
  • Yes, that's right. But your bundler must support it, and it appears that the default CRA webpack config does not. The only officially-supported solution is to maintain the common modules in the `./src/` directory of your CRA project and import them from there (relative local paths) in your Firebase modules. – jsejcksn Jun 08 '22 at 05:11
  • @jsejcksn no such luck, firebase cloud functions don't support importing local modules from outside the functions folder. Trying my luck with a preinstall script that npm packs it into the functions folder now, but that's giving me even weirder issues! – Joel Newman Jun 08 '22 at 18:39
  • @jsejcksn it doesn't seem like it's possible to make a package out of a typescript module without compiling it, which means I'm back to square one. I think my remaining options are maybe to try symlinking from the other side, or at this point, maybe to just give up and make the common stuff its own package with its own typescript setup and package.json and everything. – Joel Newman Jun 08 '22 at 19:16

1 Answers1

3

For any soul who finds themself here, what I ended up doing was just making the shared code a folder in /src/ folder of the CRA Web App, and then symlinking it from the /functions/ folder of my Firebase Cloud Functions.

Joel Newman
  • 125
  • 7