Skip to content

Commit

Permalink
Merge branch 'release-next' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
mjackson committed Nov 8, 2024
2 parents 573764d + 1258057 commit 417ecc4
Show file tree
Hide file tree
Showing 79 changed files with 565 additions and 339 deletions.
5 changes: 0 additions & 5 deletions .changeset/giant-eggs-march.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/grumpy-llamas-leave.md

This file was deleted.

29 changes: 0 additions & 29 deletions .changeset/popular-humans-attend.md

This file was deleted.

6 changes: 0 additions & 6 deletions .changeset/rude-clocks-prove.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/tiny-zebras-stare.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/twenty-nails-occur.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/twenty-waves-cheer.md

This file was deleted.

234 changes: 156 additions & 78 deletions CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ We are happy you're here!

[Remix](https://remix.run) is a full stack web framework that lets you focus on the user interface and work back through web fundamentals to deliver a fast, slick, and resilient user experience that deploys to any Node.js server and even non-Node.js environments at the edge like Cloudflare Workers.

Want to know more? Read the [Technical Explanation of Remix](https://remix.run/discussion/introduction)
Want to know more? Read the [Technical Explanation of Remix](https://remix.run/discussion/introduction).

This repository contains the Remix source code. This repo is a work in progress, so we appreciate your patience as we figure things out.

Expand Down
8 changes: 8 additions & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
- bogas04
- BogdanDevBst
- bolchowka
- bravo-kernel
- brenr
- brettscott
- brookslybrand
Expand Down Expand Up @@ -246,6 +247,7 @@
- harmony7
- harshmangalam
- helderburato
- HenryPereira
- HenryVogt
- hi-ogawa
- hicksy
Expand All @@ -269,6 +271,7 @@
- IgnusG
- ikarus-akhil
- illright
- imzivko
- imzshh
- infomiho
- ionut-botizan
Expand Down Expand Up @@ -449,6 +452,7 @@
- maxrchung
- maxschwarzmueller
- mbarto
- mbuchoff
- mcansh
- mccuna
- mdoury
Expand All @@ -468,6 +472,7 @@
- mikechabot
- mikeybinnswebdesign
- mirzafaizan
- mischah
- mitchelldirt
- mjackson
- mjangir
Expand Down Expand Up @@ -531,6 +536,7 @@
- penspinner
- penx
- petetnt
- petrpacas
- philandstuff
- phishy
- plastic041
Expand Down Expand Up @@ -589,6 +595,7 @@
- sbernheim4
- schpet
- scott-erickson
- ScottDalessandro
- scottybrown
- sdavids
- sean-roberts
Expand Down Expand Up @@ -625,6 +632,7 @@
- staylor
- stephanerangaya
- stephenwade
- strackfeldt
- SufianBabri
- supachaidev
- syeef
Expand Down
8 changes: 4 additions & 4 deletions docs/file-conventions/entry.server.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ _Note that you generally want to avoid logging when the request was aborted, sin

### Streaming Rendering Errors

When you are streaming your HTML responses via [`renderToPipeableStream`][rendertopipeablestream] or [`renderToReadableStream`][rendertoreadablestream], your own `handleError` implementation will only handle errors encountered during the initial shell render. If you encounter a rendering error during subsequent streamed rendering you will need handle these errors manually since the Remix server has already sent the Response by that point.
When you are streaming your HTML responses via [`renderToPipeableStream`][rendertopipeablestream] or [`renderToReadableStream`][rendertoreadablestream], your own `handleError` implementation will only handle errors encountered during the initial shell render. If you encounter a rendering error during subsequent streamed rendering you will need to handle these errors manually since the Remix server has already sent the Response by that point.

- For `renderToPipeableStream`, you can handle these errors in the `onError` callback function. You will need to toggle a boolean when the in `onShellReady` so you know if the error was a shell rendering error (and can be ignored) or an async rendering error (and must be handled).
- For an example, please see the default [`entry.server.tsx`][node-streaming-entry-server] for Node.
- For `renderToPipeableStream`, you can handle these errors in the `onError` callback function. You will need to toggle a boolean in `onShellReady` so you know if the error was a shell rendering error (and can be ignored) or an async rendering error (and must be handled).
- For an example, please refer to the default [`entry.server.tsx`][node-streaming-entry-server] for Node.
- For `renderToReadableStream`, you can handle these errors in the `onError` callback function
- For an example, please see the default [`entry.server.tsx`][cloudflare-streaming-entry-server] for Cloudflare
- For an example, please refer to the default [`entry.server.tsx`][cloudflare-streaming-entry-server] for Cloudflare

### Thrown Responses

Expand Down
2 changes: 1 addition & 1 deletion docs/file-conventions/routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Before we go too far into the Remix convention though, we'd like to point out th

The point is, we are well aware of this and from the get-go, Remix has always given you a first-class way to opt-out via the [`routes`][routes_config]/[`ignoredRouteFiles`][ignoredroutefiles_config] and [configure your routes manually][manual-route-configuration]. But, there has to be _some_ default so that folks can get up and running quickly and easily - and we think that the flat routes convention document below is a pretty good default that scales well for small-to-medium sized apps.

Large applications with hundred or thousands of routes will _always_ be a bit chaotic no matter what convention you use - and the idea is that via the `routes` config, you get to build _exactly_ the convention that works best for your application/team. It would be quite literally impossible for Remix to have a default convention that made everyone happy. We'd much rather give you a fairly straightforward default, and then let the community build any number of conventions you can pick and choose from.
Large applications with hundreds or thousands of routes will _always_ be a bit chaotic no matter what convention you use - and the idea is that via the `routes` config, you get to build _exactly_ the convention that works best for your application/team. It would be quite literally impossible for Remix to have a default convention that made everyone happy. We'd much rather give you a fairly straightforward default, and then let the community build any number of conventions you can pick and choose from.

So, before we dive into the details of the Remix default convention, here's some community alternatives you can check out if you decide that our default is not your cup of tea.

Expand Down
2 changes: 1 addition & 1 deletion docs/file-conventions/vite-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,6 @@ You may also want to enable the `manifest` option since, when server bundles are
[minimatch]: https://npm.im/minimatch
[presets]: ../guides/presets
[server-bundles]: ../guides/server-bundles
[rr-basename]: https://reactrouter.com/routers/create-browser-router#basename
[rr-basename]: https://reactrouter.com/v6/routers/create-browser-router#basename
[vite-public-base-path]: https://vitejs.dev/config/shared-options.html#base
[vite-base]: https://vitejs.dev/config/shared-options.html#base
2 changes: 1 addition & 1 deletion docs/guides/breadcrumbs.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default function Root() {
}
```

Note that we pass the `match` object to breadcrumbs, allowing us to potentially utilize `match.data` for enhancing breadcrumb content based on the route's data. This example doesn't use it, but you'll like want to use values from your loader data for the breadcrumb.
Note that we pass the `match` object to breadcrumbs, allowing us to potentially utilize `match.data` for enhancing breadcrumb content based on the route's data. This example doesn't use it, but you'll likely want to use values from your loader data for the breadcrumb.

Using `useMatches` with `handle` offers a robust way for routes to contribute to rendering processes higher up the element tree than their actual render point.

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/migrating-react-router-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ Now then, go off and _remix your app_. We think you'll like what you build along
- [Common "gotchas"][common-gotchas]

[react-router]: https://reactrouter.com
[react-router-docs]: https://reactrouter.com/start/concepts
[react-router-docs]: https://reactrouter.com/v6/start/concepts
[migration-guide-from-v5-to-v6]: https://reactrouter.com/en/6.22.3/upgrading/v5
[backwards-compatibility-package]: https://www.npmjs.com/package/react-router-dom-v5-compat
[a-few-tweaks-to-improve-progressive-enhancement]: ../pages/philosophy#progressive-enhancement
Expand Down
14 changes: 9 additions & 5 deletions docs/guides/single-fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,12 @@ Single Fetch requires using [`undici`][undici] as your `fetch` polyfill, or usin

With Single Fetch enabled, there will now only be one request made on client-side navigations even when multiple loaders need to run. To handle merging headers for the handlers called, the [`headers`][headers] export will now also apply to `loader`/`action` data requests. In many cases, the logic you already have in there for document requests should be close to sufficient for your new Single Fetch data requests.

**4. Add `nonce` to `<RemixServer>` (if you are using a CSP)**
**4. Add a `nonce` (if you are using a CSP)**

The `<RemixServer>` component renders inline scripts that handle the streaming data on the client side. If you have a [content security policy for scripts][csp] with [nonce-sources][csp-nonce], you can use `<RemixServer nonce>` to pass through the nonce to these `<script>` tags.
If you have a [content security policy for scripts][csp] with [nonce-sources][csp-nonce], you will need to add that `nonce` to two places for the streaming Single Fetch implementation:

- `<RemixServer nonce={yourNonceValue}>` - this will add the `nonce` to the inline scripts rendered by this component that handle the streaming data on the client side
- In your `entry.server.tsx` in the `options.nonce` parameter to [`renderToPipeableStream`][rendertopipeablestream]/[`renderToReadableStream`][rendertoreadablestream]. See also the Remix [Streaming docs][streaming-nonce]

**5. Replace `renderToString` (if you are using it)**

Expand All @@ -80,15 +83,15 @@ There are a handful of breaking changes introduced with Single Fetch - some of w

- **[New streaming Data format][streaming-format]**: Single fetch uses a new streaming format under the hood via [`turbo-stream`][turbo-stream], which means that we can stream down more complex data than just JSON
- **No more auto-serialization**: Naked objects returned from `loader` and `action` functions are no longer automatically converted into a JSON `Response` and are serialized as-is over the wire
- [**Updates to type inference**][type-inference-section]: To get the most accurate type inference, you should [augment][augment] Remix's `Future` interface with `unstable_singleFetch: true`
- [**Updates to type inference**][type-inference-section]: To get the most accurate type inference, you should [augment][augment] Remix's `Future` interface with `v3_singleFetch: true`
- [**Default revalidation behavior changes to opt-out on GET navigations**][revalidation]: Default revalidation behavior on normal navigations changes from opt-in to opt-out and your server loaders will re-run by default
- [**Opt-in `action` revalidation**][action-revalidation]: Revalidation after an `action` `4xx`/`5xx` `Response` is now opt-in, versus opt-out

## Adding a New Route with Single Fetch

With Single Fetch enabled, you can go ahead and author routes that take advantage of the more powerful streaming format.

<docs-info>In order to get proper type inference, you need to [augment][augment] Remix's `Future` interface with `unstable_singleFetch: true`. You can read more about this in the [Type Inference section][type-inference-section].</docs-info>
<docs-info>In order to get proper type inference, you need to [augment][augment] Remix's `Future` interface with `v3_singleFetch: true`. You can read more about this in the [Type Inference section][type-inference-section].</docs-info>

With Single Fetch you can return the following data types from your loader: `BigInt`, `Date`, `Error`, `Map`, `Promise`, `RegExp`, `Set`, `Symbol`, and `URL`.

Expand Down Expand Up @@ -473,7 +476,7 @@ Revalidation is handled via a `?_routes` query string parameter on the single fe
[starttransition]: https://react.dev/reference/react/startTransition
[headers]: ../route/headers
[resource-routes]: ../guides/resource-routes
[returning-response]: ../route/loader.md#returning-response-instances
[returning-response]: ../route/loader#returning-response-instances
[streaming-format]: #streaming-data-format
[undici-polyfill]: https://github.com/remix-run/remix/blob/main/CHANGELOG.md#undici
[undici]: https://github.com/nodejs/undici
Expand All @@ -489,3 +492,4 @@ Revalidation is handled via a `?_routes` query string parameter on the single fe
[compatibility-flag]: https://developers.cloudflare.com/workers/configuration/compatibility-dates
[data-utility]: ../utils/data
[augment]: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
[streaming-nonce]: ./streaming#streaming-with-a-content-security-policy
4 changes: 2 additions & 2 deletions docs/guides/spa-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,9 @@ Once you've got all your routes living in their own files, you can:
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
[runtimes]: ../discussion/runtimes
[kent-tweet]: https://twitter.com/kentcdodds/status/1743030378334708017
[rr-setup]: https://reactrouter.com/en/main/start/tutorial#setup
[rr-setup]: https://reactrouter.com/v6/start/tutorial#setup
[routes-config]: ../file-conventions/remix-config#routes
[route-lazy]: https://reactrouter.com/en/main/route/lazy
[route-lazy]: https://reactrouter.com/v6/route/lazy
[meta]: ../components/meta
[links]: ../components/links
[migrating-rr]: https://remix.run/docs/en/main/guides/migrating-react-router-app
Expand Down
2 changes: 1 addition & 1 deletion docs/hooks/use-fetcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function SomeComponent() {

### `key`

By default, `useFetcher` generate a unique fetcher scoped to that component (however, it may be looked up in [`useFetchers()`][use_fetchers] while in-flight). If you want to identify a fetcher with your own key such that you can access it from elsewhere in your app, you can do that with the `key` option:
By default, `useFetcher` generates a unique fetcher scoped to that component (however, it may be looked up in [`useFetchers()`][use_fetchers] while in-flight). If you want to identify a fetcher with your own key such that you can access it from elsewhere in your app, you can do that with the `key` option:

```tsx lines=[2,8]
function AddToBagButton() {
Expand Down
4 changes: 2 additions & 2 deletions docs/hooks/use-resolved-path.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ When you enable the flag, this "bug" is fixed so that path resolution is consist
- [`resolvePath`][rr-resolve-path]

[nav-link-component]: ../components/nav-link
[rr-resolve-path]: https://reactrouter.com/utils/resolve-path
[rr-use-resolved-path-splat]: https://reactrouter.com/hooks/use-resolved-path#splat-paths
[rr-resolve-path]: https://reactrouter.com/v6/utils/resolve-path
[rr-use-resolved-path-splat]: https://reactrouter.com/v6/hooks/use-resolved-path#splat-paths
[remix-config-future]: https://remix.run/docs/en/main/file-conventions/remix-config#future
2 changes: 1 addition & 1 deletion docs/hooks/use-view-transition-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Consider clicking on an image in a list that you need to expand into the hero im
```jsx
function NavImage({ src, alt, id }) {
const to = `/images/${idx}`;
const vt = useViewTransitionState(href);
const vt = useViewTransitionState(to);
return (
<Link to={to} viewTransition>
<img
Expand Down
15 changes: 14 additions & 1 deletion docs/other-api/serve.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ order: 3

# Remix App Server

Remix is designed for you to own your server, but if you don't want to set one up you can use the Remix App Server instead. It's a production-ready, but basic Node.js server built with Express. If you find you want to customize it, use the `@remix-run/express` adapter instead.
Remix is designed for you to own your server, but if you don't want to set one up you can use the Remix App Server instead. It's a production-ready, but basic Node.js server built with Express.

By design, we do not provide options to customize the Remix App Server because if you need to customize the underlying `express` server, we'd rather you manage the server completely instead of creating an abstraction to handle all of the possible customizations you may require. If you find you want to customize it, you should use the `@remix-run/express` adapter instead.

You can see the underlying `express` server configuration in [packages/remix-serve/cli.ts][remix-serve-code]. By default it uses the following Express middlewares (please refer to their documentation for default behaviors):

- [`compression`][compression]
- [`express.static`][express-static] (and thus [`serve-static`][serve-static])
- [`morgan`][morgan]

## `HOST` environment variable

Expand Down Expand Up @@ -83,3 +91,8 @@ In production this doesn't happen. The server boots up and that's the end of it.
[remix-run-express]: ./adapter#createrequesthandler
[singleton]: ../guides/manual-mode#keeping-in-memory-server-state-across-rebuilds
[express-listen]: https://expressjs.com/en/api.html#app.listen
[remix-serve-code]: https://github.com/remix-run/remix/blob/main/packages/remix-serve/cli.ts
[compression]: https://expressjs.com/en/resources/middleware/compression.html
[express-static]: https://expressjs.com/en/4x/api.html#express.static
[serve-static]: https://expressjs.com/en/resources/middleware/serve-static.html
[morgan]: https://expressjs.com/en/resources/middleware/morgan.html
2 changes: 1 addition & 1 deletion docs/other-api/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ test("renders loader data", async () => {
});
```

[create-memory-router]: https://reactrouter.com/en/main/routers/create-memory-router
[create-memory-router]: https://reactrouter.com/v6/routers/create-memory-router
[use-loader-data]: ../hooks/use-loader-data
[use-fetcher]: ../hooks/use-fetcher
[cypress]: https://www.cypress.io
Expand Down
6 changes: 3 additions & 3 deletions docs/start/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -958,12 +958,12 @@ At this point you should know everything you need to know to make the delete but
👉 **Create the "destroy" route module**

```shellscript nonumber
touch app/routes/contacts.\$contactId.destroy.tsx
touch app/routes/contacts.\$contactId_.destroy.tsx
```

👉 **Add the destroy action**

```tsx filename=app/routes/contacts.$contactId.destroy.tsx
```tsx filename=app/routes/contacts.$contactId_.destroy.tsx
import type { ActionFunctionArgs } from "@remix-run/node";
import { redirect } from "@remix-run/node";
import invariant from "tiny-invariant";
Expand All @@ -986,7 +986,7 @@ Alright, navigate to a record and click the "Delete" button. It works!
When the user clicks the submit button:

1. `<Form>` prevents the default browser behavior of sending a new document `POST` request to the server, but instead emulates the browser by creating a `POST` request with client side routing and [`fetch`][fetch]
2. The `<Form action="destroy">` matches the new route at `"contacts.$contactId.destroy"` and sends it the request
2. The `<Form action="destroy">` matches the new route at `contacts.$contactId_.destroy.tsx` and sends it the request
3. After the `action` redirects, Remix calls all the `loader`s for the data on the page to get the latest values (this is "revalidation"). `useLoaderData` returns new values and causes the components to update!

Add a `Form`, add an `action`, Remix does the rest.
Expand Down
Loading

0 comments on commit 417ecc4

Please sign in to comment.