@netlify/vite-plugin-react-router 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +76 -0
- package/dist/index.d.mts +26 -9
- package/dist/index.d.ts +26 -9
- package/dist/index.js +14 -6
- package/dist/index.mjs +17 -6
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.0](https://github.com/netlify/remix-compute/compare/vite-plugin-react-router-v1.0.1...vite-plugin-react-router-v2.0.0) (2025-10-16)
|
|
4
|
+
|
|
5
|
+
### ⚠ BREAKING CHANGES
|
|
6
|
+
|
|
7
|
+
* **@netlify/vite-plugin-react-router:** require React Router 7.9.0+ ([#546](https://github.com/netlify/remix-compute/issues/546))
|
|
8
|
+
|
|
9
|
+
Please make sure to upgrade `react-router` and other `@react-router/*` dependencies to 7.9.0 or later. Older versions are no longer supported.
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **@netlify/vite-plugin-react-router:** support React Router middleware ([#546](https://github.com/netlify/remix-compute/issues/546)) ([435fa15](https://github.com/netlify/remix-compute/commit/435fa158d80d78e86b0259c3a668c774ef70c565))
|
|
14
|
+
|
|
3
15
|
## [1.0.1](https://github.com/netlify/remix-compute/compare/vite-plugin-react-router-v1.0.0...vite-plugin-react-router-v1.0.1) (2025-04-04)
|
|
4
16
|
|
|
5
17
|
|
package/README.md
CHANGED
|
@@ -27,3 +27,79 @@ export default defineConfig({
|
|
|
27
27
|
],
|
|
28
28
|
})
|
|
29
29
|
```
|
|
30
|
+
|
|
31
|
+
### Load context
|
|
32
|
+
|
|
33
|
+
This plugin automatically includes all
|
|
34
|
+
[Netlify context](https://docs.netlify.com/build/functions/api/#netlify-specific-context-object) fields on loader and
|
|
35
|
+
action context.
|
|
36
|
+
|
|
37
|
+
If you're using TypeScript, `AppLoadContext` is automatically aware of these fields
|
|
38
|
+
([via module augmentation](https://reactrouter.com/upgrading/remix#9-update-types-for-apploadcontext)).
|
|
39
|
+
|
|
40
|
+
For example:
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { useLoaderData } from 'react-router'
|
|
44
|
+
import type { Route } from './+types/example'
|
|
45
|
+
|
|
46
|
+
export async function loader({ context }: Route.LoaderArgs) {
|
|
47
|
+
return {
|
|
48
|
+
country: context.geo?.country?.name ?? 'an unknown country',
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export default function Example() {
|
|
52
|
+
const { country } = useLoaderData<typeof loader>()
|
|
53
|
+
return <div>You are visiting from {country}</div>
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If you've [opted in to the `future.v8_middleware` flag](https://reactrouter.com/how-to/middleware), you can still use
|
|
58
|
+
the above access pattern for backwards compatibility, but loader and action context will now be an instance of the
|
|
59
|
+
type-safe `RouterContextProvider`. Note that this requires requires v2.0.0+ of `@netlify/vite-plugin-react-router`.
|
|
60
|
+
|
|
61
|
+
For example:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { netlifyRouterContext } from '@netlify/vite-plugin-react-router'
|
|
65
|
+
import { useLoaderData } from 'react-router'
|
|
66
|
+
import type { Route } from './+types/example'
|
|
67
|
+
|
|
68
|
+
export async function loader({ context }: Route.LoaderArgs) {
|
|
69
|
+
return {
|
|
70
|
+
country: context.get(netlifyRouterContext).geo?.country?.name ?? 'an unknown country',
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export default function Example() {
|
|
74
|
+
const { country } = useLoaderData<typeof loader>()
|
|
75
|
+
return <div>You are visiting from {country}</div>
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Middleware context
|
|
80
|
+
|
|
81
|
+
React Router introduced a stable middleware feature in 7.9.0.
|
|
82
|
+
|
|
83
|
+
To use middleware,
|
|
84
|
+
[opt in to the feature via `future.v8_middleware` and follow the docs](https://reactrouter.com/how-to/middleware). Note
|
|
85
|
+
that this requires requires v2.0.0+ of `@netlify/vite-plugin-react-router`.
|
|
86
|
+
|
|
87
|
+
To access the [Netlify context](https://docs.netlify.com/build/functions/api/#netlify-specific-context-object)
|
|
88
|
+
specifically, you must import our `RouterContextProvider` instance:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { netlifyRouterContext } from '@netlify/vite-plugin-react-router'
|
|
92
|
+
|
|
93
|
+
import type { Route } from './+types/home'
|
|
94
|
+
|
|
95
|
+
const logMiddleware: Route.MiddlewareFunction = async ({ request, context }) => {
|
|
96
|
+
const country = context.get(netlifyRouterContext).geo?.country?.name ?? 'unknown'
|
|
97
|
+
console.log(`Handling ${request.method} request to ${request.url} from ${country}`)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export const middleware: Route.MiddlewareFunction[] = [logMiddleware]
|
|
101
|
+
|
|
102
|
+
export default function Home() {
|
|
103
|
+
return <h1>Hello world</h1>
|
|
104
|
+
}
|
|
105
|
+
```
|
package/dist/index.d.mts
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as react_router from 'react-router';
|
|
2
|
+
import { AppLoadContext, RouterContextProvider, ServerBuild } from 'react-router';
|
|
2
3
|
import { Context } from '@netlify/functions';
|
|
3
4
|
import { Plugin } from 'vite';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
declare module 'react-router' {
|
|
7
|
+
interface AppLoadContext extends Context {
|
|
8
|
+
}
|
|
9
|
+
}
|
|
6
10
|
/**
|
|
7
|
-
* A function that returns the value to use as `context` in route `loader` and
|
|
8
|
-
* `action` functions.
|
|
11
|
+
* A function that returns the value to use as `context` in route `loader` and `action` functions.
|
|
9
12
|
*
|
|
10
|
-
* You can think of this as an escape hatch that allows you to pass
|
|
11
|
-
*
|
|
13
|
+
* You can think of this as an escape hatch that allows you to pass environment/platform-specific
|
|
14
|
+
* values through to your loader/action.
|
|
15
|
+
*
|
|
16
|
+
* NOTE: v7.9.0 introduced a breaking change when the user opts in to `future.v8_middleware`. This
|
|
17
|
+
* requires returning an instance of `RouterContextProvider` instead of a plain object. We have a
|
|
18
|
+
* peer dependency on >=7.9.0 so we can safely *import* these, but we cannot assume the user has
|
|
19
|
+
* opted in to the flag.
|
|
20
|
+
*/
|
|
21
|
+
type GetLoadContextFunction = GetLoadContextFunction_V7 | GetLoadContextFunction_V8;
|
|
22
|
+
type GetLoadContextFunction_V7 = (request: Request, context: Context) => Promise<AppLoadContext> | AppLoadContext;
|
|
23
|
+
type GetLoadContextFunction_V8 = (request: Request, context: Context) => Promise<RouterContextProvider> | RouterContextProvider;
|
|
24
|
+
type RequestHandler = (request: Request, context: Context) => Promise<Response>;
|
|
25
|
+
/**
|
|
26
|
+
* An instance of `ReactContextProvider` providing access to
|
|
27
|
+
* [Netlify request context]{@link https://docs.netlify.com/build/functions/api/#netlify-specific-context-object}
|
|
28
|
+
*
|
|
29
|
+
* @example context.get(netlifyRouterContext).geo?.country?.name
|
|
12
30
|
*/
|
|
13
|
-
|
|
14
|
-
type RequestHandler = (request: Request, context: LoadContext) => Promise<Response | void>;
|
|
31
|
+
declare const netlifyRouterContext: react_router.RouterContext<Context>;
|
|
15
32
|
/**
|
|
16
33
|
* Given a build and a callback to get the base loader context, this returns
|
|
17
34
|
* a Netlify Function handler (https://docs.netlify.com/functions/overview/) which renders the
|
|
@@ -26,4 +43,4 @@ declare function createRequestHandler({ build, mode, getLoadContext, }: {
|
|
|
26
43
|
|
|
27
44
|
declare function netlifyPlugin(): Plugin;
|
|
28
45
|
|
|
29
|
-
export { type GetLoadContextFunction, type RequestHandler, createRequestHandler, netlifyPlugin as default };
|
|
46
|
+
export { type GetLoadContextFunction, type RequestHandler, createRequestHandler, netlifyPlugin as default, netlifyRouterContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as react_router from 'react-router';
|
|
2
|
+
import { AppLoadContext, RouterContextProvider, ServerBuild } from 'react-router';
|
|
2
3
|
import { Context } from '@netlify/functions';
|
|
3
4
|
import { Plugin } from 'vite';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
declare module 'react-router' {
|
|
7
|
+
interface AppLoadContext extends Context {
|
|
8
|
+
}
|
|
9
|
+
}
|
|
6
10
|
/**
|
|
7
|
-
* A function that returns the value to use as `context` in route `loader` and
|
|
8
|
-
* `action` functions.
|
|
11
|
+
* A function that returns the value to use as `context` in route `loader` and `action` functions.
|
|
9
12
|
*
|
|
10
|
-
* You can think of this as an escape hatch that allows you to pass
|
|
11
|
-
*
|
|
13
|
+
* You can think of this as an escape hatch that allows you to pass environment/platform-specific
|
|
14
|
+
* values through to your loader/action.
|
|
15
|
+
*
|
|
16
|
+
* NOTE: v7.9.0 introduced a breaking change when the user opts in to `future.v8_middleware`. This
|
|
17
|
+
* requires returning an instance of `RouterContextProvider` instead of a plain object. We have a
|
|
18
|
+
* peer dependency on >=7.9.0 so we can safely *import* these, but we cannot assume the user has
|
|
19
|
+
* opted in to the flag.
|
|
20
|
+
*/
|
|
21
|
+
type GetLoadContextFunction = GetLoadContextFunction_V7 | GetLoadContextFunction_V8;
|
|
22
|
+
type GetLoadContextFunction_V7 = (request: Request, context: Context) => Promise<AppLoadContext> | AppLoadContext;
|
|
23
|
+
type GetLoadContextFunction_V8 = (request: Request, context: Context) => Promise<RouterContextProvider> | RouterContextProvider;
|
|
24
|
+
type RequestHandler = (request: Request, context: Context) => Promise<Response>;
|
|
25
|
+
/**
|
|
26
|
+
* An instance of `ReactContextProvider` providing access to
|
|
27
|
+
* [Netlify request context]{@link https://docs.netlify.com/build/functions/api/#netlify-specific-context-object}
|
|
28
|
+
*
|
|
29
|
+
* @example context.get(netlifyRouterContext).geo?.country?.name
|
|
12
30
|
*/
|
|
13
|
-
|
|
14
|
-
type RequestHandler = (request: Request, context: LoadContext) => Promise<Response | void>;
|
|
31
|
+
declare const netlifyRouterContext: react_router.RouterContext<Context>;
|
|
15
32
|
/**
|
|
16
33
|
* Given a build and a callback to get the base loader context, this returns
|
|
17
34
|
* a Netlify Function handler (https://docs.netlify.com/functions/overview/) which renders the
|
|
@@ -26,4 +43,4 @@ declare function createRequestHandler({ build, mode, getLoadContext, }: {
|
|
|
26
43
|
|
|
27
44
|
declare function netlifyPlugin(): Plugin;
|
|
28
45
|
|
|
29
|
-
export { type GetLoadContextFunction, type RequestHandler, createRequestHandler, netlifyPlugin as default };
|
|
46
|
+
export { type GetLoadContextFunction, type RequestHandler, createRequestHandler, netlifyPlugin as default, netlifyRouterContext };
|
package/dist/index.js
CHANGED
|
@@ -21,12 +21,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
createRequestHandler: () => createRequestHandler,
|
|
24
|
-
default: () => netlifyPlugin
|
|
24
|
+
default: () => netlifyPlugin,
|
|
25
|
+
netlifyRouterContext: () => netlifyRouterContext
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(index_exports);
|
|
27
28
|
|
|
28
29
|
// src/server.ts
|
|
29
30
|
var import_react_router = require("react-router");
|
|
31
|
+
var netlifyRouterContext = (0, import_react_router.createContext)();
|
|
30
32
|
function createRequestHandler({
|
|
31
33
|
build,
|
|
32
34
|
mode,
|
|
@@ -37,8 +39,14 @@ function createRequestHandler({
|
|
|
37
39
|
const start = Date.now();
|
|
38
40
|
console.log(`[${request.method}] ${request.url}`);
|
|
39
41
|
try {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
+
const getDefaultReactRouterContext = () => {
|
|
43
|
+
const ctx = new import_react_router.RouterContextProvider();
|
|
44
|
+
ctx.set(netlifyRouterContext, netlifyContext);
|
|
45
|
+
Object.assign(ctx, netlifyContext);
|
|
46
|
+
return ctx;
|
|
47
|
+
};
|
|
48
|
+
const reactRouterContext = await getLoadContext?.(request, netlifyContext) ?? getDefaultReactRouterContext();
|
|
49
|
+
const response = await reactRouterHandler(request, reactRouterContext);
|
|
42
50
|
response.headers.set("x-nf-runtime", "Node");
|
|
43
51
|
console.log(`[${response.status}] ${request.url} (${Date.now() - start}ms)`);
|
|
44
52
|
return response;
|
|
@@ -56,7 +64,7 @@ var import_posix = require("path/posix");
|
|
|
56
64
|
|
|
57
65
|
// package.json
|
|
58
66
|
var name = "@netlify/vite-plugin-react-router";
|
|
59
|
-
var version = "
|
|
67
|
+
var version = "2.0.0";
|
|
60
68
|
|
|
61
69
|
// src/plugin.ts
|
|
62
70
|
var NETLIFY_FUNCTIONS_DIR = ".netlify/v1/functions";
|
|
@@ -72,7 +80,6 @@ import { createRequestHandler } from "@netlify/vite-plugin-react-router";
|
|
|
72
80
|
import * as build from "virtual:react-router/server-build";
|
|
73
81
|
export default createRequestHandler({
|
|
74
82
|
build,
|
|
75
|
-
getLoadContext: async (_req, ctx) => ctx,
|
|
76
83
|
});
|
|
77
84
|
`
|
|
78
85
|
);
|
|
@@ -142,5 +149,6 @@ function netlifyPlugin() {
|
|
|
142
149
|
}
|
|
143
150
|
// Annotate the CommonJS export names for ESM import in node:
|
|
144
151
|
0 && (module.exports = {
|
|
145
|
-
createRequestHandler
|
|
152
|
+
createRequestHandler,
|
|
153
|
+
netlifyRouterContext
|
|
146
154
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// src/server.ts
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
createContext,
|
|
4
|
+
RouterContextProvider,
|
|
5
|
+
createRequestHandler as createReactRouterRequestHandler
|
|
6
|
+
} from "react-router";
|
|
7
|
+
var netlifyRouterContext = createContext();
|
|
3
8
|
function createRequestHandler({
|
|
4
9
|
build,
|
|
5
10
|
mode,
|
|
@@ -10,8 +15,14 @@ function createRequestHandler({
|
|
|
10
15
|
const start = Date.now();
|
|
11
16
|
console.log(`[${request.method}] ${request.url}`);
|
|
12
17
|
try {
|
|
13
|
-
const
|
|
14
|
-
|
|
18
|
+
const getDefaultReactRouterContext = () => {
|
|
19
|
+
const ctx = new RouterContextProvider();
|
|
20
|
+
ctx.set(netlifyRouterContext, netlifyContext);
|
|
21
|
+
Object.assign(ctx, netlifyContext);
|
|
22
|
+
return ctx;
|
|
23
|
+
};
|
|
24
|
+
const reactRouterContext = await getLoadContext?.(request, netlifyContext) ?? getDefaultReactRouterContext();
|
|
25
|
+
const response = await reactRouterHandler(request, reactRouterContext);
|
|
15
26
|
response.headers.set("x-nf-runtime", "Node");
|
|
16
27
|
console.log(`[${response.status}] ${request.url} (${Date.now() - start}ms)`);
|
|
17
28
|
return response;
|
|
@@ -29,7 +40,7 @@ import { sep as posixSep } from "node:path/posix";
|
|
|
29
40
|
|
|
30
41
|
// package.json
|
|
31
42
|
var name = "@netlify/vite-plugin-react-router";
|
|
32
|
-
var version = "
|
|
43
|
+
var version = "2.0.0";
|
|
33
44
|
|
|
34
45
|
// src/plugin.ts
|
|
35
46
|
var NETLIFY_FUNCTIONS_DIR = ".netlify/v1/functions";
|
|
@@ -45,7 +56,6 @@ import { createRequestHandler } from "@netlify/vite-plugin-react-router";
|
|
|
45
56
|
import * as build from "virtual:react-router/server-build";
|
|
46
57
|
export default createRequestHandler({
|
|
47
58
|
build,
|
|
48
|
-
getLoadContext: async (_req, ctx) => ctx,
|
|
49
59
|
});
|
|
50
60
|
`
|
|
51
61
|
);
|
|
@@ -115,5 +125,6 @@ function netlifyPlugin() {
|
|
|
115
125
|
}
|
|
116
126
|
export {
|
|
117
127
|
createRequestHandler,
|
|
118
|
-
netlifyPlugin as default
|
|
128
|
+
netlifyPlugin as default,
|
|
129
|
+
netlifyRouterContext
|
|
119
130
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/vite-plugin-react-router",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "React Router 7+ Vite plugin for Netlify",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -40,20 +40,20 @@
|
|
|
40
40
|
},
|
|
41
41
|
"homepage": "https://github.com/netlify/remix-compute#readme",
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"
|
|
44
|
-
"isbot": "^5.0.0",
|
|
45
|
-
"react-router": "^7.0.1"
|
|
43
|
+
"isbot": "^5.0.0"
|
|
46
44
|
},
|
|
47
45
|
"devDependencies": {
|
|
48
|
-
"@netlify/functions": "^3.
|
|
46
|
+
"@netlify/functions": "^3.1.9",
|
|
49
47
|
"@types/react": "^18.0.27",
|
|
50
48
|
"@types/react-dom": "^18.0.10",
|
|
51
49
|
"react": "^18.2.0",
|
|
52
50
|
"react-dom": "^18.2.0",
|
|
51
|
+
"react-router": "^7.9.4",
|
|
53
52
|
"tsup": "^8.0.2",
|
|
54
53
|
"vite": "^6.2.5"
|
|
55
54
|
},
|
|
56
55
|
"peerDependencies": {
|
|
56
|
+
"react-router": ">=7.9.0",
|
|
57
57
|
"vite": ">=5.0.0"
|
|
58
58
|
},
|
|
59
59
|
"engines": {
|