Remix Dev Server #4664
Replies: 3 comments 1 reply
-
Love this effort. One clarifying question:
This is such a huge win with Remix today. I believe the answer is no, but would the above proposal compromise that? |
Beta Was this translation helpful? Give feedback.
-
The trick with stateful HMR is we want to know when to preserve state and when to refetch. Server changes I imagine we'd want to default to do a slow refetch, client side changes are a grey area in most apps though in Remix apps maybe a lot less so, CSS changes should always be almost instant, as they are in the browser dev tools. Is it possible to know what kind of code we've changed and refresh accordingly? |
Beta Was this translation helpful? Give feedback.
-
Is
|
Beta Was this translation helpful? Give feedback.
-
Nevermind! I assumed "we’ll stop barfing a billion files into the build and public/build directories" implied doing this in-memory, but that's not the case. |
Beta Was this translation helpful? Give feedback.
-
Remix Dev Server
Instead of just a file watcher that writes files with
remix watch
, we should have a dev server receive requests, serve the asset, then proxy everything else to the real server. This should make building developer tooling better for us and our users better (live reload, HMR, faster incremental builds, forwarding build errors to a browser modal, etc.)Background
Two important concepts drove today’s Remix’s
npm run dev
design:How it works today: two processes
Two Processes need to run for remix development today:
remix watch
and a command to run a server likenode server.js
orwrangler dev
etc.remix.config.js
to know where to write the server and client build artifacts. It does not receive requests, it just spits out files where the web server is reading from.node server.js
, requires the server build thatremix watch
created (it’s just a module in the end) and uses it as the request handler. When the page is viewed in the browser, the assetsremix watch
created are requested from the actual server, as long as it’s correctly configured to server them of course!In other words: dev and production are identical when it comes to what happens when a request for a document or a static asset is made. The server (
node server.js
) serves everything.remix watch
simply created the modules for the server and client. In this way, Remix can be deployed anywhere.The exception: remix dev + remix-serve
For developers who don’t care to run their own server, the
remix-serve
package creates an express app configured just enough to run a Remix app. It has an integration with the remix CLI to run both the watcher (fromremix watch
) and the express server in the same process.Problems today
Requiring two processes is annoying. Many developers today are not used to owning so much of the stack (which is why we created
remix-serve
).Ports and Live Reload. It’s actually surprisingly difficult to develop two Remix apps at the same time. When you have two processes you can’t simply provide a
--port 3001
cli option. You may dowrangler dev --port 3000
for one app andnodemon server.js --port 3001
in another. That’s fine for the servers but the live reload web socket, that’s part ofremix watch
needs to specify a port too, and that port needs to be known for both SSR (server bundles) and in the browser (client bundles). In order to get the correct web socket port for bothremix watch
andwrangler dev
, we use an environment variable which is not only cumbersome but also super weird: it’s read at runtime for the server render (actual environment variable) but bundled as a static value into the client modules (not actually an environment variable!).Perhaps in the live reload case, we could figure out a better way to do it (like a cli option that gets bundled directly into both client/server bundles) but it illustrates the point well that having two processes in development adds some complexity. In fact, there have been a bunch of breakages around live reload in various commits because folks both outside and inside of Remix because they didn’t understand all the moving parts.
Proposal
I’m proposing we change the way Remix works in development by introducing a development server. Instead of requests always coming to the real server in development (
node server.js
), requests come to a Remix development server.API
remix.config.js
has a newdev
field that indicates how to spawn your development serverremix dev
boots a development server that also spawns the real serverWhen a requests comes in, the dev server matches it against the
remix.config
for assets, if it matches, it serves the file (with some bundling). If it doesn’t match, it proxies the request to the real server.Expected benefits
Having a persistent dev server should make all of the “DX” things we want to do easier to deal with because we get to receive the requests first.
concurrently
andpm2-dev
have race conditions where the browser reloaded when files changed but the builds aren't done!The core benefit is that we are in control of when to notify the browser of anything with a persistent server that owns both processes. By spawning a child process for the real server, we also don’t lose the “development and production are nearly identical” either. All assets are bundled the same, served from the same URLs controlled by remix.config.
Beta Was this translation helpful? Give feedback.
All reactions