Skip to content

Commit

Permalink
Merge branch 'main' into release-next
Browse files Browse the repository at this point in the history
  • Loading branch information
mjackson committed Nov 4, 2024
2 parents 6f82889 + 1bd7f94 commit 2e5d28e
Show file tree
Hide file tree
Showing 39 changed files with 179 additions and 122 deletions.
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ You can now export an optional `Layout` component from your root route which wil

#### Basename support

React Router has long supported a [`basename`](https://reactrouter.com/en/main/routers/create-browser-router#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](https://github.com/remix-run/remix/discussions/2891) to add this functionality.
React Router has long supported a [`basename`](https://reactrouter.com/v6/routers/create-browser-router#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](https://github.com/remix-run/remix/discussions/2891) to add this functionality.

Two things have since changed that made us reconsider the lack of `basename` support:

Expand Down Expand Up @@ -1023,7 +1023,7 @@ A few notes on the new plugin:
- This gives parity with the Cloudflare preset for the Remix Vite plugin and keeps our templates leaner
- `@remix-run/dev` - Vite: Cloudflare Proxy as a Vite plugin ([#8749](https://github.com/remix-run/remix/pull/8749))
- **⚠️ This is a breaking change for projects relying on Cloudflare support from the unstable Vite plugin**
- `@remix-run/dev` - Vite: Add a new `basename` option to the Vite plugin, allowing users to set the internal React Router [`basename`](https://reactrouter.com/en/main/routers/create-browser-router#basename) in order to to serve their applications underneath a subpath ([#8145](https://github.com/remix-run/remix/pull/8145))
- `@remix-run/dev` - Vite: Add a new `basename` option to the Vite plugin, allowing users to set the internal React Router [`basename`](https://reactrouter.com/v6/routers/create-browser-router#basename) in order to to serve their applications underneath a subpath ([#8145](https://github.com/remix-run/remix/pull/8145))
- `@remix-run/dev` - Vite: Stabilize the Remix Vite plugin, Cloudflare preset, and all related types by removing all `unstable_` / `Unstable_` prefixes ([#8713](https://github.com/remix-run/remix/pull/8713))
- While this is a breaking change for existing Remix Vite plugin consumers, now that the plugin has stabilized, there will no longer be any breaking changes outside of a major release. Thank you to all of our early adopters and community contributors for helping us get here! 🙏
- `@remix-run/dev` - Vite: Stabilize "SPA Mode" by renaming the Remix vite plugin config from `unstable_ssr -> ssr` ([#8692](https://github.com/remix-run/remix/pull/8692))
Expand Down Expand Up @@ -1715,7 +1715,7 @@ function handleClick() {

### Minor Changes

- Remove the `unstable_` prefix from the [`useBlocker`](https://reactrouter.com/en/main/hooks/use-blocker) hook ([#7882](https://github.com/remix-run/remix/pull/7882))
- Remove the `unstable_` prefix from the [`useBlocker`](https://reactrouter.com/v6/hooks/use-blocker) hook ([#7882](https://github.com/remix-run/remix/pull/7882))
- Add `unstable_flushSync` option to `useNavigate`/`useSubmit`/`fetcher.load`/`fetcher.submit` to opt-out of `React.startTransition` and into `ReactDOM.flushSync` for state updates ([#7996](https://github.com/remix-run/remix/pull/7996))

### Patch Changes
Expand Down
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
Loading

0 comments on commit 2e5d28e

Please sign in to comment.