Sebastian Markbåge
all · built 2026-09-10
Performance
What Sebastian Markbåge shipped in the selected window, measured in ETV, and how it compares with the 90 days before it.
Effective capacity
−1.0engineers
delivers like 0.0 (0.0x pre-AI)
Output (ETV)
0.0ETV
±0% vs 0.0 prior
Features share
0.0%
±0 pp vs prior window
Fixes share
0.0%
±0 pp vs prior window
Work mix
0% Features0% Maintenance0% Tests0% Docs0% Fixes
0 commits over 90 days, ending 2026-09-10.
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 60 %
- By Features share
- Top 6 %
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 10 by ETV across all time.
- 4.7ETVImplement Partial Hydration for Activity (#32863) Stacked on #32862 and #32842. This means that Activity boundaries now act as boundaries which can have their effects mounted independently. Just like Suspense boundaries, we hydrate the outer content first and then start hydrating the content in an Offscreen lane. Flowing props or interacting with the content increases the priority just like Suspense boundaries. This skips emitting even the comments for `<Activity mode="hidden">` so we don't hydrate those. Instead those are deferred to a later client render. The implementation are just forked copies of the SuspenseComponent branches and then carefully going through each line and tweaking it. The main interesting bit is that, unlike Suspense, Activity boundaries don't have fallbacks so all those branches where you might commit a suspended tree disappears. Instead, if something suspends while hydration, we can just leave the dehydrated content in place. However, if something does suspend during client rendering then it should bubble up to the parent. Therefore, we have to be careful to only pushSuspenseHandler when hydrating. That's really the main difference. This just uses the existing basic Activity tests but I've started work on port all of the applicable Suspense tests in SelectiveHydration-test and PartialHydration-test to Activity versions.github.com-facebook-react · 3ef31d19 · 2025-04-23
- 2.1ETVPatch FlightReplyServer with fixes from ReactFlightClient (#35277) FlightReplyServer are for client->server and ReactFlightClient is for server->client. They're not 100% symmetrical. We did a number of refactors to ReactFlightClient in PRs like #29823 and #33664 to change the structure of the resolution. This PR brings those changes to synchronize the two approaches. Which addresses deep resolution of cycles and deferred error handling. This also fixes a critical security vulnerability.github.com-facebook-react · 7dc903cd · 2025-12-03
- 2.0ETVAdd <ViewTransition> Component (#31975) This will provide the opt-in for using [View Transitions](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) in React. View Transitions only trigger for async updates like `startTransition`, `useDeferredValue`, Actions or `<Suspense>` revealing from fallback to content. Synchronous updates provide an opt-out but also guarantee that they commit immediately which View Transitions can't. There's no need to opt-in to View Transitions at the "cause" side like event handlers or actions. They don't know what UI will change and whether that has an animated transition described. Conceptually the `<ViewTransition>` component is like a DOM fragment that transitions its children in its own isolate/snapshot. The API works by wrapping a DOM node or inner component: ```js import {ViewTransition} from 'react'; <ViewTransition><Component /></ViewTransition> ``` The default is `name="auto"` which will automatically assign a `view-transition-name` to the inner DOM node. That way you can add a View Transition to a Component without controlling its DOM nodes styling otherwise. A difference between this and the browser's built-in `view-transition-name: auto` is that switching the DOM nodes within the `<ViewTransition>` component preserves the same name so this example cross-fades between the DOM nodes instead of causing an exit and enter: ```js <ViewTransition>{condition ? <ComponentA /> : <ComponentB />}</ViewTransition> ``` This becomes especially useful with `<Suspense>` as this example cross-fades between Skeleton and Content: ```js <ViewTransition> <Suspense fallback={<Skeleton />}> <Content /> </Suspense> </ViewTransition> ``` Where as this example triggers an exit of the Skeleton and an enter of the Content: ```js <Suspense fallback={<ViewTransition><Skeleton /></ViewTransition>}> <ViewTransition><Content /></ViewTransition> </Suspense> ``` Managing instances and keys becomes extra important. You can also specify an explicit `name` property for example for animating the same conceptual item from one page onto another. However, best practices is to property namespace these since they can easily collide. It's also useful to add an `id` to it if available. ```js <ViewTransition name="my-shared-view"> ``` The model in general is the same as plain `view-transition-name` except React manages a set of heuristics for when to apply it. A problem with the naive View Transitions model is that it overly opts in every boundary that *might* transition into transitioning. This is leads to unfortunate effects like things floating around when unrelated updates happen. This leads the whole document to animate which means that nothing is clickable in the meantime. It makes it not useful for smaller and more local transitions. Best practice is to add `view-transition-name` only right before you're about to need to animate the thing. This is tricky to manage globally on complex apps and is not compositional. Instead we let React manage when a `<ViewTransition>` "activates" and add/remove the `view-transition-name`. This is also when React calls `startViewTransition` behind the scenes while it mutates the DOM. I've come up with a number of heuristics that I think will make a lot easier to coordinate this. The principle is that only if something that updates that particular boundary do we activate it. I hope that one day maybe browsers will have something like these built-in and we can remove our implementation. A `<ViewTransition>` only activates if: - If a mounted Component renders a `<ViewTransition>` within it outside the first DOM node, and it is within the viewport, then that ViewTransition activates as an "enter" animation. This avoids inner "enter" animations trigger when the parent mounts. - If an unmounted Component had a `<ViewTransition>` within it outside the first DOM node, and it was within the viewport, then that ViewTransition activates as an "exit" animation. This avoids inner "exit" animations triggering when the parent unmounts. - If an explicitly named `<ViewTransition name="...">` is deep within an unmounted tree and one with the same name appears in a mounted tree at the same time, then both are activated as a pair, but only if they're both in the viewport. This avoids these triggering "enter" or "exit" animations when going between parents that don't have a pair. - If an already mounted `<ViewTransition>` is visible and a DOM mutation, that might affect how it's painted, happens within its children but outside any nested `<ViewTransition>`. This allows it to "cross-fade" between its updates. - If an already mounted `<ViewTransition>` resizes or moves as the result of direct DOM nodes siblings changing or moving around. This allows insertion, deletion and reorders into a list to animate all children. It is only within one DOM node though, to avoid unrelated changes in the parent to trigger this. If an item is outside the viewport before and after, then it's skipped to avoid things flying across the screen. - If a `<ViewTransition>` boundary changes size, due to a DOM mutation within it, then the parent activates (or the root document if there are no more parents). This ensures that the container can cross-fade to avoid abrupt relayout. This can be avoided by using absolutely positioned children. When this can avoid bubbling to the root document, whatever is not animating is still responsive to clicks during the transition. Conceptually each DOM node has its own default that activates the parent `<ViewTransition>` or no transition if the parent is the root. That means that if you add a DOM node like `<div><ViewTransition><Component /></ViewTransition></div>` this won't trigger an "enter" animation since it was the div that was added, not the ViewTransition. Instead, it might cause a cross-fade of the parent ViewTransition or no transition if it had no parent. This ensures that only explicit boundaries perform coarse animations instead of every single node which is really the benefit of the View Transitions model. This ends up working out well for simple cases like switching between two pages immediately while transitioning one floating item that appears on both pages. Because only the floating item transitions by default. Note that it's possible to add manual `view-transition-name` with CSS or `style={{ viewTransitionName: 'auto' }}` that always transitions as long as something else has a `<ViewTransition>` that activates. For example a `<ViewTransition>` can wrap a whole page for a cross-fade but inside of it an explicit name can be added to something to ensure it animates as a move when something relates else changes its layout. Instead of just cross-fading it along with the Page which would be the default. There's more PRs coming with some optimizations, fixes and expanded APIs. This first PR explores the above core heuristic. --------- Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>github.com-facebook-react · a4d122f2 · 2025-01-08
- 1.6ETV[Flight] Add Debug Channel option for stateful connection to the backend in DEV (#33627) This adds plumbing for opening a stream from the Flight Client to the Flight Server so it can ask for more data on-demand. In this mode, the Flight Server keeps the connection open as long as the client is still alive and there's more objects to load. It retains any depth limited objects so that they can be asked for later. In this first PR it just releases the object when it's discovered on the server and doesn't actually lazy load it yet. That's coming in a follow up. This strategy is built on the model that each request has its own channel for this. Instead of some global registry. That ensures that referential identity is preserved within a Request and the Request can refer to previously written objects by reference. The fixture implements a WebSocket per request but it doesn't have to be done that way. It can be multiplexed through an existing WebSocket for example. The current protocol is just a Readable(Stream) on the server and WritableStream on the client. It could even be sent through a HTTP request body if browsers implemented full duplex (which they don't). This PR only implements the direction of messages from Client to Server. However, I also plan on adding Debug Channel in the other direction to allow debug info (optionally) be sent from Server to Client through this channel instead of through the main RSC request. So the `debugChannel` option will be able to take writable or readable or both. --------- Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>github.com-facebook-react · bbc13fa1 · 2025-06-24
- 1.6ETV[DevTools] Use use() instead of throwing a Promise in Caches (#34033)github.com-facebook-react · 5d7e8b90 · 2025-07-29
- 1.6ETV[Flight] Add Separate Outgoing Debug Channel (#33754) This lets us pass a writable on the server side and readable on the client side to send debug info through a separate channel so that it doesn't interfere with the main payload as much. The main payload refers to chunks defined in the debug info which means it's still blocked on it though. This ensures that the debug data has loaded by the time the value is rendered so that the next step can forward the data. This will be a bit fragile to race conditions until #33665 lands. Another follow up needed is the ability to skip the debug channel on the receiving side. Right now it'll block forever if you don't provide one since we're blocking on the debug data.github.com-facebook-react · eb7f8b42 · 2025-07-10
- 1.3ETV[Flight] Make debug info and console log resolve in predictable order (#33665) This resolves an outstanding issue where it was possible for debug info and console logs to become out of order if they up blocked. E.g. by a future reference or a client reference that hasn't loaded yet. Such as if you console.log a client reference followed by one that doesn't. This encodes the order similar to how the stream chunks work. This also blocks the main chunk from resolving until the last debug info has fully loaded, including future references and client references. This also ensures that we could send some of that data in a different stream, since then it can come out of order.github.com-facebook-react · 28d4bc49 · 2025-07-20
- 1.1ETV[Flight] Track I/O Entry for the RSC Stream itself (#34425) One thing that can suspend is the downloading of the RSC stream itself. This tracks an I/O entry for each Promise (`SomeChunk<T>`) that represents the request to the RSC stream. As the value we use the `Response` for `createFromFetch` (or the `ReadableStream` for `createFromReadableStream`). The start time is when you called those. Since we're not awaiting the whole stream, each I/O entry represents the part of the stream up until it got unblocked. However, in a production environment with TLS packets and buffering in practice the chunks received by the client isn't exactly at the boundary of each row. It's a bit longer into larger chunks. From testing, it seems like multiples of 16kb or 64kb uncompressed are common. To simulate a production environment we group into roughly 64kb chunks if they happen in rapid sequence. Note that this might be too small to give a good idea because of the throttle many boundaries might be skipped anyway so this might show too many. The React DevTools will see each I/O entry as separate but dedupe if an outer boundary already depends on the same chunk. This deduping makes it so that small boundaries that are blocked on the same chunk, don't get treated as having unique suspenders. If you have a boundary with large content, then that content will likely be in a separate chunk which is not in the parent and then it gets marked as. This is all just an approximation. The goal of this is just to highlight that very large boundaries will very likely suspend even if they don't suspend on any I/O on the server. In practice, these boundaries can float around a lot and it's really any Suspense boundary that might suspend but some are more likely than others which this is meant to highlight. It also just lets you inspect how many bytes needs to be transferred before you can show a particular part of the content, to give you an idea that it's not just I/O on the server that might suspend. If you don't use the debug channel it can be misleading since the data in development mode stream will have a lot more data in it which leads to more chunking. Similarly to "client references" these I/O infos don't have an "env" since it's the client that has the I/O and so those are excluded from flushing in the Server performance tracks. Note that currently the same Response can appear many times in the same Instance of SuspenseNode in DevTools when there are multiple chunks. In a follow up I'll show only the last one per Response at any given level. Note that when a separate debugChannel is used it has its own I/O entry that's on the `_debugInfo` for the debug chunks in that channel. However, if everything works correctly these should never leak into the DevTools UI since they should never be propagated from a debug chunk to the values waited by the runtime. This is easy to break though.github.com-facebook-react · 969a9790 · 2025-09-09
- 1.0ETV[Flight] Patch Promise cycles and toString on Server Functions (#35345) Server Functions can be stringified (sometimes implicitly) when passed as data. This adds an override to hide the source code in that case - just in case someone puts sensitive information in there. Note that this still preserves the `name` field but this is also available on the export but in practice is likely minified anyway. There's nothing else on these referenes we'd consider unsafe unless you explicitly expose expandos which are part of the `"use server"` export. This adds a safety check to ensure you don't encode cyclic Promises. This isn't a parser bug per se. Promises do have a safety mechanism that avoids them infinite looping. However, since we use custom Thenables, what can happen is that every time a native Promise awaits it, another Promise wrapper is created around the Thenable which foils the ECMAScript Promise cycle detection which can lead to an infinite loop. This also ensures that embedded `ReadableStream` and `AsyncIterable` streams are properly closed if the source stream closes early both on the Server and Client. This doesn't cause an infinite loop but just to make sure resource clean up can proceed properly. We're also adding some more explicit clear errors for invalid payloads since we no longer need to obfuscate the original issue.github.com-facebook-react · 894bc73c · 2025-12-11
- 1.0ETV[Flight] Add Web Stream support to the Flight Server in Node (#33474) This needs some tweaks to the implementation and a conversion but simple enough. --------- Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>github.com-facebook-react · 9666605a · 2025-06-07