Skip to content

Conversation

@ngbrown
Copy link
Contributor

@ngbrown ngbrown commented Sep 12, 2025

This is a small optimization to href() to not use a backtracking regex on splat paths.

The speedup of the new trimEndSplat() method over the regex /\/*\*?$/ is about 17x to 36x speedup: jsbenchmark.com benchmark

The speedup of all of href() with options is about 1.2x to 1.5x speedup: jsbenchmark.com benchmark

This could also apply to compilePath(), but that only runs once per path at application load, not many times per page in the React render loop.

@changeset-bot
Copy link

changeset-bot bot commented Sep 12, 2025

🦋 Changeset detected

Latest commit: ba26a58

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
react-router Patch
@react-router/architect Patch
@react-router/cloudflare Patch
@react-router/dev Patch
react-router-dom Patch
@react-router/express Patch
@react-router/node Patch
@react-router/serve Patch
@react-router/fs-routes Patch
@react-router/remix-routes-option-adapter Patch
create-react-router Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ngbrown ngbrown force-pushed the faster-trim-end-splat branch from 0271f76 to 0835456 Compare October 22, 2025 15:21
@ngbrown
Copy link
Contributor Author

ngbrown commented Nov 21, 2025

@timdorr and @pcattori This improvement to href() has been approved for awhile. Can it be merged now?

@pcattori pcattori merged commit 1dbf8e3 into remix-run:dev Nov 21, 2025
5 checks passed
@ngbrown ngbrown deleted the faster-trim-end-splat branch November 24, 2025 14:54
@github-actions
Copy link
Contributor

github-actions bot commented Dec 2, 2025

🤖 Hello there,

We just published version 7.10.0 which includes this pull request. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

Doridian pushed a commit to foxCaves/foxCaves that referenced this pull request Dec 3, 2025
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [react-router](https://github.com/remix-run/react-router) ([source](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router)) | [`7.9.6` -> `7.10.0`](https://renovatebot.com/diffs/npm/react-router/7.9.6/7.10.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/react-router/7.10.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-router/7.9.6/7.10.0?slim=true) |

---

### Release Notes

<details>
<summary>remix-run/react-router (react-router)</summary>

### [`v7.10.0`](https://github.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#7100)

[Compare Source](https://github.com/remix-run/react-router/compare/[email protected]@7.10.0)

##### Minor Changes

- Stabilize `fetcher.reset()` ([#&#8203;14545](remix-run/react-router#14545))
  - ⚠️ This is a breaking change if you have begun using `fetcher.unstable_reset()`

- Stabilize the `dataStrategy` `match.shouldRevalidateArgs`/`match.shouldCallHandler()` APIs. ([#&#8203;14592](remix-run/react-router#14592))

  - The `match.shouldLoad` API is now marked deprecated in favor of these more powerful alternatives

  - If you're using this API in a custom `dataStrategy` today, you can swap to the new API at your convenience:

    ```tsx
    // Before
    const matchesToLoad = matches.filter((m) => m.shouldLoad);

    // After
    const matchesToLoad = matches.filter((m) => m.shouldCallHandler());
    ```

  - `match.shouldRevalidateArgs` is the argument that will be passed to the route `shouldRevaliate` function

  - Combined with the parameter accepted by `match.shouldCallHandler`, you can define a custom revalidation behavior for your `dataStrategy`:

  ```tsx
  const matchesToLoad = matches.filter((m) => {
    const defaultShouldRevalidate = customRevalidationBehavior(
      match.shouldRevalidateArgs,
    );
    return m.shouldCallHandler(defaultShouldRevalidate);
    // The argument here will override the internal `defaultShouldRevalidate` value
  });
  ```

##### Patch Changes

- Fix a Framework Mode bug where the `defaultShouldRevalidate` parameter to `shouldRevalidate` would not be correct after `action` returned a 4xx/5xx response (`true` when it should have been `false`) ([#&#8203;14592](remix-run/react-router#14592))
  - If your `shouldRevalidate` function relied on that parameter, you may have seen unintended revalidations

- Fix `fetcher.submit` failing with plain objects containing a `tagName` property ([#&#8203;14534](remix-run/react-router#14534))

- \[UNSTABLE] Add `unstable_pattern` to the parameters for client side `unstable_onError`, refactor how it's called by `RouterProvider` to avoid potential strict mode issues ([#&#8203;14573](remix-run/react-router#14573))

- Add new `unstable_useTransitions` flag to routers to give users control over the usage of [`React.startTransition`](https://react.dev/reference/react/startTransition) and [`React.useOptimistic`](https://react.dev/reference/react/useOptimistic). ([#&#8203;14524](remix-run/react-router#14524))
  - Framework Mode + Data Mode:
    - `<HydratedRouter unstable_transition>`/`<RouterProvider unstable_transition>`
    - When left unset (current default behavior)
      - Router state updates are wrapped in `React.startTransition`
      - ⚠️ This can lead to buggy behaviors if you are wrapping your own navigations/fetchers in `React.startTransition`
      - You should set the flag to `true` if you run into this scenario to get the enhanced `useOptimistic` behavior (requires React 19)
    - When set to `true`
      - Router state updates remain wrapped in `React.startTransition` (as they are without the flag)
      - `Link`/`Form` navigations will be wrapped in `React.startTransition`
      - A subset of router state info will be surfaced to the UI *during* navigations via `React.useOptimistic` (i.e., `useNavigation()`, `useFetchers()`, etc.)
        - ⚠️ This is a React 19 API so you must also be React 19 to opt into this flag for Framework/Data Mode
    - When set to `false`
      - The router will not leverage `React.startTransition` or `React.useOptimistic` on any navigations or state changes
  - Declarative Mode
    - `<BrowserRouter unstable_useTransitions>`
    - When left unset
      - Router state updates are wrapped in `React.startTransition`
    - When set to `true`
      - Router state updates remain wrapped in `React.startTransition` (as they are without the flag)
      - `Link`/`Form` navigations will be wrapped in `React.startTransition`
    - When set to `false`
      - the router will not leverage `React.startTransition` on any navigations or state changes

- Fix the promise returned from `useNavigate` in Framework/Data Mode so that it properly tracks the duration of `popstate` navigations (i.e., `navigate(-1)`) ([#&#8203;14524](remix-run/react-router#14524))

- Fix internal type error in useRoute types that surfaces when skipLibCheck is disabled ([#&#8203;14577](remix-run/react-router#14577))

- Preserve `statusText` on the `ErrorResponse` instance when throwing `data()` from a route handler ([#&#8203;14555](remix-run/react-router#14555))

- Optimize href() to avoid backtracking regex on splat ([#&#8203;14329](remix-run/react-router#14329))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4yNy4xIiwidXBkYXRlZEluVmVyIjoiNDIuMjcuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://git.foxden.network/foxCaves/foxCaves/pulls/13
Co-authored-by: Renovate <[email protected]>
Co-committed-by: Renovate <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants