This page lists all releases/release notes for Remix back to v2.0.0
. For releases prior to v2, please refer to the Github Releases Page.
We manage release notes in this file instead of the paginated Github Releases Page for 2 reasons:
Date: 2024-02-21
.css?url
imports (#8829)Date: 2024-02-20
@remix-run/cloudflare-pages
(#8819)
getLoadContext
argument for backwards compatibility.Date: 2024-02-20
We're excited to announce that support for Vite is now stable in Remix 2.7.0
! Ever since the initial unstable release of Remix Vite, weāve been hard at work refining and extending it over the past few months with help from all of our early adopters and community contributors. This also means that Vite-only features such as SPA Mode, Server Bundles, and basename
support are now officially stable as well š.
For more information, check out the blog post and the Vite docs.
Layout
ExportWe've found that it's super common to create your own component in your root route to hold the shared layout/app shell between your Component
/ErrorBoundary
/HydrateFallback
. This is so common (and can also cause some minor edge-case issues such as a FOUC on hydration) that we've incorporated this as a first-class API in 2.7.0
.
You can now export an optional Layout
component from your root route which will be provided your route component, ErrorBoundary, or HydrateFallback as it's children
. For more information, please see the Layout
docs and the RFC.
React Router has long supported a basename
config that allows you to serve your app within a subpath such as http://localhost/myapp/*
without having to include the /myapp
segment in all of your route paths. This was originally omitted from Remix because v1 nested folders file-convention made it pretty easy to put your route files in a routes/myapp/
folder, giving you the same functionality. There has also been an open proposal from the community to add this functionality.
Two things have since changed that made us reconsider the lack of basename
support:
myapp.
compared to the nested folder conventionbase
config which is often (and easily) confused with the concept of a React Router basename
(when in reality it's more aligned with the old Remix publicPath
config)In 2.7.0
we've added support for a basename
in the Vite plugin config. For more information, please check out the basename
docs.
Note: This is a Vite-only feature and is not available via the esbuild
compiler.
ā ļø This is a breaking change for projects relying on Cloudflare support from the unstable Vite plugin
The Cloudflare preset (unstable_cloudflarePreset
) as been removed and replaced with a new Vite plugin:
import {
unstable_vitePlugin as remix,
- unstable_cloudflarePreset as cloudflare,
+ cloudflareDevProxyVitePlugin as remixCloudflareDevProxy,
} from "@remix-run/dev";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
+ remixCloudflareDevProxy(),
+ remix(),
- remix({
- presets: [cloudflare()],
- }),
],
- ssr: {
- resolve: {
- externalConditions: ["workerd", "worker"],
- },
- },
});
A few notes on the new plugin:
remixCloudflareDevProxy
must come before the remix
plugin so that it can override Vite's dev server middleware to be compatible with Cloudflare's proxied environmentremixCloudflareDevProxy
can set ssr.resolve.externalConditions
to be workerd
-compatible for youremixCloudflareDevProxy
accepts a getLoadContext
function that replaces the old getRemixDevLoadContext
nightly
version that required getBindingsProxy
or getPlatformProxy
, that is no longer requiredgetBindingsProxy
or getPlatformProxy
should now be passed to remixCloudflareDevProxy
instead@remix-run/react
- Allow an optional Layout
export from the root route (#8709)@remix-run/cloudflare-pages
- Make getLoadContext
optional for Cloudflare Pages (#8701)
(context) => ({ env: context })
, which is what we used to have in all the templates@remix-run/dev
- Vite: Cloudflare Proxy as a Vite plugin (#8749)
@remix-run/dev
- Vite: Add a new basename
option to the Vite plugin, allowing users to set the internal React Router basename
in order to to serve their applications underneath a subpath (#8145)@remix-run/dev
- Vite: Stabilize the Remix Vite plugin, Cloudflare preset, and all related types by removing all unstable_
/ Unstable_
prefixes (#8713)
@remix-run/dev
- Vite: Stabilize "SPA Mode" by renaming the Remix vite plugin config from unstable_ssr -> ssr
(#8692)@remix-run/express
- Use req.originalUrl
instead of req.url
so that Remix sees the full URL (#8145)
@remix-run/react
- Fix a bug with SPA mode when the root route had no children (#8747)@remix-run/server-runtime
- Add a more specific error if a user returns a defer
response from a resource route (#8726)@remix-run/dev
- Always prepend DOCTYPE
in SPA mode entry.server.tsx
, can opt out via remix reveal (#8725)@remix-run/dev
- Fix build issue in SPA mode when using a basename
(#8720)@remix-run/dev
- Fix type error in Remix config for synchronous routes
function (#8745)@remix-run/dev
- Vite: Fix issue where client route file requests fail if search params have been parsed and serialized before reaching the Remix Vite plugin (#8740)@remix-run/dev
- Vite: Validate that the MDX Rollup plugin, if present, is placed before Remix in Vite config (#8690)@remix-run/dev
- Vite: Fix issue resolving critical CSS during development when the current working directory differs from the project root (#8752)@remix-run/dev
- Vite: Require version 5.1.0
to support .css?url
imports (#8723)@remix-run/dev
- Vite: Support Vite 5.1.0
's .css?url
imports (#8684)@remix-run/dev
- Vite: Enable use of vite preview
to preview Remix SPA applications (#8624)
npm run start
has been renamed to npm run preview
which uses vite preview
instead of a standalone HTTP server such as http-server
or serv-cli
@remix-run/dev
- Vite: Remove the ability to pass publicPath
as an option to the Remix vite plugin (#8145)
publicPath
base
config so we now set the Remix publicPath
from the Vite base
config@remix-run/dev
- Vite: Enable HMR for .md
and .mdx
files (#8711)@remix-run/dev
- Vite: reliably detect non-root routes in Windows (#8806)@remix-run/dev
- Vite: Pass remixUserConfig
to preset remixConfig
hook (#8797)@remix-run/dev
- Vite: Ensure CSS file URLs that are only referenced in the server build are available on the client (#8796)@remix-run/dev
- Vite: fix server exports dead-code elimination for routes outside of app directory (#8795)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.6.0...v2.7.0
Date: 2024-02-01
As we continue moving towards stabilizing the Vite plugin, we've introduced a few breaking changes to the unstable Vite plugin in this release. Please read the @remix-run/dev
changes below closely and update your app accordingly if you've opted into using the Vite plugin.
We've also removed the unstable_
prefix from the serverBundles
option as we're now confident in the API (#8596).
š And last, but certainly not least - we've added much anticipated Cloudflare support in #8531! To get started with Cloudflare, you can use the unstable-vite-cloudflare
template:
npx create-remix@latest --template remix-run/remix/templates/unstable-vite-cloudflare
For more information, please refer to the docs at Future > Vite > Cloudflare and Future > Vite > Migrating > Migrating Cloudflare Functions.
@remix-run/server-runtime
- Add future.v3_throwAbortReason
flag to throw request.signal.reason
when a request is aborted instead of an Error
such as new Error("query() call aborted: GET /path")
(#8251)@remix-run/server-runtime
- Unwrap thrown Response
's from entry.server
into ErrorResponse
's and preserve the status code (#8577)
@remix-run/dev
- Vite: Add manifest
option to Vite plugin to enable writing a .remix/manifest.json
file to the build directory (#8575)
build/server/bundles.json
file has been superseded by the more general build/.remix/manifest.json
manifest
option@remix-run/dev
- Vite: Rely on Vite plugin ordering (#8627)
ā ļø This is a breaking change for projects using the unstable Vite plugin
The Remix plugin expects to process JavaScript or TypeScript files, so any transpilation from other languages must be done first.
For example, that means putting the MDX plugin before the Remix plugin:
import mdx from "@mdx-js/rollup";
import { unstable_vitePlugin as remix } from "@remix-run/dev";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
+ mdx(),
remix()
- mdx(),
],
});
Previously, the Remix plugin misused enforce: "post"
from Vite's plugin API to ensure that it ran last
However, this caused other unforeseen issues
Instead, we now rely on standard Vite semantics for plugin ordering
The official Vite React SWC plugin also relies on plugin ordering for MDX
@remix-run/dev
- Vite: Remove interop with <LiveReload />
, rely on <Scripts />
instead (#8636)
ā ļø This is a breaking change for projects using the unstable Vite plugin
Vite provides a robust client-side runtime for development features like HMR, making the <LiveReload />
component obsolete
In fact, having a separate dev scripts component was causing issues with script execution order
To work around this, the Remix Vite plugin used to override <LiveReload />
into a bespoke implementation that was compatible with Vite
Instead of all this indirection, now the Remix Vite plugin instructs the <Scripts />
component to automatically include Vite's client-side runtime and other dev-only scripts
To adopt this change, you can remove the LiveReload component from your root.tsx
component:
import {
- LiveReload,
Outlet,
Scripts,
}
export default function App() {
return (
<html>
<head>
</head>
<body>
<Outlet />
<Scripts />
- <LiveReload />
</body>
</html>
)
}
@remix-run/dev
- Vite: Only write Vite manifest files if build.manifest
is enabled within the Vite config (#8599)
ā ļø This is a breaking change for consumers of Vite's manifest.json
files
To explicitly enable generation of Vite manifest files, you must set build.manifest
to true
in your Vite config:
export default defineConfig({
build: { manifest: true },
// ...
});
@remix-run/dev
- Vite: Add new buildDirectory
option with a default value of "build"
(#8575)
ā ļø This is a breaking change for consumers of the Vite plugin that were using the assetsBuildDirectory
and serverBuildDirectory
options
This replaces the old assetsBuildDirectory
and serverBuildDirectory
options which defaulted to "build/client"
and "build/server"
respectively
The Remix Vite plugin now builds into a single directory containing client
and server
directories
If you've customized your build output directories, you'll need to migrate to the new buildDirectory
option, e.g.:
import { unstable_vitePlugin as remix } from "@remix-run/dev";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
remix({
- serverBuildDirectory: "dist/server",
- assetsBuildDirectory: "dist/client",
+ buildDirectory: "dist",
})
],
});
@remix-run/dev
- Vite: Write Vite manifest files to build/.vite
directory rather than being nested within build/client
and build/server
directories (#8599)
manifest.json
filesmanifest.json
build/.vite/client-manifest.json
and build/.vite/server-manifest.json
, or build/.vite/server-{BUNDLE_ID}-manifest.json
when using server bundles@remix-run/dev
- Vite: Remove unstable
prefix from serverBundles
option (#8596)
@remix-run/dev
- Vite: Add --sourcemapClient
and --sourcemapServer
flags to remix vite:build
(#8613)
--sourcemapClient
, --sourcemapClient=inline
, or --sourcemapClient=hidden
--sourcemapServer
, --sourcemapServer=inline
, or --sourcemapServer=hidden
@remix-run/dev
- Vite: Validate IDs returned from the serverBundles
function to ensure they only contain alphanumeric characters, hyphens and underscores (#8598)
@remix-run/dev
- Vite: Fix "could not fast refresh" false alarm (#8580)
meta
for fast refresh, which removes the false alarm.@remix-run/dev
- Vite: Cloudflare Pages support (#8531)
@remix-run/dev
- Vite: Add getRemixDevLoadContext
option to Cloudflare preset (#8649)
@remix-run/dev
- Vite: Remove undocumented backwards compatibility layer for Vite v4 (#8581)
@remix-run/dev
- Vite: Add presets
option to ease integration with different platforms and tools (#8514)
@remix-run/dev
- Vite: Add buildEnd
hook (#8620)
@remix-run/dev
- Vite: Add mode
field into generated server build (#8539)
@remix-run/dev
- Vite: Reduce network calls for route modules during HMR (#8591)
@remix-run/dev
- Vite: Export Unstable_ServerBundlesFunction
and Unstable_VitePluginConfig
types (#8654)
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.5.1...v2.6.0
Date: 2024-01-18
create-remix
- high-contrast fg/bg for header colors (#8503)
bgWhite
and whiteBright
are the same color in many terminal colorthemes, which was causing it to render as illegible white-on-white@remix-run/dev
- Add isSpaMode
to @remix-run/dev/server-build
virtual module (#8492)@remix-run/dev
- SPA Mode: Automatically prepend <!DOCTYPE html>
if not present to fix quirks mode warnings for SPA template (#8495)@remix-run/dev
- Vite: Errors for server-only code point to new docs (#8488)@remix-run/dev
- Vite: Fix HMR race condition when reading changed file contents (#8479)@remix-run/dev
- Vite: Tree-shake unused route exports in the client build (#8468)@remix-run/dev
- Vite: Performance profiling (#8493)
remix vite:build --profile
to generate a .cpuprofile
that can be shared or uploaded to speedscope.appp + enter
to start a new profiling session or stop the current sessionremix vite:dev --profile
to initialize the dev server with a running profiling session@remix-run/dev
- Vite: Improve performance of dev server requests by invalidating Remix's virtual modules on relevant file changes rather than on every request (#8164)@remix-run/react
- Remove leftover unstable_
prefix from Blocker
/BlockerFunction
types (#8530)@remix-run/react
- Only use active matches in <Meta>
/<Links>
in SPA mode (#8538)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.5.0...v2.5.1
Date: 2024-01-11
SPA Mode (RFC) allows you to generate your Remix app as a standalone SPA served from a static index.html
file. You can opt into SPA Mode by setting unstable_ssr: false
in your Remix Vite plugin config:
// vite.config.ts
import { unstable_vitePlugin as remix } from "@remix-run/dev";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [remix({ unstable_ssr: false })],
});
Development in SPA Mode is just like a normal Remix app, and still uses the Remix dev server for HMR/HDR:
remix vite:dev
Building in SPA Mode will generate an index.html
file in your client assets directory:
remix vite:build
To run your SPA, you serve your client assets directory via an HTTP server:
npx http-server build/client
For more information, please refer to the SPA Mode docs.
This is an advanced feature designed for hosting provider integrations where you may want to split server code into multiple request handlers. When compiling your app into multiple server bundles, there will need to be a custom routing layer in front of your app directing requests to the correct bundle. This feature is currently unstable and only designed to gather early feedback.
You can control the server bundles generated by your Remix Vite build by setting the unstable_serverBundles
option in your vite config:
import { unstable_vitePlugin as remix } from "@remix-run/dev";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
remix({
unstable_serverBundles: ({ branch }) => {
const isAuthenticatedRoute = branch.some(
(route) => route.id === "routes/_authenticated"
);
return isAuthenticatedRoute ? "authenticated" : "unauthenticated";
},
}),
],
});
unstable_serverBundles
option to Vite plugin to support splitting server code into multiple request handlers (#8332)create-remix
: Only update *
versions for Remix dependencies (#8458)remix-serve
: Don't try to load sourcemaps if they don't exist on disk (#8446)@remix-run/dev
: Fix issue with isbot@4
released on 1/1/2024 (#8415)
remix dev
will now add "isbot": "^4"
to package.json
instead of using latest
entry.server
files to work with both isbot@3
and isbot@4
for backwards-compatibility with Remix apps that have pinned isbot@3
isbot@4
moving forward via create-remix
@remix-run/dev
: Vite - Fix HMR issues when altering exports for non-rendered routes (#8157)@remix-run/dev
: Vite - Default NODE_ENV
to "production"
when running remix vite:build
command (#8405)@remix-run/dev
: Vite - Remove Vite plugin config option serverBuildPath
in favor of separate serverBuildDirectory
and serverBuildFile
options (#8332)@remix-run/dev
: Vite - Loosen strict route exports restriction, reinstating support for non-Remix route exports (#8420)@remix-run/react
: Vite - Fix type conflict with import.meta.hot
from the existing Remix compiler (#8459)@remix-run/server-runtime
: Updated cookie
dependency to 0.6.0
to inherit support for the Partitioned
attribute (#8375)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.4.1...v2.5.0
Date: 2023-12-22
@remix-run/dev
: Vite - Remove unstable_viteServerBuildModuleId
in favor of manually referencing virtual module name "virtual:remix/server-build"
(#8264)
ā ļø This is a breaking change for projects using the unstable Vite plugin with a custom server
This change was made to avoid issues where @remix-run/dev
could be inadvertently required in your server's production dependencies.
Instead, you should manually write the virtual module name "virtual:remix/server-build"
when calling ssrLoadModule
in development.
-import { unstable_viteServerBuildModuleId } from "@remix-run/dev";
// ...
app.all(
"*",
createRequestHandler({
build: vite
- ? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId)
+ ? () => vite.ssrLoadModule("virtual:remix/server-build")
: await import("./build/server/index.js"),
})
);
@remix-run/dev
: Vite - Add vite:dev
and vite:build
commands to the Remix CLI (#8211)
In order to handle upcoming Remix features where your plugin options can impact the number of Vite builds required, you should now run your Vite dev
and build
processes via the Remix CLI.
{
"scripts": {
- "dev": "vite dev",
- "build": "vite build && vite build --ssr"
+ "dev": "remix vite:dev",
+ "build": "remix vite:build"
}
}
@remix-run/dev
: Vite - Error messages when .server
files are referenced by client (#8267)
.server
module from client code resulted in an error message like:
The requested module '/app/models/answer.server.ts' does not provide an export named 'isDateType'
answer.server.ts
does provide the isDateType
export, but Remix was replacing .server
modules with empty modules (export {}
) for the client build.server
module is referenced from client code and includes dedicated error messages depending on whether the import occurs in a route or a non-route module@remix-run/dev
: Vite - Preserve names for exports from .client
modules (#8200)
.server
modules, the main idea is not to prevent code from leaking into the server build since the client build is already public.client
modules without compilation failing and then rely on runtime checks or otherwise ensure that execution only happens within a client-only context (e.g. event handlers, useEffect
).client
modules with empty modules would cause the build to fail as ESM named imports are statically analyzed
undefined
@remix-run/dev
: Vite - Disable watch mode in Vite child compiler during build (#8342)
@remix-run/dev
: Vite - Show warning when source maps are enabled in production build (#8222)
@remix-run/react
: Propagate server loader
errors through serverLoader
in hydrating clientLoader
's (#8304)
@remix-run/react
Re-export Response
helpers (defer
/json
/redirect
/redirectDocument
) through @remix-run/react
for use in clientLoader
/clientAction
(#8351)
@remix-run/server-runtime
: Add optional error
to ServerRuntimeMetaArgs
type to align with MetaArgs
(#8238)
create-remix
: Switch to using @remix-run/web-fetch
instead of node-fetch
inside the create-remix
CLI (#7345)
remix-serve
: Use node fileURLToPath
to convert source map URL to path (#8321)
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.4.0...v2.4.1
Date: 2023-12-13
We're excited to land the Client Data RFC in this release! The final API differs slightly from the RFC, so please check out the docs for use-cases and final APIs:
While we still recommend server loaders/actions for the majority of your data needs in a Remix app - these provide some levers you can pull for more advanced use-cases such as:
future.v3_relativeSplatPath
We introduced a future.v3_relativeSplatPath
flag to implement a breaking bug fix to relative routing when inside a splat route. For more information, please see the React Router 6.21.0
Release Notes and the useResolvedPath
docs
Remix now excludes modules within .server
directories from client build.
Remix now enforces strict route exports, and will will throw an error if you have unsupported exports in your route modules. Previously, the Remix compiler would allow any export from routes. While this was convenient, it was also a common source of bugs that were hard to track down because they only surfaced at runtime. For more information, please see the docs.
clientLoader
/clientAction
/HydrateFallback
route exports (#8173)future.v3_relativeSplatPath
flag to implement a breaking bug fix to relative routing when inside a splat route (#8216)DataFunctionArgs
in favor of LoaderFunctionArgs
/ActionFunctionArgs
(#8173)
clientLoader
/clientActon
functions have serverLoader
/serverAction
parameters which differentiate ClientLoaderFunctionArgs
/ClientActionFunctionArgs
.server
directories from client build (#8154)@remix-run/server-runtime
: Fix flash of unstyled content for non-Express custom servers in Vite dev (#8076)
@remix-run/server-runtime
: Pass request handler errors to vite.ssrFixStacktrace
in Vite dev to ensure stack traces correctly map to the original source code (#8066)
remix-serve
: Fix source map loading when file has ?t=timestamp
suffix (rebuilds) (#8174)
@remix-run/dev
: Change Vite build output paths to fix a conflict between how Vite and the Remix compiler each manage the public
directory (#8077)
build/server
rather than build
, and the client is now compiled into build/client
rather than public
@remix-run/dev
: Upgrade Vite peer dependency range to v5 (#8172)
@remix-run/dev
: Support HMR for routes with handle
export in Vite dev (#8022)
@remix-run/dev
: Fix flash of unstyled content for non-Express custom servers in Vite dev (#8076)
@remix-run/dev
: Bundle CSS imported in client entry file in Vite plugin (#8143)
@remix-run/dev
: Remove undocumented legacyCssImports
option from Vite plugin due to issues with ?url
imports of CSS files not being processed correctly in Vite (#8096)
@remix-run/dev
: Vite: fix access to default entry.{client,server}.tsx
within pnpm
workspaces on Windows (#8057)
@remix-run/dev
: Remove unstable_createViteServer
and unstable_loadViteServerBuild
which were only minimal wrappers around Vite's createServer
and ssrLoadModule
functions when using a custom server (#8120)
ā ļø This is a breaking change for projects using the unstable Vite plugin with a custom server
Instead, we now provide unstable_viteServerBuildModuleId
so that custom servers interact with Vite directly rather than via Remix APIs, for example:
-import {
- unstable_createViteServer,
- unstable_loadViteServerBuild,
-} from "@remix-run/dev";
+import { unstable_viteServerBuildModuleId } from "@remix-run/dev";
Creating the Vite server in middleware mode:
const vite =
process.env.NODE_ENV === "production"
? undefined
- : await unstable_createViteServer();
+ : await import("vite").then(({ createServer }) =>
+ createServer({
+ server: {
+ middlewareMode: true,
+ },
+ })
+ );
Loading the Vite server build in the request handler:
app.all(
"*",
createRequestHandler({
build: vite
- ? () => unstable_loadViteServerBuild(vite)
+ ? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId)
: await import("./build/server/index.js"),
})
);
@remix-run/dev
: Pass request handler errors to vite.ssrFixStacktrace
in Vite dev to ensure stack traces correctly map to the original source code (#8066)
@remix-run/dev
: Vite: Preserve names for exports from .client
imports (#8200)
.server
modules, the main idea is not to prevent code from leaking into the server build since the client build is already public.client
modules without compilation failing and then rely on runtime checks to determine if the code is running on the server or client.client
modules with empty modules would cause the build to fail as ESM named imports are statically analyzed
@remix-run/dev
: Add @remix-run/node
to Vite's optimizeDeps.include
array (#8177)
@remix-run/dev
: Improve Vite plugin performance (#8121)
server.preTransformRequests
in Vite child compiler since it's only used to process route modules@remix-run/dev
: Remove automatic global Node polyfill installation from the built-in Vite dev server and instead allow explicit opt-in (#8119)
ā ļø This is a breaking change for projects using the unstable Vite plugin without a custom server
If you're not using a custom server, you should call installGlobals
in your Vite config instead.
import { unstable_vitePlugin as remix } from "@remix-run/dev";
+import { installGlobals } from "@remix-run/node";
import { defineConfig } from "vite";
+installGlobals();
export default defineConfig({
plugins: [remix()],
});
@remix-run/dev
: Vite: Errors at build-time when client imports .server default export (#8184)
@remix-run/dev
: Fix request instanceof Request
checks when using Vite dev server (#8062)
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.3.1...v2.4.0
Date: 2023-11-22
@remix-run/dev
: Support nonce
prop on LiveReload
component in Vite dev (#8014)@remix-run/dev
: Ensure code-split JS files in the server build's assets directory aren't cleaned up after Vite build (#8042)@remix-run/dev
: Fix redundant copying of assets from public
directory in Vite build (#8039)
assetsBuildDirectory
was deeply nested within the public
directorycreate-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.3.0...v2.3.1
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
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
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
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
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
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