A URL Is Not a Development Loop
DEV Community

A URL Is Not a Development Loop

Yesterday I wrote about why local development still feels strangely isolated. The obvious answer to that problem is usually some variation of: “Just expose the port.” And technically, yes. Congratulations, the URL now works somewhere else. But that only solves the least interesting part of the problem. What I care about with Relay is what happens after somebody connects. If I save a file locally, the connected client should update. If something breaks on their device, useful information should come back. If they move around the app, that context should not just disappear into the void. In other words, I don’t just want Relay to share a development server. I want it to preserve the development loop. The connection has to stay alive Modern development servers do a lot more than serve HTML and JavaScript. They keep long-lived connections open. They push updates. They expect the browser and the development server to keep talking to each other. Frameworks build their own assumptions on top of that, and they’re not always particularly shy about it. So if Relay is going to sit between a local development server and a connected client, it cannot just forward the first request and call it a day. HTTP needs to work. WebSockets need to work. Assets need to keep loading. Routes need to behave normally. HMR and Fast Refresh need to survive the connection. And when the developer saves a file, the person on the other side should see the result without waiting for another build, deployment, or the ceremonial “can you refresh?” message. That sounds simple when written as a paragraph. It is slightly less simple when several different frameworks all have their own ideas about how development traffic should behave. HMR is one of the bits that matters most One of the easiest ways for a shared development environment to stop feeling like a development environment is for live updates to disappear. If every code change turns into a full reload, or worse, requires the other person to manually refresh, you’ve already lost a lot of the value. Relay keeps the normal development connection intact, so frameworks can continue doing what they already do. With Vite-based applications, HMR continues across the Relay gateway. With React, Fast Refresh still works. Next.js and Turbopack have their own quirks, because apparently one straightforward implementation across every tool would have been too generous, but the same principle applies. Relay stays out of the application and preserves the traffic the framework expects. That means the developer’s workflow does not change just because somebody else is connected. Save the file. The framework notices. The update travels through Relay. The connected client changes. That’s the loop. Useful information has to come back too Getting live updates to the connected client is only one half of it. The other half is knowing what actually happened over there. Suppose QA is using the app on a physical device and hits an issue. Without that feedback loop, the conversation tends to become something like: “It broke.” “What broke?” “The page.” “Any errors?” “Where?” Which is not the most advanced debugging protocol we’ve ever invented. Relay sends useful diagnostics back from the connected client. That currently includes things like console output, JavaScript exceptions, failed HTTP requests and lower-level network failures. So while somebody is actually using the application, the developer can see what the client is reporting instead of trying to reconstruct it from screenshots and vague descriptions afterwards. The important part is that this diagnostic traffic stays separate from the application itself. Relay is not injecting a giant debugging runtime into the page or asking the app to send its own logs somewhere special. The application keeps behaving like the application. Relay handles the extra context around it. Why that changes collaboration This is where Relay starts becoming more useful than a simple preview link. A designer can try an interaction while the developer is still changing it, and see updates as they happen. QA can reproduce an issue on a real device while the developer watches the relevant errors come back. A senior developer helping somebody else does not necessarily need to recreate the entire problem locally before they can start understanding it. A technician can interact with the real thing while the developer sees how the application is behaving underneath. The connected client is no longer just somewhere the app happens to be visible. It becomes part of the development session. That distinction is what I keep coming back to. The boring plumbing is the product A lot of Relay is deliberately boring from the user’s point of view. That is a good thing. Nobody should have to care that WebSocket upgrade handling is working correctly. Nobody should need to know which headers a framework expects during HMR. Nobody should have to think about whether application cookies and Relay authentication are being kept separate. Those are Relay’s problems. The person using it should be able to start their app, connect another client, and keep working. The more invisible that plumbing becomes, the better the experience. Which is slightly unfortunate for me, because the invisible plumbing is where a fairly large amount of the engineering lives. What I’m working on next The basic two-way loop is already there: application traffic out, diagnostics back. The next pieces build on top of that. Route visibility and navigation are getting more attention, so the development machine can know where a connected client is in the application and control navigation when needed. From there, the interesting problem becomes synchronisation: keeping multiple clients on the same route without creating a delightful infinite navigation loop and ruining everybody’s afternoon. There are also more device controls, screenshots and broader diagnostics to layer in. But the underlying principle stays the same: A connected client should feel like part of the development environment, not just a browser that happens to know the URL. That is the bit I’m building Relay around. And, as ever, the apparently simple parts are doing an excellent job of finding increasingly creative ways not to be simple. Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.