react-router 8.0.1 → 8.1.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.
Files changed (139) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/development/dom-export.js +1 -1
  3. package/dist/development/index-react-server-client.js +1 -1
  4. package/dist/development/index-react-server.d.ts +32 -7
  5. package/dist/development/index-react-server.js +180 -152
  6. package/dist/development/index.d.ts +2 -2
  7. package/dist/development/index.js +1 -1
  8. package/dist/development/lib/actions.js +1 -1
  9. package/dist/development/lib/components.js +1 -1
  10. package/dist/development/lib/context.js +1 -1
  11. package/dist/development/lib/dom/dom.js +1 -1
  12. package/dist/development/lib/dom/lib.js +2 -2
  13. package/dist/development/lib/dom/server.js +1 -1
  14. package/dist/development/lib/dom/ssr/components.js +1 -1
  15. package/dist/development/lib/dom/ssr/data.js +1 -1
  16. package/dist/development/lib/dom/ssr/errorBoundaries.js +1 -1
  17. package/dist/development/lib/dom/ssr/fallback.js +1 -1
  18. package/dist/development/lib/dom/ssr/fog-of-war.js +1 -1
  19. package/dist/development/lib/dom/ssr/hydration.js +1 -1
  20. package/dist/development/lib/dom/ssr/invariant.js +1 -1
  21. package/dist/development/lib/dom/ssr/links.js +1 -1
  22. package/dist/development/lib/dom/ssr/markup.js +1 -1
  23. package/dist/development/lib/dom/ssr/routeModules.js +1 -1
  24. package/dist/development/lib/dom/ssr/routes-test-stub.js +1 -1
  25. package/dist/development/lib/dom/ssr/routes.js +1 -1
  26. package/dist/development/lib/dom/ssr/server.js +1 -1
  27. package/dist/development/lib/dom/ssr/single-fetch.js +1 -1
  28. package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
  29. package/dist/development/lib/dom-export/hydrated-router.js +1 -1
  30. package/dist/development/lib/errors.js +1 -1
  31. package/dist/development/lib/hooks.js +1 -1
  32. package/dist/development/lib/href.js +1 -1
  33. package/dist/development/lib/router/history.js +1 -1
  34. package/dist/development/lib/router/instrumentation.d.ts +33 -8
  35. package/dist/development/lib/router/instrumentation.js +176 -99
  36. package/dist/development/lib/router/router.js +19 -19
  37. package/dist/development/lib/router/url.js +1 -1
  38. package/dist/development/lib/router/utils.js +17 -2
  39. package/dist/development/lib/rsc/browser.js +1 -1
  40. package/dist/development/lib/rsc/errorBoundaries.js +1 -1
  41. package/dist/development/lib/rsc/html-stream/browser.js +1 -1
  42. package/dist/development/lib/rsc/html-stream/server.js +1 -1
  43. package/dist/development/lib/rsc/route-modules.js +1 -1
  44. package/dist/development/lib/rsc/server.ssr.js +1 -1
  45. package/dist/development/lib/server-runtime/cookies.js +1 -1
  46. package/dist/development/lib/server-runtime/crypto.js +1 -1
  47. package/dist/development/lib/server-runtime/data.js +1 -1
  48. package/dist/development/lib/server-runtime/dev.js +1 -1
  49. package/dist/development/lib/server-runtime/entry.js +1 -1
  50. package/dist/development/lib/server-runtime/errors.js +1 -1
  51. package/dist/development/lib/server-runtime/headers.js +1 -1
  52. package/dist/development/lib/server-runtime/invariant.js +1 -1
  53. package/dist/development/lib/server-runtime/mode.js +1 -1
  54. package/dist/development/lib/server-runtime/routeMatching.js +1 -1
  55. package/dist/development/lib/server-runtime/routes.js +1 -1
  56. package/dist/development/lib/server-runtime/server.js +12 -5
  57. package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
  58. package/dist/development/lib/server-runtime/sessions/cookieStorage.js +1 -1
  59. package/dist/development/lib/server-runtime/sessions/memoryStorage.js +1 -1
  60. package/dist/development/lib/server-runtime/sessions.js +1 -1
  61. package/dist/development/lib/server-runtime/single-fetch.js +1 -1
  62. package/dist/development/lib/server-runtime/urls.js +1 -1
  63. package/dist/development/lib/server-runtime/warnings.js +1 -1
  64. package/dist/development/lib/types/internal.js +1 -1
  65. package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
  66. package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +1 -1
  67. package/dist/development/vendor/turbo-stream-v2/unflatten.js +1 -1
  68. package/dist/development/vendor/turbo-stream-v2/utils.js +1 -1
  69. package/dist/production/dom-export.js +1 -1
  70. package/dist/production/index-react-server-client.js +1 -1
  71. package/dist/production/index-react-server.d.ts +32 -7
  72. package/dist/production/index-react-server.js +180 -152
  73. package/dist/production/index.d.ts +2 -2
  74. package/dist/production/index.js +1 -1
  75. package/dist/production/lib/actions.js +1 -1
  76. package/dist/production/lib/components.js +1 -1
  77. package/dist/production/lib/context.js +1 -1
  78. package/dist/production/lib/dom/dom.js +1 -1
  79. package/dist/production/lib/dom/lib.js +2 -2
  80. package/dist/production/lib/dom/server.js +1 -1
  81. package/dist/production/lib/dom/ssr/components.js +1 -1
  82. package/dist/production/lib/dom/ssr/data.js +1 -1
  83. package/dist/production/lib/dom/ssr/errorBoundaries.js +1 -1
  84. package/dist/production/lib/dom/ssr/fallback.js +1 -1
  85. package/dist/production/lib/dom/ssr/fog-of-war.js +1 -1
  86. package/dist/production/lib/dom/ssr/hydration.js +1 -1
  87. package/dist/production/lib/dom/ssr/invariant.js +1 -1
  88. package/dist/production/lib/dom/ssr/links.js +1 -1
  89. package/dist/production/lib/dom/ssr/markup.js +1 -1
  90. package/dist/production/lib/dom/ssr/routeModules.js +1 -1
  91. package/dist/production/lib/dom/ssr/routes-test-stub.js +1 -1
  92. package/dist/production/lib/dom/ssr/routes.js +1 -1
  93. package/dist/production/lib/dom/ssr/server.js +1 -1
  94. package/dist/production/lib/dom/ssr/single-fetch.js +1 -1
  95. package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
  96. package/dist/production/lib/dom-export/hydrated-router.js +1 -1
  97. package/dist/production/lib/errors.js +1 -1
  98. package/dist/production/lib/hooks.js +1 -1
  99. package/dist/production/lib/href.js +1 -1
  100. package/dist/production/lib/router/history.js +1 -1
  101. package/dist/production/lib/router/instrumentation.d.ts +33 -8
  102. package/dist/production/lib/router/instrumentation.js +176 -99
  103. package/dist/production/lib/router/router.js +19 -19
  104. package/dist/production/lib/router/url.js +1 -1
  105. package/dist/production/lib/router/utils.js +17 -2
  106. package/dist/production/lib/rsc/browser.js +1 -1
  107. package/dist/production/lib/rsc/errorBoundaries.js +1 -1
  108. package/dist/production/lib/rsc/html-stream/browser.js +1 -1
  109. package/dist/production/lib/rsc/html-stream/server.js +1 -1
  110. package/dist/production/lib/rsc/route-modules.js +1 -1
  111. package/dist/production/lib/rsc/server.ssr.js +1 -1
  112. package/dist/production/lib/server-runtime/cookies.js +1 -1
  113. package/dist/production/lib/server-runtime/crypto.js +1 -1
  114. package/dist/production/lib/server-runtime/data.js +1 -1
  115. package/dist/production/lib/server-runtime/dev.js +1 -1
  116. package/dist/production/lib/server-runtime/entry.js +1 -1
  117. package/dist/production/lib/server-runtime/errors.js +1 -1
  118. package/dist/production/lib/server-runtime/headers.js +1 -1
  119. package/dist/production/lib/server-runtime/invariant.js +1 -1
  120. package/dist/production/lib/server-runtime/mode.js +1 -1
  121. package/dist/production/lib/server-runtime/routeMatching.js +1 -1
  122. package/dist/production/lib/server-runtime/routes.js +1 -1
  123. package/dist/production/lib/server-runtime/server.js +12 -5
  124. package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
  125. package/dist/production/lib/server-runtime/sessions/cookieStorage.js +1 -1
  126. package/dist/production/lib/server-runtime/sessions/memoryStorage.js +1 -1
  127. package/dist/production/lib/server-runtime/sessions.js +1 -1
  128. package/dist/production/lib/server-runtime/single-fetch.js +1 -1
  129. package/dist/production/lib/server-runtime/urls.js +1 -1
  130. package/dist/production/lib/server-runtime/warnings.js +1 -1
  131. package/dist/production/lib/types/internal.js +1 -1
  132. package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
  133. package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +1 -1
  134. package/dist/production/vendor/turbo-stream-v2/unflatten.js +1 -1
  135. package/dist/production/vendor/turbo-stream-v2/utils.js +1 -1
  136. package/docs/how-to/instrumentation.md +131 -26
  137. package/docs/upgrading/component-routes.md +1 -1
  138. package/docs/upgrading/router-provider.md +1 -1
  139. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { ErrorResponseImpl, RouterContextProvider, defaultMapRouteProperties, isRouteErrorResponse, removeTrailingSlash, stripBasename } from "../router/utils.js";
