v1.12.0
We've got a few nice bug fixes and improvements in this release. You can catch those in the individual package changelogs below, but what we really want to talk about today is a huge step forward in a much nicer developer experience for you. Let's get to it!
An early peek at a new dev server 👀
Since the early days of Remix, the remix dev
command has been limited by its association with the built-in Remix app server while remix watch
simply watched your files and spit out builds, but doesn't handle requests like some other tools. But one of the major benefits of this is that Remix lets you own your server. While this is a very powerful core feature of our architecture, it presented a few challenges for local development. If you own your server, how can we build a dev server that is flexible enough to work for your specific setup?
Our first answer was … we don't. Don't try to be clever, don't over-abstract anything. Simply run the remix watch
, spit out files, and have <LiveReload>
tell the browser to reload. But we didn't know if your app server was done rebooting the server code! And in the case of remix dev
with remix-serve
, we didn't reboot the server, we simply wiped out the node require cache as a budget server side HMR.
There were a few downsides for local development with this:
- Clearing the require cache wipes in-memory references, such as database connections or in-memory caches. This means you have to use workaround like sticking flags on
global
to persist anything stored in memory across rebuilds. - Getting the web socket port to
remix watch
and over to your app server in a different process (whether it was express, netlify def, vercel dev, etc.) and using it inLiveReload
was a lot of unnecessary friction. - It makes implementing popular new dev features like hot-module replacement (HMR) much more difficult to implement in a way that works consistently across all app servers.
- Each rebuild writes new files to
build/
andpublic/build/
. As these files are not removed (unless the dev server crashes or is gracefully terminated), thousands of files could accumulate as the dev server ran. This causes performance issues and could be confusing when debugging.
To start addressing these issues, we decided to take a new approach. This release gives you early access to our new dev server and start making incremental improvements to your local development flow.
Please note that this is an unstable feature and a work-in-progress. But we think there are good reasons to opt in right away!
At this stage, the idea is to spin up the dev server alongside your normal Remix app server:
# spin up the new dev server
remix dev
# Spin up your app server in parallel.
# This can be done in a separate terminal or with a tool like `concurrently`.
nodemon --watch build/ ./server.js
Our dev server will build your app in development mode and then rebuild whenever any app files changes. It will also wait for your app server to signal that it's "ready" before triggering a reload in your browser.
No more wiping in-memory caches. No more weird hacks to keep your database alive. A fresh, clean slate for each rebuild.
While this may seem like a relatively small change, but it's removes a huge barrier for future DX improvements for local development. We think you're going to love what we're working on next 🔥🔁
Limitations
The new dev server does not currently work with Remix App Server (i.e. remix-serve
command) because Remix App Server hardcodes NODE_ENV=production
.
Rest assured, when the new dev server stabilizes it will support Remix App Server as well.
Configuring the unstable_dev
server
To enable the new dev server with all defaults, set the unstable_dev
future flag to true
:
// remix.config.js
module.exports = {
future: {
unstable_dev: true,
},
};
You can also set specific options. As this is an unstable feature, these options may change before the next major release.
// remix.config.js
module.exports = {
future: {
unstable_dev: {
// Port to use for the dev server (i.e. the <LiveReload> websocket)
// This can be overridden by a CLI flag: `remix dev --port 3011`
// By default, we will find an empty port and use that
port: 3010,
// Port for running your Remix app server
// This can be overridden by a CLI flag: `remix dev --app-server-port 3021`
// default: `3000`
appServerPort: 3020,
// Path to the Remix request handler in your app server
// Most app servers will route all requests to the Remix request
// handler and will not need this option. If your app server _does_
// route only certain request paths to the Remix request handler, then
// you'll need to set this.
// default: `""`
remixRequestHandlerPath: "/products",
// The number of milliseconds between "readiness" pings to your app server
// When a Remix rebuild finishes, the dev server will ping a special
// endpoint (`__REMIX_ASSETS_MANIFEST`) to check if your app server is
// serving up-to-date routes and assets. You can set this option to tune
// how frequently the dev server polls your app server.
// default: `50`
rebuildPollIntervalMs: 25,
},
},
};
Other Stuff
- Updated to latest
react-router
versions. See the release notes for more details.react-router-dom@6.8.0
@remix-run/router@1.3.1
- You can now configure the client-side socket timeout via the new
timeoutMs
prop on<LiveReload />
(#4036) <Link to>
can now accept absolute URLs. When theto
value is an absolute URL, the underlying anchor element will behave as normal, and its URL will not be prefetched. (#5092)- Added support for
unstable_useBlocker
andunstable_usePrompt
from React Router (#5151) - Removed
react
&react-dom
frompeerDependencies
(#4801)