Monorepo in Gitpod
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:
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! ๐ผ
Subscribe to my newsletter
Read articles from Daniel Cadeau directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by