Pre-release Changes
-
BREAKING CHANGE: Middleware consumed through
remix/routerandremix/fetch-routermust now explicitly continue the request chain by callingnext()or return aResponse. Middleware that returnedundefinedwithout callingnext()now throws at runtime instead of implicitly continuing.Update context-loading middleware to return the downstream response:
function loadUser(): Middleware { return (context, next) => { context.set(CurrentUser, user) return next() } }
-
Improve Node compatibility for the
remix/assertentrypoint.The default export is now callable as an alias for
assert.ok, failure errors expose Node-style metadata, expected-error/message handling more closely followsnode:assert/strict, strict/deep equality now handlesObject.isand built-in object comparisons more consistently with Node, andassert.partialDeepEqualis available for strict partial deep comparisons. -
Add
router.mount()and theRouteBuilder/RouteInstallertypes toremix/routerandremix/fetch-routerso larger apps can be built from smaller route groups without making feature modules hard-code their final URL. A feature module can now export a local route installer that registers routes like/,/users/:id, or a route map, and the parent can mount it at/admin,/orgs/:orgId, or another route pattern prefix while one router still owns request dispatch, matching, middleware, and default handling. Params from the mount pattern are available to mounted handlers, and duplicate param names followroute-patternbehavior where the right-most param wins.RouterContext<typeof router>extracts the request context provided by a router or route builder, so apps can keep root middleware inline and use that router-derived context forRouterTypes.context.createAction(), direct action objects, andcreateController()now infer middleware-provided values from plain inline middleware arrays, which removes the usual need for intermediateMiddlewareContext<...>aliases and explicit generics in stored actions and controllers.createMiddleware()creates reusable middleware chains that preserve their tuple type withoutas constin the specific cases where a chain crosses an inference boundary: derivingMiddlewareContext<typeof rootMiddleware>without a router value, exporting a reusable chain, or returning a chain from a factory. Prefer inline arrays for ordinarymiddlewareoptions on routers, controllers, actions, and route helpers.Middlewareis now a callable type alias with type-only context metadata, which preserves inline middleware context transforms more reliably than an interface call signature.The re-exported router types also keep
createRouter()androuter.map()to single call signatures while preserving route params, middleware context inference, and stored action/controller compatibility checks, making the public type surface smaller while everyday route setup gets more expressive.BREAKING CHANGE:
MapTargetandMapHandlerare no longer re-exported fromremix/routerorremix/fetch-router. Use the publicRouter,RouteBuilder,RouteInstaller,Action, andControllertypes instead. -
Expose
remix/testtimeout and abort signal support through the Remix package.Tests and lifecycle hooks can pass
{ timeout, signal }, andt.signalaborts when a test times out. Stringskip/todoreasons now flow throughremix/testresults and reporter output. -
Keep generated README mirrors in the published
remixpackage sonode_modules/remix/src/<subpath>/README.mddocumentation remains available while the duplicated source files stay untracked in git. -
Bumped
@remix-run/*dependencies:assert@0.3.0assets@0.4.3async-context-middleware@0.3.3auth@0.2.5auth-middleware@0.2.3cli@0.3.3compression-middleware@0.1.11cop-middleware@0.1.6cors-middleware@0.1.6csrf-middleware@0.1.6fetch-router@0.20.0form-data-middleware@0.3.3logger-middleware@0.3.3method-override-middleware@0.1.11render-middleware@0.1.3route-pattern@0.22.1session-middleware@0.3.3static-middleware@0.4.12test@0.5.0