@vercel/remix
Advanced tools
Changelog
v2.7.0
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
Changelog
v2.6.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
Changelog
v2.5.1
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
Changelog
v2.5.0
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
Changelog
v2.4.1
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
Changelog
v2.4.0
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:
Changelog
v2.3.1
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