12
- import { instrumentHandler } from "../router/instrumentation.js";
11
+ import { ErrorResponseImpl, RouterContextProvider, createDataFunctionUrl, defaultMapRouteProperties, getRoutePattern, isRouteErrorResponse, removeTrailingSlash, stripBasename } from "../router/utils.js";
12
+ import { instrumentHandler, instrumentationResultMetaContext } from "../router/instrumentation.js";
13
13
  import { createStaticHandler, getStaticContextFromError, isMutationMethod, isRedirectResponse, isResponse } from "../router/router.js";
14
14
  import { getManifestPath } from "../dom/ssr/fog-of-war.js";
15
15
  import { createEntryRouteModules } from "./entry.js";
@@ -36,6 +36,7 @@ function derive(build, mode) {
36
36
  let errorHandler = build.entry.module.handleError || ((error, { request }) => {
37
37
  if (serverMode !== "test" && !request.signal.aborted) console.error(isRouteErrorResponse(error) && error.error ? error.error : error);
38
38
  });
39
+ let requestHandlerInstrumentations = build.entry.module.instrumentations?.map((i) => i.handler).filter(Boolean);
39
40
  let requestHandler = async (request, initialContext) => {
40
41
  let params = {};
41
42
  let loadContext;
@@ -54,7 +55,8 @@ function derive(build, mode) {
54
55
  }
55
56
  loadContext = initialContext || new RouterContextProvider();
56
57
  let requestUrl = new URL(request.url);
57
- let normalizedPathname = getNormalizedPath(request).pathname;
58
+ let normalizedPath = getNormalizedPath(request);
59
+ let normalizedPathname = normalizedPath.pathname;
58
60
  let isSpaMode = getBuildTimeHeader(request, "X-React-Router-SPA-Mode") === "yes";
59
61
  if (!build.ssr) {
60
62
  let decodedPath = decodeURI(normalizedPathname);
@@ -95,6 +97,11 @@ function derive(build, mode) {
95
97
  }
96
98
  let matches = matchServerRoutes(build.routes, staticHandler.dataRoutes, staticHandler._internalRouteBranches, normalizedPathname, build.basename);
97
99
  if (matches && matches.length > 0) Object.assign(params, matches[0].params);
100
+ if (requestHandlerInstrumentations?.length) loadContext.set(instrumentationResultMetaContext, {
101
+ url: createDataFunctionUrl(request, normalizedPath),
102
+ pattern: matches ? getRoutePattern(matches) : "",
103
+ params: matches?.[0]?.params ? { ...matches[0].params } : {}
104
+ });
98
105
  let response;
99
106
  if (requestUrl.pathname.endsWith(".data")) {
100
107
  response = await handleSingleFetchRequest(serverMode, build, staticHandler, request, loadContext, handleError);
@@ -122,7 +129,7 @@ function derive(build, mode) {
122
129
  });
123
130
  return response;
124
131
  };
125
- if (build.entry.module.instrumentations) requestHandler = instrumentHandler(requestHandler, build.entry.module.instrumentations.map((i) => i.handler).filter(Boolean));
132
+ if (requestHandlerInstrumentations?.length) requestHandler = instrumentHandler(requestHandler, requestHandlerInstrumentations);
126
133
  return {
127
134
  serverMode,
128
135
  staticHandler,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.1
2
+ * react-router v8.1.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -44,8 +44,11 @@ export const instrumentations = [
44
44
  async request(handleRequest, { request }) {
45
45
  let url = `${request.method} ${request.url}`;
46
46
  console.log(`Request start: ${url}`);
47
- await handleRequest();
48
- console.log(`Request end: ${url}`);
47
+ let result = await handleRequest();
48
+ let pattern = result.meta?.pattern ?? "unknown";
49
+ console.log(
50
+ `Request end: ${url} (${result.statusCode} ${pattern})`,
51
+ );
49
52
  },
50
53
  });
51
54
  },
@@ -92,20 +95,24 @@ const instrumentations = [
92
95
  router.instrument({
93
96
  // Instrument navigations
94
97
  async navigate(callNavigate, { currentUrl, to }) {
95
- let nav = `${currentUrl} ${to}`;
98
+ let nav = `${currentUrl} -> ${to}`;
96
99
  console.log(`Navigation start: ${nav}`);
97
- await callNavigate();
98
- console.log(`Navigation end: ${nav}`);
100
+ let result = await callNavigate();
101
+ console.log(
102
+ `Navigation end: ${nav} (${result.meta?.pattern})`,
103
+ );
99
104
  },
100
105
  // Instrument fetcher calls
101
106
  async fetch(
102
107
  callFetch,
103
108
  { href, currentUrl, fetcherKey },
104
109
  ) {
105
- let fetch = `${fetcherKey} ${href}`;
110
+ let fetch = `${fetcherKey} -> ${href}`;
106
111
  console.log(`Fetcher start: ${fetch}`);
107
- await callFetch();
108
- console.log(`Fetcher end: ${fetch}`);
112
+ let result = await callFetch();
113
+ console.log(
114
+ `Fetcher end: ${fetch} (${result.meta?.pattern})`,
115
+ );
109
116
  },
110
117
  });
111
118
  },
@@ -160,20 +167,24 @@ const instrumentations = [
160
167
  router.instrument({
161
168
  // Instrument navigations
162
169
  async navigate(callNavigate, { currentUrl, to }) {
163
- let nav = `${currentUrl} ${to}`;
170
+ let nav = `${currentUrl} -> ${to}`;
164
171
  console.log(`Navigation start: ${nav}`);
165
- await callNavigate();
166
- console.log(`Navigation end: ${nav}`);
172
+ let result = await callNavigate();
173
+ console.log(
174
+ `Navigation end: ${nav} (${result.meta?.pattern})`,
175
+ );
167
176
  },
168
177
  // Instrument fetcher calls
169
178
  async fetch(
170
179
  callFetch,
171
180
  { href, currentUrl, fetcherKey },
172
181
  ) {
173
- let fetch = `${fetcherKey} ${href}`;
182
+ let fetch = `${fetcherKey} -> ${href}`;
174
183
  console.log(`Fetcher start: ${fetch}`);
175
- await callFetch();
176
- console.log(`Fetcher end: ${fetch}`);
184
+ let result = await callFetch();
185
+ console.log(
186
+ `Fetcher end: ${fetch} (${result.meta?.pattern})`,
187
+ );
177
188
  },
178
189
  });
179
190
  },
@@ -227,7 +238,9 @@ export const instrumentations = [
227
238
  handler.instrument({
228
239
  async request(handleRequest, { request, context }) {
229
240
  // Runs around ALL requests to your app
230
- await handleRequest();
241
+ let result = await handleRequest();
242
+ let statusCode = result.statusCode;
243
+ let routePattern = result.meta?.pattern;
231
244
  },
232
245
  });
233
246
  },
@@ -248,14 +261,16 @@ export const instrumentations = [
248
261
  router.instrument({
249
262
  async navigate(callNavigate, { to, currentUrl }) {
250
263
  // Runs around navigation operations
251
- await callNavigate();
264
+ let result = await callNavigate();
265
+ let routePattern = result.meta?.pattern;
252
266
  },
253
267
  async fetch(
254
268
  callFetch,
255
269
  { href, currentUrl, fetcherKey },
256
270
  ) {
257
271
  // Runs around fetcher operations
258
- await callFetch();
272
+ let result = await callFetch();
273
+ let routePattern = result.meta?.pattern;
259
274
  },
260
275
  });
261
276
  },
@@ -327,7 +342,7 @@ This ensures that instrumentation is safe to add to production applications and
327
342
 
328
343
  To ensure that instrumentation code doesn't impact the runtime application, errors are caught internally and prevented from propagating outward. This design choice shows up in 2 aspects.
329
344
 
330
- First, if a "handler" function (loader, action, request handler, navigation, etc.) throws an error, that error will not bubble out of the `callHandler` function invoked from your instrumentation. Instead, the `callHandler` function returns a discriminated union result of type `{ type: "success", error: undefined } | { type: "error", error: unknown }`. This ensures your entire instrumentation function runs without needing any try/catch/finally logic to handle application errors.
345
+ First, if a "handler" function (loader, action, request handler, navigation, etc.) throws an error, that error will not bubble out of the `callHandler` function invoked from your instrumentation. Instead, the `callHandler` function returns a discriminated union result of type `{ status: "success", error: undefined } | { status: "error", error: Error }`. This ensures your entire instrumentation function runs without needing any try/catch/finally logic to handle application errors.
331
346
 
332
347
  ```tsx
333
348
  export const instrumentations = [
@@ -374,6 +389,64 @@ export const instrumentations = [
374
389
  ];
375
390
  ```
376
391
 
392
+ ### Result Metadata
393
+
394
+ Some instrumented calls return additional information that is only available after React Router starts processing the request, navigation, or fetcher call.
395
+
396
+ - Route-level instrumentations (`loader`/`action`/`middleware`) don't include `meta` because metadata is available on the `info` parameter
397
+ - Client navigation/fetcher and Server request handler instrumentations return a meta field
398
+ - `meta` contains the same values passed to loaders and actions
399
+ - `url`: The normalized `URL` for the matched route request
400
+ - `pattern`: The matched route pattern, such as `/projects/:id`
401
+ - `params`: The matched route params
402
+ - `meta` may be `undefined` when React Router does not have route metadata for the instrumented call, such as server manifest requests or numeric POP navigations like `navigate(-1)`
403
+ - For client navigations that redirect, `meta` describes the original navigation target instead of the final redirected location.
404
+ - Server request handler instrumentations also return the `statusCode` of the response
405
+
406
+ ```tsx
407
+ // entry.server.tsx
408
+ export const instrumentations = [
409
+ {
410
+ handler(handler) {
411
+ handler.instrument({
412
+ async request(handleRequest) {
413
+ let result = await handleRequest();
414
+
415
+ let statusCode = result.statusCode;
416
+ let routeUrl = result.meta?.url;
417
+ let routePattern = result.meta?.pattern;
418
+ let routeParams = result.meta?.params;
419
+ },
420
+ });
421
+ },
422
+ },
423
+ ];
424
+
425
+ // entry.client.tsx
426
+ const instrumentations = [
427
+ {
428
+ router(router) {
429
+ router.instrument({
430
+ async navigate(callNavigate) {
431
+ let result = await callNavigate();
432
+
433
+ let routeUrl = result.meta?.url;
434
+ let routePattern = result.meta?.pattern;
435
+ let routeParams = result.meta?.params;
436
+ },
437
+ async fetch(callFetch) {
438
+ let result = await callFetch();
439
+
440
+ let routeUrl = result.meta?.url;
441
+ let routePattern = result.meta?.pattern;
442
+ let routeParams = result.meta?.params;
443
+ },
444
+ });
445
+ },
446
+ },
447
+ ];
448
+ ```
449
+
377
450
  ### Composition
378
451
 
379
452
  You can compose multiple instrumentations by providing an array:
@@ -429,8 +502,16 @@ export const instrumentations = [
429
502
  const logging: ServerInstrumentation = {
430
503
  handler({ instrument }) {
431
504
  instrument({
432
- request: (fn, { request }) =>
433
- log(`request ${request.url}`, fn),
505
+ async request(fn, { request }) {
506
+ let label = `request ${request.url}`;
507
+ let start = Date.now();
508
+ console.log(`-> ${label}`);
509
+ let result = await fn();
510
+ let pattern = result.meta?.pattern ?? "";
511
+ console.log(
512
+ `<- ${label} (${Date.now() - start}ms ${result.statusCode} ${pattern})`,
513
+ );
514
+ },
434
515
  });
435
516
  },
436
517
  route({ instrument, id }) {
@@ -447,9 +528,9 @@ async function log(
447
528
  cb: () => Promise<InstrumentationHandlerResult>,
448
529
  ) {
449
530
  let start = Date.now();
450
- console.log(`➡️ ${label}`);
531
+ console.log(`-> ${label}`);
451
532
  await cb();
452
- console.log(`⬅️ ${label} (${Date.now() - start}ms)`);
533
+ console.log(`<- ${label} (${Date.now() - start}ms)`);
453
534
  }
454
535
 
455
536
  export const instrumentations = [logging];
@@ -523,10 +604,34 @@ export const instrumentations = [otel];
523
604
  const windowPerf: ClientInstrumentation = {
524
605
  router({ instrument }) {
525
606
  instrument({
526
- navigate: (fn, { to, currentUrl }) =>
527
- measure(`navigation:${currentUrl}->${to}`, fn),
528
- fetch: (fn, { href }) =>
529
- measure(`fetcher:${href}`, fn),
607
+ async navigate(fn, { to, currentUrl }) {
608
+ let label = `navigation:${currentUrl}->${to}`;
609
+ performance.mark(`start:${label}`);
610
+ let result = await fn();
611
+ performance.mark(`end:${label}`);
612
+ performance.measure(
613
+ label,
614
+ `start:${label}`,
615
+ `end:${label}`,
616
+ );
617
+ console.log(
618
+ `navigation pattern: ${result.meta?.pattern}`,
619
+ );
620
+ },
621
+ async fetch(fn, { href }) {
622
+ let label = `fetcher:${href}`;
623
+ performance.mark(`start:${label}`);
624
+ let result = await fn();
625
+ performance.mark(`end:${label}`);
626
+ performance.measure(
627
+ label,
628
+ `start:${label}`,
629
+ `end:${label}`,
630
+ );
631
+ console.log(
632
+ `fetcher pattern: ${result.meta?.pattern}`,
633
+ );
634
+ },
530
635
  });
531
636
  },
532
637
  route({ instrument, id }) {
@@ -9,7 +9,7 @@ If you are using `<RouterProvider>` please see [Framework Adoption from RouterPr
9
9
 
10
10
  If you are using `<Routes>` this is the right place.
11
11
 
12
- The React Router Vite plugin adds framework features to React Router. This guide will help you adopt the plugin in your app. If you run into any issues, please reach out for help on [Twitter](https://x.com/remix_run) or [Discord](https://rmx.as/discord).
12
+ The React Router Vite plugin adds framework features to React Router. This guide will help you adopt the plugin in your app. If you run into any issues, please reach out for help on [Twitter](https://x.com/remix_run) or [Discord](https://remix.run/discord).
13
13
 
14
14
  ## Features
15
15
 
@@ -7,7 +7,7 @@ order: 5
7
7
 
8
8
  If you are not using `<RouterProvider>` please see [Framework Adoption from Component Routes][upgrade-component-routes] instead.
9
9
 
10
- The React Router Vite plugin adds framework features to React Router. This guide will help you adopt the plugin in your app. If you run into any issues, please reach out for help on [Twitter](https://x.com/remix_run) or [Discord](https://rmx.as/discord).
10
+ The React Router Vite plugin adds framework features to React Router. This guide will help you adopt the plugin in your app. If you run into any issues, please reach out for help on [Twitter](https://x.com/remix_run) or [Discord](https://remix.run/discord).
11
11
 
12
12
  ## Features
13
13
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-router",
3
3
  "type": "module",
4
- "version": "8.0.1",
4
+ "version": "8.1.0",
5
5
  "description": "Declarative routing for React",
6
6
  "keywords": [
7
7
  "react",