diff --git a/.changeset/angry-poets-accept.md b/.changeset/angry-poets-accept.md
deleted file mode 100644
index 0454cf765d6..00000000000
--- a/.changeset/angry-poets-accept.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/serve": patch
----
-
-Use node `fileURLToPath` to convert source map URL to path
diff --git a/.changeset/big-cooks-confess.md b/.changeset/big-cooks-confess.md
deleted file mode 100644
index ab6fd78c460..00000000000
--- a/.changeset/big-cooks-confess.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/server-runtime": patch
----
-
-Add optional `error` to `ServerRuntimeMetaArgs` type to align with `MetaArgs`
diff --git a/.changeset/breezy-grapes-roll.md b/.changeset/breezy-grapes-roll.md
deleted file mode 100644
index 3f64539b86a..00000000000
--- a/.changeset/breezy-grapes-roll.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Vite: Error messages when `.server` files are referenced by client
-
-- Previously, referencing a `.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'`
-- This was confusing because `answer.server.ts` _does_ provide the `isDateType` export, but Remix was replacing `.server` modules with empty modules (`export {}`) for the client build
-- Now, Remix explicitly fails at compile time when a `.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
-- The error messages also include links to relevant documentation
diff --git a/.changeset/breezy-walls-scream.md b/.changeset/breezy-walls-scream.md
deleted file mode 100644
index 1b1510d22a1..00000000000
--- a/.changeset/breezy-walls-scream.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Remove `unstable_viteServerBuildModuleId` in favor of manually referencing virtual module name `"virtual:remix/server-build"`.
-
-**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.
-
-```diff
--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"),
- })
-);
-```
diff --git a/.changeset/create-remix-fetch.md b/.changeset/create-remix-fetch.md
deleted file mode 100644
index f4ac92e94dc..00000000000
--- a/.changeset/create-remix-fetch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"create-remix": patch
----
-
-Switch to using `@remix-run/web-fetch` instead of `node-fetch` inside the `create-remix` CLI
diff --git a/.changeset/poor-eels-bow.md b/.changeset/poor-eels-bow.md
deleted file mode 100644
index 0eec188583f..00000000000
--- a/.changeset/poor-eels-bow.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Add `vite:dev` and `vite:build` commands to the Remix CLI.
-
-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.
-
-```diff
-{
- "scripts": {
-- "dev": "vite dev",
-- "build": "vite build && vite build --ssr"
-+ "dev": "remix vite:dev",
-+ "build": "remix vite:build"
- }
-}
-```
diff --git a/.changeset/rude-keys-heal.md b/.changeset/rude-keys-heal.md
deleted file mode 100644
index 325ccf4297e..00000000000
--- a/.changeset/rude-keys-heal.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Vite: Preserve names for exports from `.client` modules
-
-Unlike `.server` modules, the main idea is not to prevent code from leaking into the server build
-since the client build is already public. Rather, the goal is to isolate the SSR render from client-only code.
-Routes need to import code from `.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`).
-
-Replacing `.client` modules with empty modules would cause the build to fail as ESM named imports are statically analyzed.
-So instead, we preserve the named export but replace each exported value with `undefined`.
-That way, the import is valid at build time and standard runtime checks can be used to determine if the
-code is running on the server or client.
diff --git a/.changeset/server-loader-error.md b/.changeset/server-loader-error.md
deleted file mode 100644
index c7961752b66..00000000000
--- a/.changeset/server-loader-error.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/react": patch
----
-
-Propagate server `loader` errors through `serverLoader` in hydrating `clientLoader`'s
diff --git a/.changeset/seven-bees-thank.md b/.changeset/seven-bees-thank.md
deleted file mode 100644
index 830436dcbfd..00000000000
--- a/.changeset/seven-bees-thank.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Disable watch mode in Vite child compiler during build
diff --git a/.changeset/sour-snakes-melt.md b/.changeset/sour-snakes-melt.md
deleted file mode 100644
index 8a238697707..00000000000
--- a/.changeset/sour-snakes-melt.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@remix-run/dev": patch
----
-
-Vite: Show warning when source maps are enabled in production build
diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml
index 38bdf6cfb41..a1d7f33f627 100644
--- a/.github/workflows/no-response.yml
+++ b/.github/workflows/no-response.yml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 🥺 Handle Ghosting
- uses: actions/stale@v8
+ uses: actions/stale@v9
with:
days-before-close: 10
close-issue-message: >
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40900cfc0b3..4d3ff304dd6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,46 +13,50 @@ We manage release notes in this file instead of the paginated Github Releases Pa
Table of Contents
- [Remix Releases](#remix-releases)
+ - [v2.4.1](#v241)
+ - [Patch Changes](#patch-changes)
+ - [Updated Dependencies](#updated-dependencies)
+ - [Changes by Package](#changes-by-package)
- [v2.4.0](#v240)
- [What's Changed](#whats-changed)
- [Client Data](#client-data)
- [`future.v3_relativeSplatPath`](#futurev3_relativesplatpath)
- [Vite Updates (Unstable)](#vite-updates-unstable)
- [Minor Changes](#minor-changes)
- - [Patch Changes](#patch-changes)
- - [Updated Dependencies](#updated-dependencies)
- - [Changes by Package](#changes-by-package)
- - [v2.3.1](#v231)
- [Patch Changes](#patch-changes-1)
- [Updated Dependencies](#updated-dependencies-1)
- [Changes by Package](#changes-by-package-1)
+ - [v2.3.1](#v231)
+ - [Patch Changes](#patch-changes-2)
+ - [Updated Dependencies](#updated-dependencies-2)
+ - [Changes by Package](#changes-by-package-2)
- [v2.3.0](#v230)
- [What's Changed](#whats-changed-1)
- [Stabilized `useBlocker`](#stabilized-useblocker)
- [`unstable_flushSync` API](#unstable_flushsync-api)
- [Minor Changes](#minor-changes-1)
- - [Patch Changes](#patch-changes-2)
- - [Updated Dependencies](#updated-dependencies-2)
- - [Changes by Package](#changes-by-package-2)
+ - [Patch Changes](#patch-changes-3)
+ - [Updated Dependencies](#updated-dependencies-3)
+ - [Changes by Package](#changes-by-package-3)
- [v2.2.0](#v220)
- [What's Changed](#whats-changed-2)
- [Vite!](#vite)
- [New Fetcher APIs](#new-fetcher-apis)
- [Persistence Future Flag](#persistence-future-flag)
- [Minor Changes](#minor-changes-2)
- - [Patch Changes](#patch-changes-3)
- - [Updated Dependencies](#updated-dependencies-3)
- - [Changes by Package](#changes-by-package-3)
+ - [Patch Changes](#patch-changes-4)
+ - [Updated Dependencies](#updated-dependencies-4)
+ - [Changes by Package](#changes-by-package-4)
- [v2.1.0](#v210)
- [What's Changed](#whats-changed-3)
- [View Transitions](#view-transitions)
- [Stable `createRemixStub`](#stable-createremixstub)
- [Minor Changes](#minor-changes-3)
- - [Patch Changes](#patch-changes-4)
- - [Updated Dependencies](#updated-dependencies-4)
- - [Changes by Package](#changes-by-package-4)
- - [v2.0.1](#v201)
- [Patch Changes](#patch-changes-5)
+ - [Updated Dependencies](#updated-dependencies-5)
+ - [Changes by Package](#changes-by-package-5)
+ - [v2.0.1](#v201)
+ - [Patch Changes](#patch-changes-6)
- [Changes by Package 🔗](#changes-by-package-)
- [v2.0.0](#v200)
- [Breaking Changes](#breaking-changes)
@@ -64,8 +68,8 @@ We manage release notes in this file instead of the paginated Github Releases Pa
- [Breaking Type Changes](#breaking-type-changes)
- [New Features](#new-features)
- [Other Notable Changes](#other-notable-changes)
- - [Updated Dependencies](#updated-dependencies-5)
- - [Changes by Package](#changes-by-package-5)
+ - [Updated Dependencies](#updated-dependencies-6)
+ - [Changes by Package](#changes-by-package-6)
@@ -111,6 +115,93 @@ To add a new release, copy from this template:
-->
+## v2.4.1
+
+### Patch Changes
+
+- `@remix-run/dev`: Vite - Remove `unstable_viteServerBuildModuleId` in favor of manually referencing virtual module name `"virtual:remix/server-build"` ([#8264](https://github.com/remix-run/remix/pull/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.
+
+ ```diff
+ -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](https://github.com/remix-run/remix/pull/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.
+
+ ```diff
+ {
+ "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](https://github.com/remix-run/remix/pull/8267))
+ - Previously, referencing a `.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'`
+ - This was confusing because `answer.server.ts` _does_ provide the `isDateType` export, but Remix was replacing `.server` modules with empty modules (`export {}`) for the client build
+ - Now, Remix explicitly fails at compile time when a `.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
+ - The error messages also include links to relevant documentation
+- `@remix-run/dev`: Vite - Preserve names for exports from `.client` modules ([#8200](https://github.com/remix-run/remix/pull/8200))
+ - Unlike `.server` modules, the main idea is not to prevent code from leaking into the server build since the client build is already public
+ - Rather, the goal is to isolate the SSR render from client-only code
+ - Routes need to import code from `.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`)
+ - Replacing `.client` modules with empty modules would cause the build to fail as ESM named imports are statically analyzed
+ - So instead, we preserve the named export but replace each exported value with `undefined`
+ - That way, the import is valid at build time and standard runtime checks can be used to determine if the code is running on the server or client
+- `@remix-run/dev`: Vite - Disable watch mode in Vite child compiler during build ([#8342](https://github.com/remix-run/remix/pull/8342))
+- `@remix-run/dev`: Vite - Show warning when source maps are enabled in production build ([#8222](https://github.com/remix-run/remix/pull/8222))
+- `@remix-run/react`: Propagate server `loader` errors through `serverLoader` in hydrating `clientLoader`'s ([#8304](https://github.com/remix-run/remix/pull/8304))
+- `@remix-run/react` Re-export `Response` helpers (`defer`/`json`/`redirect`/`redirectDocument`) through `@remix-run/react` for use in `clientLoader`/`clientAction` ([#8351](https://github.com/remix-run/remix/pull/8351))
+- `@remix-run/server-runtime`: Add optional `error` to `ServerRuntimeMetaArgs` type to align with `MetaArgs` ([#8238](https://github.com/remix-run/remix/pull/8238))
+- `create-remix`: Switch to using `@remix-run/web-fetch` instead of `node-fetch` inside the `create-remix` CLI ([#7345](https://github.com/remix-run/remix/pull/7345))
+- `remix-serve`: Use node `fileURLToPath` to convert source map URL to path ([#8321](https://github.com/remix-run/remix/pull/8321))
+
+### Updated Dependencies
+
+- [`react-router-dom@6.21.1`](https://github.com/remix-run/react-router/releases/tag/react-router%406.21.1)
+- [`@remix-run/router@1.14.1`](https://github.com/remix-run/react-router/blob/main/packages/router/CHANGELOG.md#1141)
+
+### Changes by Package
+
+- [`create-remix`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/create-remix/CHANGELOG.md#241)
+- [`@remix-run/architect`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-architect/CHANGELOG.md#241)
+- [`@remix-run/cloudflare`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-cloudflare/CHANGELOG.md#241)
+- [`@remix-run/cloudflare-pages`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-cloudflare-pages/CHANGELOG.md#241)
+- [`@remix-run/cloudflare-workers`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-cloudflare-workers/CHANGELOG.md#241)
+- [`@remix-run/css-bundle`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-css-bundle/CHANGELOG.md#241)
+- [`@remix-run/deno`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-deno/CHANGELOG.md#241)
+- [`@remix-run/dev`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-dev/CHANGELOG.md#241)
+- [`@remix-run/eslint-config`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-eslint-config/CHANGELOG.md#241)
+- [`@remix-run/express`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-express/CHANGELOG.md#241)
+- [`@remix-run/node`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-node/CHANGELOG.md#241)
+- [`@remix-run/react`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-react/CHANGELOG.md#241)
+- [`@remix-run/serve`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-serve/CHANGELOG.md#241)
+- [`@remix-run/server-runtime`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-server-runtime/CHANGELOG.md#241)
+- [`@remix-run/testing`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-testing/CHANGELOG.md#241)
+
+**Full Changelog**: [`v2.4.0...v2.4.1`](https://github.com/remix-run/remix/compare/remix@2.4.0...remix@2.4.1)
+
## v2.4.0
### What's Changed
@@ -122,7 +213,7 @@ We're excited to land the [Client Data RFC](https://github.com/remix-run/remix/d
- [Client Data Guide](https://remix.run/guides/client-data)
- [`clientLoader`](https://remix.run/route/client-loader)
- [`HydrateFallback`](https://remix.run/route/hydrate-fallback)
-- [`clientAction`](https://remix.run/route/client-loader)
+- [`clientAction`](https://remix.run/route/client-action)
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:
diff --git a/contributors.yml b/contributors.yml
index 14b80999999..6b8851535a3 100644
--- a/contributors.yml
+++ b/contributors.yml
@@ -325,6 +325,7 @@
- leon
- leothorp
- leovander
+- leoweigand
- levippaul
- LewisArdern
- lifeiscontent
@@ -434,6 +435,7 @@
- omamazainab
- oott123
- orballo
+- ovi-ispas
- pacexy
- pandaiolo
- panteliselef
@@ -491,6 +493,7 @@
- sandulat
- sandstone991
- sarahse
+- sathvik-k
- sbernheim4
- schpet
- scottybrown
@@ -624,3 +627,5 @@
- alexanderson1993
- signed
- VHall1
+- souredoutlook
+- tmcw
diff --git a/docs/discussion/server-vs-client.md b/docs/discussion/server-vs-client.md
index feb02d5a577..d1700db8464 100644
--- a/docs/discussion/server-vs-client.md
+++ b/docs/discussion/server-vs-client.md
@@ -62,6 +62,7 @@ export default function Component() {
export async function action({
request,
}: ActionFunctionArgs) {
+ const formData = await request.formData();
const user = await getUser(request);
await updateUser(user.id, {
diff --git a/docs/file-conventions/remix-config.md b/docs/file-conventions/remix-config.md
index 72545db61f1..ca47f4f87a0 100644
--- a/docs/file-conventions/remix-config.md
+++ b/docs/file-conventions/remix-config.md
@@ -272,7 +272,7 @@ There are a few conventions that Remix uses you should be aware of.
[esbuild_plugins_node_modules_polyfill]: https://npm.im/esbuild-plugins-node-modules-polyfill
[browser-node-builtins-polyfill]: #browsernodebuiltinspolyfill
[server-node-builtins-polyfill]: #servernodebuiltinspolyfill
-[future-flags]: ../start/future-flags.md
+[future-flags]: ../start/future-flags
[fetcherpersist-rfc]: https://github.com/remix-run/remix/discussions/7698
[use-fetchers]: ../hooks/use-fetchers
[use-fetcher]: ../hooks/use-fetcher
diff --git a/docs/future/vite.md b/docs/future/vite.md
index ce4bb44fca4..e571bd3cb5a 100644
--- a/docs/future/vite.md
+++ b/docs/future/vite.md
@@ -304,7 +304,7 @@ If you prefer, you can instead author your custom server in TypeScript.
You could then use tools like [`tsx`][tsx] or [`tsm`][tsm] to run your custom server:
```shellscript nonumber
-tsx ./server.tsx
+tsx ./server.ts
node --loader tsm ./server.ts
```
@@ -324,8 +324,8 @@ For example, to update the Dockerfile from the [Blues Stack][blues-stack]:
```diff filename=Dockerfile
-COPY --from=build /myapp/build /myapp/build
-COPY --from=build /myapp/public /myapp/public
-+COPY --from=build /myapp/server/build /myapp/server/build
-+COPY --from=build /myapp/client/build /myapp/client/build
++COPY --from=build /myapp/build/server /myapp/build/server
++COPY --from=build /myapp/build/client /myapp/build/client
```
#### Configure path aliases
@@ -399,20 +399,24 @@ During development, [Vite injects imported CSS files into the page via JavaScrip
This also means that in many cases you won't need the `links` function export anymore.
-👉 **Convert CSS imports to side effects**
+Since the order of your CSS is determined by its import order, you'll need to ensure that your CSS imports are in the same order as your `links` function.
+
+👉 **Convert CSS imports into side effects — in the same order they were in your `links` function!**
```diff filename=app/dashboard/route.tsx
-// No need to export a links function anymore:
- import type { LinksFunction } from "@remix-run/node"; // or cloudflare/deno
- import dashboardStyles from "./dashboard.css?url";
+- import sharedStyles from "./shared.css?url";
++ // ⚠️ NOTE: The import order has been updated
++ // to match the original `links` function!
++ import "./shared.css";
++ import "./dashboard.css";
- export const links: LinksFunction = () => [
+- { rel: "stylesheet", href: sharedStyles },
- { rel: "stylesheet", href: dashboardStyles },
- ];
-
-// Just import the CSS as a side effect:
-+ import "./dashboard.css";
```
While [Vite supports importing static asset URLs via an explicit `?url` query string][vite-url-imports], which in theory would match the behavior of the existing Remix compiler when used for CSS files, there is a [known Vite issue with `?url` for CSS imports][vite-css-url-issue]. This may be fixed in the future, but in the meantime you should exclusively use side effect imports for CSS.
@@ -745,6 +749,47 @@ export default function SuperCool() {}
export const mySuperCoolThing = () => {};
```
+##### Full Stack components
+
+[Full stack components][fullstack-components] are components that are colocated in the same file as a resource route and exported for use in other routes.
+They access data from a resource route by fetching that route's URL.
+
+Conceptually, it's tempting to think of full stack components as a new concept,
+but as far as Remix is concerned, they are standard React components.
+Looking closer, they only depend on the resource route's URL and the type for the corresponding `loader`.
+That means they are shared components with _zero_ runtime dependencies on code from the resource route.
+Organize them they way you would organize any shared component.
+
+For better intuition, consider a full stack component that needs to fetch data from multiple resource routes.
+It doesn't belong to any particular resource route.
+
+👉 **Move full stack components alongside other shared components**
+
+```ts filename=app/components/hello.tsx
+export function Hello() {
+ /* ... */
+}
+```
+
+👉 **Export the loader's type from the resource route**
+
+```diff filename=app/routes/api/hello.ts
++ export type Loader = typeof loader;
+```
+
+👉 **Replace `typeof loader` with `Loader` type**
+
+```diff filename=app/components/hello.tsx
++ import type { Loader } from "~/routes/api/hello";
+
+export function Hello() {
+ // ...
+- const data = useFetcher()
++ const data = useFetcher()
+ // ...
+}
+```
+
## Troubleshooting
Check out the [known issues with the Remix Vite plugin on GitHub][issues-vite] before filing a new bug report!
@@ -760,7 +805,7 @@ Vite supports both ESM and CJS dependencies, but sometimes you might still run i
Usually, this is because a dependency is not properly configured to support ESM.
And we don't blame them, its [really tricky to support both ESM and CJS properly][modernizing-packages-to-esm].
-You can check [_Are The Types Wrong_][arethetypeswrong] to see if the dependency giving you trouble might be misconfigured.
+To diagnose if your one of dependencies is misconfigured, check [publint][publint] or [_Are The Types Wrong_][arethetypeswrong].
Additionally, you can use the [vite-plugin-cjs-interop plugin][vite-plugin-cjs-interop] smooth over issues with `default` exports for external CJS dependencies.
Finally, you can also explicitly configure which dependencies to bundle into your server bundled
@@ -888,9 +933,11 @@ We're definitely late to the Vite party, but we're excited to be here now!
[sveltekit]: https://kit.svelte.dev/
[modernizing-packages-to-esm]: https://blog.isquaredsoftware.com/2023/08/esm-modernization-lessons/
[arethetypeswrong]: https://arethetypeswrong.github.io/
+[publint]: https://publint.dev/
[vite-plugin-cjs-interop]: https://github.com/cyco130/vite-plugin-cjs-interop
[ssr-no-external]: https://vitejs.dev/config/ssr-options.html#ssr-noexternal
[server-dependencies-to-bundle]: https://remix.run/docs/en/main/file-conventions/remix-config#serverdependenciestobundle
[blues-stack]: https://github.com/remix-run/blues-stack
[global-node-polyfills]: ../other-api/node#polyfills
[server-bundles]: ./server-bundles
+[fullstack-components]: https://www.epicweb.dev/full-stack-components
diff --git a/docs/guides/client-data.md b/docs/guides/client-data.md
index ae4a99d3d79..88da8d4c856 100644
--- a/docs/guides/client-data.md
+++ b/docs/guides/client-data.md
@@ -23,7 +23,7 @@ When using Remix in a [BFF][bff] architecture, it may be advantageous to skip th
1. Load the data from server `loader` on the document load
2. Load the data from the `clientLoader` on all subsequent loads
-In this scenario, we will _not_ call the `clientLoader` on hydration - and will only call it on subsequent navigations.
+In this scenario, Remix will _not_ call the `clientLoader` on hydration - and will only call it on subsequent navigations.
```tsx lines=[8,15]
import type { LoaderFunctionArgs } from "@remix-run/node";
@@ -51,7 +51,7 @@ Sometimes, you may want to leverage "Fullstack State" where some of your data co
1. Load the partial data from server `loader` on the document load
2. Export a [`HydrateFallback`][hydratefallback] component to render during SSR because we don't yet have a full set of data
-3. Set `clientLoader.hydrate = true` to load the rest of the data on hydration
+3. Set `clientLoader.hydrate = true`, this instructs Remix to call the clientLoader as part of initial document hydration
4. Combine the server data with the client data in `clientLoader`
```tsx lines=[8-10,23-24,27,30]
@@ -101,6 +101,8 @@ You may want to mix and match data loading strategies in your application such t
1. Export a `loader` when you want to use server data
2. Export `clientLoader` and a `HydrateFallback` when you want to use client data
+A route that only depends on a server loader looks like this:
+
```tsx filename="app/routes/server-data-route.tsx
import type { LoaderFunctionArgs } from "@remix-run/node";
import { json } from "@remix-run/node";
@@ -118,6 +120,8 @@ export default function Component() {
}
```
+A route that only depends on a client loader looks like this.
+
```tsx filename="app/routes/client-data-route.tsx
import type { ClientLoaderFunctionArgs } from "@remix-run/react";
@@ -149,7 +153,7 @@ export default function Component() {
## Client Cache
-Remix normally recommends using `Cache-Control` headers for caching of loader data, however you may want to use a more manual in-browser client-side cache (i.e., in-memory cache, `localStorage`). You can leverage a client-side cache to bypass certain calls to the server as follows:
+You can leverage a client-side cache (memory, local storage, etc.) to bypass certain calls to the server as follows:
1. Load the data from server `loader` on the document load
2. Set `clientLoader.hydrate = true` to prime the cache
diff --git a/docs/guides/typescript.md b/docs/guides/typescript.md
index 949eaec1911..cfd7720efd2 100644
--- a/docs/guides/typescript.md
+++ b/docs/guides/typescript.md
@@ -9,27 +9,28 @@ Remix seamlessly supports both JavaScript and TypeScript. If you name a file wit
The Remix compiler will not do any type checking (it simply removes the types). If you want to do type checking, you'll want to use TypeScript's `tsc` CLI yourself. A common solution is to add a `typecheck` script to your package.json:
-```json filename=package.json lines=[9]
+```json filename=package.json lines=[10]
{
"name": "remix-app",
"private": true,
"sideEffects": false,
"scripts": {
"build": "remix build",
- "dev": "remix dev",
- "start": "remix-serve build/index.js",
+ "dev": "remix dev --manual",
+ "lint": "eslint --ignore-path .gitignore .",
+ "start": "remix-serve ./build/index.js",
"typecheck": "tsc"
},
"dependencies": {
"@remix-run/node": "latest",
"@remix-run/react": "latest",
"@remix-run/serve": "latest",
+ "isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@remix-run/dev": "latest",
- "@remix-run/eslint-config": "latest",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"eslint": "^8.23.1",
diff --git a/docs/hooks/use-submit.md b/docs/hooks/use-submit.md
index 0a5b7ba9fb4..bdee83e828b 100644
--- a/docs/hooks/use-submit.md
+++ b/docs/hooks/use-submit.md
@@ -46,13 +46,22 @@ Can be any of the following:
```tsx
const formData = new FormData();
formData.append("myKey", "myValue");
-submit(formData);
+submit(formData, { method: "post" });
```
**Plain object that will be serialized as `FormData`**
```tsx
-submit({ myKey: "myValue" });
+submit({ myKey: "myValue" }, { method: "post" });
+```
+
+**Plain object that will be serialized as JSON**
+
+```tsx
+submit(
+ { myKey: "myValue" },
+ { method: "post", encType: "application/json" }
+);
```
### `options`
@@ -61,7 +70,7 @@ Options for the submission, the same as [`