@vercel/remix
Advanced tools
Changelog
v2.3.0
Date: 2023-11-16
useBlocker
We've removed the unstable_
prefix from the useBlocker
hook as it's been in use for enough time that we are confident in the API. We do not plan to remove the prefix from unstable_usePrompt
due to differences in how browsers handle window.confirm
that prevent React Router from guaranteeing consistent/correct behavior.
unstable_flushSync
APIWe've added a new unstable_flushSync
option to the imperative APIs (useSubmit
, useNavigate
, fetcher.submit
, fetcher.load
) to let users opt-into synchronous DOM updates for pending/optimistic UI.
function handleClick() {
submit(data, { flushSync: true });
// Everything is flushed to the DOM so you can focus/scroll to your pending/optimistic UI
setFocusAndOrScrollToNewlyAddedThing();
}
unstable_
prefix from the useBlocker
hook (#7882)unstable_flushSync
option to useNavigate
/useSubmit
/fetcher.load
/fetcher.submit
to opt-out of React.startTransition
and into ReactDOM.flushSync
for state updates (#7996)@remix-run/react
: Add missing modulepreload
for the manifest (#7684)@remix-run/server-runtime
: Updated cookie
dependency from 0.4.1
to 0.5.0
to inherit support for Priority
attribute in Chrome (#6770)@remix-run/dev
: Fix FutureConfig
type (#7895)vite
compiler:
LiveReload
component in Vite dev (#7919)LiveReload
component after Scripts
in Vite dev (#7919)react-refresh/babel
resolution for custom server with pnpm
(#7904).jsx
files without manual React
import in Vite (#7888)development
and production
modes are present (e.g. @mdx-js/rollup
) (#7911)process.env.NODE_ENV
values other than "development"
in Vite dev (#7980)/@fs
(#7913)
server.fs.allow
@remix-run/react
(#7926)
remix-react-proxy
plugin does not process default client and server entry files since those come from within node_modules
Error: You must render this element inside a <Remix> element
defer
in Vite dev server (#7842)Set-Cookie
headers in Vite dev server (#7843)process.env
from .env
files on the server in Vite dev (#7958)8cd31d65
)create-remix
@remix-run/architect
@remix-run/cloudflare
@remix-run/cloudflare-pages
@remix-run/cloudflare-workers
@remix-run/css-bundle
@remix-run/deno
@remix-run/dev
@remix-run/eslint-config
@remix-run/express
@remix-run/node
@remix-run/react
@remix-run/serve
@remix-run/server-runtime
@remix-run/testing
Full Changelog: v2.2.0...v2.3.0
Changelog
v2.2.0
Date: 2023-10-31
Remix 2.2.0
adds unstable support for Vite for Node-based apps! See our announcement blog post and the Future > Vite page in the Remix docs for more details.
You can try it out today with two new (unstable) templates:
# minimal server
npx create-remix@latest --template remix-run/remix/templates/unstable-vite
# custom server (Express example)
npx create-remix@latest --template remix-run/remix/templates/unstable-vite-express
@remix-run/dev
unstable_vitePlugin
: The new Remix Vite pluginunstable_createViteServer
: Creates a Vite server in middleware mode for interop with custom serversunstable_loadViteServerBuild
: Allows your custom server to delegate SSR requests to Vite during developmentcreateRequestHandler
: Now also allows the build
argument to be a function that will be used to dynamically load new builds for each request during developmentnpm
interopPer this RFC, we've introduced some new APIs that give you more granular control over your fetcher behaviors:
useFetcher({ key: string })
, which allows you to access the same fetcher instance from different components in your application without prop-drillinguseFetchers
so that they can be looked up by key
Form
and useSubmit
now support optional navigate
/fetcherKey
props/params to allow kicking off a fetcher submission under the hood with an optionally user-specified key
<Form method="post" navigate={false} fetcherKey="my-key">
submit(data, { method: "post", navigate: false, fetcherKey: "my-key" })
useFetchers()
or useFetcher({ key })
to look it up elsewherePer the same RFC as above, we've introduced a new future.v3_fetcherPersist
flag that allows you to opt-into the new fetcher persistence/cleanup behavior. Instead of being immediately cleaned up on unmount, fetchers will persist until they return to an idle
state. This makes pending/optimistic UI much easier in scenarios where the originating fetcher needs to unmount.
useFetchers()
API was always supposed to only reflect in-flight fetcher information for pending/optimistic UI -- it was not intended to reflect fetcher data or hang onto fetchers after they returned to an idle
stateuseFetchers()
after completion - they served no purpose in there since you can access the data via useFetcher().data
idle
state
useFetchers
while in-flight so you can still access pending/optimistic data after unmountkey
, then it's result will be processed, even if the originating fetcher was unmountedvite
support (#7590)key
APIs and navigate
/fetcherKey
params for navigational APIs (#10960)future.v3_fetcherPersist
flag (#10962)@remix-run/express
: Allow the Express adapter to work behind a proxy when using app.enable('trust proxy')
(#7323)
req.get('host')
to construct the Remix Request
, but that does not respect X-Forwarded-Host
req.hostname
which will respect X-Forwarded-Host
@remix-run/react
: Fix warning that could be inadvertently logged when using route files with no default
export (#7745)create-remix
: Support local tarballs with a .tgz
extension which allows direct support for pnpm pack
tarballs (#7649)create-remix
: Default the Remix app version to the version of create-remix
being used (#7670)
npm create remix@nightly
create-remix
@remix-run/architect
@remix-run/cloudflare
@remix-run/cloudflare-pages
@remix-run/cloudflare-workers
@remix-run/css-bundle
@remix-run/deno
@remix-run/dev
@remix-run/eslint-config
@remix-run/express
@remix-run/node
@remix-run/react
@remix-run/serve
@remix-run/server-runtime
@remix-run/testing
Full Changelog: v2.1.0...v2.2.0
Changelog
v2.1.0
Date: 2023-10-16
We're excited to release experimental support for the the View Transitions API in Remix! You can now trigger navigational DOM updates to be wrapped in document.startViewTransition
to enable CSS animated transitions on SPA navigations in your application.
The simplest approach to enabling a View Transition in your Remix app is via the new <Link unstable_viewTransition>
prop. This will cause the navigation DOM update to be wrapped in document.startViewTransition
which will enable transitions for the DOM update. Without any additional CSS styles, you'll get a basic cross-fade animation for your page.
If you need to apply more fine-grained styles for your animations, you can leverage the unstable_useViewTransitionState
hook which will tell you when a transition is in progress and you can use that to apply classes or styles:
function ImageLink(to, src, alt) {
const isTransitioning = unstable_useViewTransitionState(to);
return (
<Link to={to} unstable_viewTransition>
<img
src={src}
alt={alt}
style={{
viewTransitionName: isTransitioning ? "image-expand" : "",
}}
/>
</Link>
);
}
You can also use the <NavLink unstable_viewTransition>
shorthand which will manage the hook usage for you and automatically add a transitioning
class to the <a>
during the transition:
a.transitioning img {
view-transition-name: "image-expand";
}
<NavLink to={to} unstable_viewTransition>
<img src={src} alt={alt} />
</NavLink>
For an example usage of View Transitions, check out our fork of the Astro Records demo (which uses React Router but so does Remix š).
For more information on using the View Transitions API, please refer to the Smooth and simple transitions with the View Transitions API guide from the Google Chrome team.
createRemixStub
After real-world experience, we're confident in the createRemixStub
API and ready to commit to it, so in 2.1.0
we've removed the unstable_
prefix.
ā ļø Please note that this did involve 1 small breaking change - the <RemixStub remixConfigFuture>
prop has been renamed to <RemixStub future>
to decouple the future
prop from a specific file location.
@remix-run/testing
createRemixStub
helper (#7647)JSON.parse(JSON.stringify(x))
in SerializeFrom
(#7605)
undefined
after serialization are now omitted since JSON.stringify |> JSON.parse
will omit them. See test cases for examplesmeta
object when tagName
is specified (#7594)route.lazy
routes (#7576)useMatches
wrapper to fix UIMatch
typings (#7551)@remix-run/cloudflare
- sourcemap takes into account special chars in output file (#7574)@remix-run/express
- Flush headers for text/event-stream
responses (#7619)create-remix
@remix-run/architect
@remix-run/cloudflare
@remix-run/cloudflare-pages
@remix-run/cloudflare-workers
@remix-run/css-bundle
@remix-run/deno
@remix-run/dev
@remix-run/eslint-config
@remix-run/express
@remix-run/node
@remix-run/react
@remix-run/serve
@remix-run/server-runtime
@remix-run/testing
Full Changelog: v2.0.1...v2.1.0
Changelog
v2.0.1
Date: 2023-09-21
getDependenciesToBundle
to handle ESM packages without main exports (#7272)
package.json
in their exports
field so that their path can be resolvedserverBuildPath
extension is .cjs
(#7180)remix-serve
and manual mode (remix dev --manual
) (#7487)
require
cache, remix-serve
now correctly re-imports new server changes in CJSbuild.assets
being undefined and crashing when reading build.assets.version
UIMatch
for handle
field (#7464)route.lazy
(#7498)ErrorResponse
instead of just an Error
when submitting to a route without an action
(#7423)@remix-run/web-fetch
(#7477)crypto.randomBytes
to crypto.webcrypto.getRandomValues
for file session storage ID generation (#7203)Blob
class instead of polyfill (#7217)Full Changelog: v2.0.0...v2.0.1
Changelog
v2.0.0
Date: 2023-09-15
We're so excited to release Remix v2 to you and we really hope this upgrade is one of the smoothest framework upgrades you've ever experienced! That was our primary goal with v2 - something we aimed to achieve through a heavy use of deprecation warnings and Future Flags in Remix v1.
If you are on the latest 1.x
version and you've enabled all future flags and addressed all console warnings, then our hope is that you are 90% of the way to being upgraded for v2. There are always going to be a few things that we can't put behind a flag (like breaking type changes) or come up at the very last moment and don't have time to add as a warning or flag in 1.x
.
If you're not yet on the latest 1.x version we'd recommend first upgrading to that and resolving any flag/console warnings:
> npx upgrade-remix 1.19.3
Below is a very concise list of the breaking changes in v2.
Remix v2 has upgraded it's minimum version support for React and Node and now officially requires:
The following future flags were removed and their behavior is now the default - you can remove all of these from your remix.config.js
file.
v2_dev
- New dev server with HMR+HDR (#7002)
future.v2_dev
instead of just the boolean value (i.e., future.v2_dev.port
), you can lift them into a root dev
object in your remix.config.js
v2_errorBoundary
- Removed CatchBoundary
in favor of a singular ErrorBoundary
(#6906)v2_headers
- Altered the logic for headers
in nested route scenarios (#6979)v2_meta
- Altered the return format of meta()
(#6958)v2_normalizeFormMethod
- Normalize formMethod
APIs to uppercase (#6875)v2_routeConvention
- Routes use a flat route convention by default now (#6969)The following lists other breaking changes/API removals which had deprecation warnings in Remix v1. If you're on the latest 1.19.3
release without any console warnings, then you're probably good to go on all of these!
remix.config.js
browserBuildDirectory
to assetsBuildDirectory
(#6900)devServerBroadcastDelay
(#7063)devServerPort
to dev.port
(000457e0
)
1.x
release, your config flag will be future.v2_dev.port
, but on a stable 2.x
release it will be dev.port
serverModuleFormat
from cjs
to esm
(#6949)serverBuildTarget
(#6896)serverBuildDirectory
to serverBuildPath
(#6897)serverNodeBuiltinsPolyfill
(#6911@remix-run/react
useTransition
(#6870)fetcher.type
and flattened fetcher.submission
(#6874)
<fetcher.Form method="get">
is now more accurately categorized as state:"loading"
instead of state:"submitting"
to better align with the underlying GET requestimagesrcset
/imagesizes
(#6936)Unfortunately, we didn't manage to get a deprecation warning on every breaking change or API removal š. Here's a list of remaining changes that you may need to look into to upgrade to v2:
remix.config.js
browserNodeBuiltinsPolyfill
(#7269)postcss
and tailwind
flags (#6909)@remix-run/cloudflare
@remix-run/dev
REMIX_DEV_HTTP_ORIGIN
in favor of REMIX_DEV_ORIGIN
(#6963)REMIX_DEV_SERVER_WS_PORT
in favor of dev.port
or --port
(#6965)--no-restart
/restart
flag in favor of --manual
/manual
(#6962)--scheme
/scheme
and --host
/host
in favor of REMIX_DEV_ORIGIN
instead (#6962)codemod
command (#6918)@remix-run/eslint-config
@remix-run/netlify
@remix-run/netlify
adapter has been removed in favor of the Netlify official adapters (#7058)@remix-run/node
fetch
is no longer polyfilled by default - apps must call installGlobals()
to install the polyfills (#7009)fetch
and related APIs are no longer exported from @remix-run/node
- apps should use the versions in the global namespace (#7293)sourceMapSupport.install()
to setup source map support@remix-run/react
unstable_shouldReload
in favor of shouldRevalidate
(#6865)@remix-run/serve
@remix-run/vercel
@remix-run/vercel
adapter has been removed in favor of out of the box functionality provided by Vercel (#7035)create-remix
isTypeScript
to remix.init
script (#7099)remix
V2_
prefixes from future.v2_meta
types as they are now the default behavior (#6958)
V2_MetaArgs
-> MetaArgs
V2_MetaDescriptor
-> MetaDescriptor
V2_MetaFunction
-> MetaFunction
V2_MetaMatch
-> MetaMatch
V2_MetaMatches
-> MetaMatches
V2_ServerRuntimeMetaArgs
-> ServerRuntimeMetaArgs
V2_ServerRuntimeMetaDescriptor
-> ServerRuntimeMetaDescriptor
V2_ServerRuntimeMetaFunction
-> ServerRuntimeMetaFunction
V2_ServerRuntimeMetaMatch
-> ServerRuntimeMetaMatch
V2_ServerRuntimeMetaMatches
-> ServerRuntimeMetaMatches
unknown
over any
and to align with underlying React Router types (#7319):
useMatches()
return type from RouteMatch
to UIMatch
LoaderArgs
/ActionArgs
to LoaderFunctionArgs
/ActionFunctionArgs
AppData
changed from any
to unknown
Location["state"]
(useLocation.state
) changed from any
to unknown
UIMatch["data"]
(useMatches()[i].data
) changed from any
to unknown
UIMatch["handle"]
(useMatches()[i].handle
) changed from { [k: string]: any }
to unknown
Fetcher["data"]
(useFetcher().data
) changed from any
to unknown
MetaMatch.handle
(used in meta()
) changed from any
to unknown
AppData
/RouteHandle
are no longer exported as they are just aliases for unknown
create-remix
CLI (#6887)
--template
flag and our ever-growing list of available templates--overwrite
flag (#7062)bun
package manager (#7074)build.mode
(#6964)serverNodeBuiltinsPolyfill.globals
/browserNodeBuiltinsPolyfill.globals
(#7269)redirectDocument
utility to redirect via a fresh document load (#7040, #6842)error
to meta
params so you can render error titles, etc. (#7105)unstable_createRemixStub
now supports adding meta
/links
functions on stubbed Remix routes (#7186)
unstable_createRemixStub
no longer supports the element
/errorElement
properties on routes. You must use Component
/ErrorBoundary
to match what you would export from a Remix route module.route.lazy
method internally to load route modules on navigations (#7133)@remix-run/node
atob
/btoa
polyfills in favor of the built-in versions (#7206)@remix-run/dev
package from the contents of the @remix-run/css-bundle
package (#6982)
@remix-run/css-bundle
package are now entirely managed by the Remix compiler. Even though it's still recommended that your Remix dependencies all share the same version, this change ensures that there are no runtime errors when upgrading @remix-run/dev
without upgrading @remix-run/css-bundle
.remix-serve
now picks an open port if 3000 is taken (#7278)
PORT
env var is set, remix-serve
will use that portremix-serve
picks an open port (3000 unless that is already taken)react-router-dom@6.16.0
@remix-run/router@1.9.0
@remix-run/web-fetch@4.4.0
@remix-run/web-file@3.1.0
@remix-run/web-stream@1.1.0