Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions packages/vite-plugin-react-router/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,37 @@
The React Router Adapter for Netlify allows you to deploy your [React Router](https://reactrouter.com) app to
[Netlify Functions](https://docs.netlify.com/functions/overview/).

To deploy a React Router 7+ site to Netlify, install this package:

## How to use

To deploy a React Router 7+ site to Netlify, install this package:

```sh
npm install --save-dev @netlify/vite-plugin-react-router
```

It's also recommended (but not required) to use the
[Netlify Vite plugin](https://www.npmjs.com/package/@netlify/vite-plugin), which provides full Netlify platform
emulation directly in your local dev server:

```sh
npm install --save-dev @netlify/vite-plugin
```

and include the Netlify plugin in your `vite.config.ts`:

```typescript
import { reactRouter } from '@react-router/dev/vite'
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'
import netlifyPlugin from '@netlify/vite-plugin-react-router' // <- add this
import netlifyReactRouter from '@netlify/vite-plugin-react-router' // <- add this
import netlify from '@netlify/vite-plugin' // <- add this (optional)

export default defineConfig({
plugins: [
reactRouter(),
tsconfigPaths(),
netlifyPlugin(), // <- add this
netlifyReactRouter(), // <- add this
netlify(), // <- add this (optional)
],
})
```
Expand Down Expand Up @@ -76,6 +86,12 @@ export default function Example() {
}
```

> [!IMPORTANT]
>
> Note that in local development, `netlifyRouterContext` requires Netlify platform emulation, which is provided
> seamlessly by [`@netlify/vite-plugin`](https://www.npmjs.com/package/@netlify/vite-plugin) (or Netlify CLI - up to
> you).

### Middleware context

React Router introduced a stable middleware feature in 7.9.0.
Expand Down Expand Up @@ -103,3 +119,9 @@ export default function Home() {
return <h1>Hello world</h1>
}
```

> [!IMPORTANT]
>
> Note that in local development, `netlifyRouterContext` requires Netlify platform emulation, which is provided
> seamlessly by [`@netlify/vite-plugin`](https://www.npmjs.com/package/@netlify/vite-plugin) (or Netlify CLI - up to
> you).
31 changes: 30 additions & 1 deletion packages/vite-plugin-react-router/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,36 @@ export type RequestHandler = (request: Request, context: NetlifyContext) => Prom
*
* @example context.get(netlifyRouterContext).geo?.country?.name
*/
export const netlifyRouterContext = createContext<NetlifyContext>()
export const netlifyRouterContext =
// We must use a singleton because Remix contexts rely on referential equality.
// We can't hook into the request lifecycle in dev mode, so we use a Proxy to always read from the
// current `Netlify.context` value, which is always contextual to the in-flight request.
createContext<Partial<NetlifyContext>>(
new Proxy(
// Can't reference `Netlify.context` here because it isn't set outside of a request lifecycle
{},
{
get(_target, prop, receiver) {
return Reflect.get(Netlify.context ?? {}, prop, receiver)
},
set(_target, prop, value, receiver) {
return Reflect.set(Netlify.context ?? {}, prop, value, receiver)
},
has(_target, prop) {
return Reflect.has(Netlify.context ?? {}, prop)
},
deleteProperty(_target, prop) {
return Reflect.deleteProperty(Netlify.context ?? {}, prop)
},
ownKeys(_target) {
return Reflect.ownKeys(Netlify.context ?? {})
},
getOwnPropertyDescriptor(_target, prop) {
return Reflect.getOwnPropertyDescriptor(Netlify.context ?? {}, prop)
},
},
),
)

/**
* Given a build and a callback to get the base loader context, this returns
Expand Down