Monorepo in Gitpod

Daniel CadeauDaniel Cadeau
3 min read

In this article, I will walk through a monorepo setup with a React front-end and a Symfony back-end, using Gitpod as the cloud-based development environment provider (same logic for Stackblitz, Github Codespaces and so on).

CORS: where the journey begins (and sometimes ends but not this time, I commit)

In a local setup scenario, we may start both sides on localhost whatever ports we choose, allowing the front-end to communicate with the back-end.

Well that's nice, but in a cloud-based development environment opened directly in a web browser without port forwarding: this won't work the same way.

E.g. in Gitpod your apps will be served on URLs resembling:
https://$PORT-$REPOSITORY_NAME-$RANDOM_STRING.$REGION.gitpod.io/
Then, when your code tries to make a request to your back-end on something like http://localhost:8000, this is what happens:

Screenshot of browser console errors. Two error messages are displayed:  'Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/hello/world. (Reason: CORS request did not succeed). Status code: (null). [Learn More]' 'Error fetching message: TypeError: NetworkError when attempting to fetch resource.'  These errors are highlighted in red, indicating CORS (Cross-Origin Resource Sharing) issues when attempting to access a back-end development server.

This is because your web browser is making a call to your local machine localhost which is returning a complete void in the above case.

A new hope for CORS conflicts

By setting up a proxy we can route API calls from the front-end to the back-end. Even though your front-end is served on a dynamically generated URL by Gitpod (or whatever).

This approach is widely adopted across many front-end development tools:
https://vite.dev/config/server-options.html#server-proxy
https://create-react-app.dev/docs/proxying-api-requests-in-development/
https://angular.dev/tools/cli/serve#proxying-to-a-backend-server

E.g. on my demo monorepo I followed the way detailed in Vite docs. Here is my properly updated vite.config.ts:

server: {
  proxy: {
    '/api': {
      target: 'http://localhost:8000',  // Symfony Back-end URL
      changeOrigin: true,
      rewrite: (path) => path.replace(/^\/api/, ''),  // Rewrites the path
    }
  }
}

This ensures that all requests made to /api on the front-end are automatically forwarded to the correct localhost back-end URL, even in the context of a dynamic preview page of a cloud-based development environment.

It effectively avoids CORS issues by routing all API requests through the proxy. Since both the front-end and back-end appear to be served from the same origin, there's no need to configure CORS on the back-end during development.

This simplifies the overall workflow.

Making waves across codebase

Now instead of doing:

fetch('http://localhost:8000/hello/world')

You can simply use:

fetch('/api/hello/world')

Of course, in a real life context both http://localhost:8000 and /api should be stored in environment variables since they will likely change in a production environment.

All's well that ends well (with proper configuration โ€” always!)

In summary, configuring a proxy as demonstrated is a powerful method to make it works everywhere. The front-end may now communicate with the back-end even on a dynamically generated web preview.

If you'd like to explore the code directly, you can find it in the repository here:
๐Ÿ“ฆ https://github.com/daliendev/monorepo-demo

Since we are here to talk about cloud-based development environment, you can also launch it directly in Gitpod.
๐ŸŸ  https://gitpod.io/#https://github.com/daliendev/monorepo-demo

Thank you for reading! ๐Ÿ˜ผ

10
Subscribe to my newsletter

Read articles from Daniel Cadeau directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Daniel Cadeau
Daniel Cadeau