1

Question

I have

  1. a straightforward react client, and
  2. a node server that serves the client pages and acts as an API for the client.

They are tightly-coupled, independent TypeScript projects that are part of one larger git repo. The server will never be "deployed" anywhere, it just will run on the local network.

I want to keep a shared set of types that define the API. Something like how RESTyped defines them:

interface MyAPIDefinition {
  "/user/": {
    "GET": {
      params: { id: number }
      response: { ... }
    }
    ...
  }
  "/image/:id": {
  ...
}

Note: Some of these types may be dependent on @types/node, e.g. Buffer.

What is the best way to accomplish this?

Research so far

  1. This stackoverflow answer suggests merging everything into one project, with the server at the root and the client as a subfolder. The downsides I see with this are:

    • The complexity of getting react-scripts build|run to work on the subfolder
    • (More importantly IMO) the server and client are sharing their node_modules
  2. This answer suggests using yarn workspaces. In my case I would use npm workspaces I guess, but that seems to be bleeding-edge tooling that I would rather not mess with, as it could cause confusion among my team.

  3. This one says to throw away the simplicity of a directory-based workflow and package your shared code/types into a privately-hosted npm module. This seems like a huge pain, since a) the server and client are part of a single repo, so the shared code should live there too, and b) I would have to republish the package and reupdate the dependencies in both modules whenever I wanted to make changes. This would also be a complicated workflow to explain to my collaborators.

  4. This question wasn't answered but has a few updates from the OP. They ended up writing a script which watches the files in the shared directory and automatically copies them to the other projects. This feels hacky and confusing to collaborators.

Ahmet Emre Kilinc
  • 5,489
  • 12
  • 30
  • 42
MHebes
  • 2,290
  • 1
  • 16
  • 29
  • 1
    3 is the official answer and will serve for sharing beyond this app. 2 is a solution to 3's overhead (from [lerna](https://lerna.js.org/)). 1 I would avoid. 4 seems like [link](https://classic.yarnpkg.com/en/docs/cli/link/) with extra steps. – Matt Oct 27 '20 at 06:51

1 Answers1

1

As I understand it, you already use some kind of monorepo containing projects for your back and front.

Tools such as rush or nx allows you to automatize monorepo project inter-dependencies / publishing / build...

The back and front project could depend on a new shared "interfaces" project and the monorepo tool would wire everything and handle dependency bump and such.

known-as-bmf
  • 1,162
  • 8
  • 9
  • Thanks for the response. Is there any reason I shouldn't just `npm install ../shared` in the server/client? Per [this](https://stackoverflow.com/a/8089029/3554391) answer. – MHebes Oct 27 '20 at 15:33