We’ve all been there
You have your API server running and you have your React code ready. How do you stitch it together?
Like most developers out there, I use yarn start
when I am doing my development work for React. This creates a development server locally, most commonly running on localhost:3000. Once I’ve finished my frontend changes, I would run a yarn build
to produce my bundles, and then using Go’s embed
package, I would bundle it in and serve it via a route on /*
. Depending on my need, I would also host the bundled files directly via nginx or from AppEngine.
This worked no problem, but there’s a few extra steps I had to worry about, such as if I was currently running the web server and frontend servers in the dev or production environments. With the above approach, I would have to rebuild the Go binary with the updated React bundle, which started taking more and more time. If I wanted to test with just yarn start
, I would encounter issues like CORS for localhost:3000->localhost:8080
communications which caused more problems than necessary.
To save myself the constant headache and juggling between the browser and terminal, I leveraged on of my favorite secret weapons: proxies.
The Art of Proxying
Proxies are something that many people immediately start to tremble at the sound of. Their minds draw them to big-brother like monitoring systems, watching everything they do, or giving them a way to get past their school or employers firewall configurations. Yet, proxies are much more than that.
Proxies give you control over the request flow, how a system sees it, and how a response is managed. When you’re developing locally, this give you the ability to imitate your upstream and production services without leaving your system.
How can we use a proxy to speed up development?
Getting a Closer Look
This pattern allows your web server to serve requests by either serving from the embedded filesystem, or by proxying the requests to the dev React instance. I usually use a BrowserRouter
from react-router-dom
in order to perform the browser-based frontend routing, so I listen on /*
to serve all requests for React.
I then configure my /api
route to serve all API-based traffic.
Now, all I need to do is access localhost:8080
in the browser after I run go run main.go
, and I’ll be greeted with my React interface. No more needing to worry about making requests to two different ports or different servers.
One Step Further
To make this process even better, stay tuned for a write up on how to use chainlink. Chainlink provides a DNS-proxy so you can intercept hostnames and rewrite localhost
to something more meaningful, while recursing all valid domains to your preferred DNS server.
Conclusion
As a developer and security engineer, I always put a special focus on the usability of the tools I am developing. I grew up in the age where enterprise tools only supported IE6 and the user experience was the last thing the developer could care about. However, there is a clear pattern of sales to tool usability, even if it does not provide better functionality. Look at something like Slack, compared to Microsoft Teams or Google Hangouts Chat. Both of the later platforms integrate perfectly with their respective workplace offerings, however the usability on Slack has an arguably lower entry level, and quicker time to success for new users.
Why go into all this extra detail on usability?
Testing is something that most devs have a hard time with. Local development of micro-services is hard. Traversing environments from dev to prod is hard. Testing and iteration-based development is hard. In 2021, there are a lot of different approaches we can take when writing code, testing, and deploying; but this is the only one pattern that I fell in love with.
Member discussion