@rsc-kit/core 0.20.5 → 0.20.7
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/dist/js/ActivityRouter.js +5 -0
- package/dist/js/ActivityRouter.js.map +1 -1
- package/dist/js/Link.d.ts +1 -1
- package/dist/js/Link.js +25 -9
- package/dist/js/Link.js.map +1 -1
- package/dist/js/PageTransition.d.ts +27 -0
- package/dist/js/PageTransition.js +57 -0
- package/dist/js/PageTransition.js.map +1 -0
- package/dist/js/SegmentBoundary.js +8 -0
- package/dist/js/SegmentBoundary.js.map +1 -1
- package/dist/js/earlyClicks.d.ts +3 -2
- package/dist/js/earlyClicks.js +11 -5
- package/dist/js/earlyClicks.js.map +1 -1
- package/dist/js/navigate.d.ts +14 -1
- package/dist/js/navigate.js +56 -5
- package/dist/js/navigate.js.map +1 -1
- package/dist/js/perf.d.ts +25 -0
- package/dist/js/perf.js +57 -0
- package/dist/js/perf.js.map +1 -0
- package/dist/js/router.d.ts +10 -1
- package/dist/js/router.js +9 -2
- package/dist/js/router.js.map +1 -1
- package/dist/js/viewportPrefetch.d.ts +19 -10
- package/dist/js/viewportPrefetch.js +23 -13
- package/dist/js/viewportPrefetch.js.map +1 -1
- package/dist/vite.js +18 -1
- package/dist/vite.js.map +1 -1
- package/package.json +5 -1
package/dist/js/router.d.ts
CHANGED
|
@@ -8,7 +8,16 @@ import type { Route, RevalidateTarget } from "../routes.js";
|
|
|
8
8
|
export declare function visit(url: Route, opts?: {
|
|
9
9
|
replace?: boolean;
|
|
10
10
|
}): Promise<void>;
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Fetch a page's payload before a navigation asks for it.
|
|
13
|
+
*
|
|
14
|
+
* `intent: true` also decodes it as it lands, which loads the client chunks
|
|
15
|
+
* the page names - for a link the visitor is about to follow, not for one
|
|
16
|
+
* that may never be.
|
|
17
|
+
*/
|
|
18
|
+
export declare function prefetch(url: Route, cacheForMs?: number, opts?: {
|
|
19
|
+
intent?: boolean;
|
|
20
|
+
}): void;
|
|
12
21
|
/**
|
|
13
22
|
* Ask the server for part of the current page again.
|
|
14
23
|
*
|
package/dist/js/router.js
CHANGED
|
@@ -11,12 +11,19 @@ export function visit(url, opts) {
|
|
|
11
11
|
}
|
|
12
12
|
return nav(url, opts);
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Fetch a page's payload before a navigation asks for it.
|
|
16
|
+
*
|
|
17
|
+
* `intent: true` also decodes it as it lands, which loads the client chunks
|
|
18
|
+
* the page names - for a link the visitor is about to follow, not for one
|
|
19
|
+
* that may never be.
|
|
20
|
+
*/
|
|
21
|
+
export function prefetch(url, cacheForMs, opts) {
|
|
15
22
|
const fn = window.__rsc_prefetch;
|
|
16
23
|
if (!fn) {
|
|
17
24
|
throw new Error("RSC navigation not initialized. Ensure createViteRscApp has been called.");
|
|
18
25
|
}
|
|
19
|
-
fn(url, cacheForMs);
|
|
26
|
+
fn(url, cacheForMs, opts?.intent ?? false);
|
|
20
27
|
}
|
|
21
28
|
/**
|
|
22
29
|
* Ask the server for part of the current page again.
|
package/dist/js/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/js/router.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,UAAU,KAAK,CACnB,GAAU,EACV,IAA4B;IAE5B,MAAM,GAAG,GAAI,MAAc,CAAC,cAAc,CAAC;IAE3C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAU,EAAE,UAAmB;
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/js/router.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,UAAU,KAAK,CACnB,GAAU,EACV,IAA4B;IAE5B,MAAM,GAAG,GAAI,MAAc,CAAC,cAAc,CAAC;IAE3C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAU,EAAE,UAAmB,EAAE,IAA2B;IACnF,MAAM,EAAE,GAAI,MAAc,CAAC,cAAc,CAAC;IAE1C,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC9F,CAAC;IAED,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,OAAO,CAAC,MAAyB;IAC/C,MAAM,EAAE,GAAI,MAAc,CAAC,aAAa,CAAC;IAEzC,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC5C,eAAe,MAAM,CAAC","sourcesContent":["/**\n * Programmatic navigation API for use from client components.\n *\n * Reads from window globals set by createViteRscApp, since client components\n * are built in a separate build graph and cannot directly import navigate.ts.\n */\n\nimport type { Route, RevalidateTarget } from \"../routes.js\";\n\nexport function visit(\n url: Route,\n opts?: { replace?: boolean }\n): Promise<void> {\n const nav = (window as any).__rsc_navigate;\n\n if (!nav) {\n throw new Error(\"RSC navigation not initialized. Ensure createViteRscApp has been called.\");\n }\n\n return nav(url, opts);\n}\n\n/**\n * Fetch a page's payload before a navigation asks for it.\n *\n * `intent: true` also decodes it as it lands, which loads the client chunks\n * the page names - for a link the visitor is about to follow, not for one\n * that may never be.\n */\nexport function prefetch(url: Route, cacheForMs?: number, opts?: { intent?: boolean }): void {\n const fn = (window as any).__rsc_prefetch;\n\n if (!fn) {\n throw new Error(\"RSC navigation not initialized. Ensure createViteRscApp has been called.\");\n }\n\n fn(url, cacheForMs, opts?.intent ?? false);\n}\n\n/**\n * Ask the server for part of the current page again.\n *\n * refresh() the page, leaving the layouts mounted\n * refresh('all') the whole document\n * refresh('orders') one parallel slot\n *\n * The page form leaves the layouts alone, so anything living in one — a count\n * in a sidebar, say — will not move until you ask for 'all'.\n */\nexport function refresh(target?: RevalidateTarget): Promise<void> {\n const fn = (window as any).__rsc_refresh;\n\n if (!fn) {\n throw new Error(\"RSC navigation not initialized. Ensure createViteRscApp has been called.\");\n }\n\n return fn(target);\n}\n\nconst router = { visit, prefetch, refresh };\nexport default router;\n"]}
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Prefetching a link as it comes into view
|
|
2
|
+
* Prefetching a link as it comes into view.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* a
|
|
4
|
+
* A navigation is as fast as what is already in the browser when the click
|
|
5
|
+
* lands, and a hover is too late to fetch that: a pointer that has settled
|
|
6
|
+
* on a link is 200-300 ms from clicking it, and on a phone the first signal
|
|
7
|
+
* is touchstart, 100-300 ms before the click - about a round trip either
|
|
8
|
+
* way, so a fetch started there has barely left when the navigation needs
|
|
9
|
+
* it. Next prefetches the links on screen instead, and that is what makes
|
|
10
|
+
* its clicks feel like a single-page app's: the payload was there before
|
|
11
|
+
* the pointer moved. So, on every device, the links on screen are fetched -
|
|
12
|
+
* the bytes only; decoding a payload loads the chunks it names, and that
|
|
13
|
+
* waits for the hover or the touch that says which link is meant. It used
|
|
14
|
+
* to be phones only, with a hover-capable device left to the hover: a click
|
|
15
|
+
* that came quicker than the round trip waited for it, and desktop was
|
|
16
|
+
* fast but not instant.
|
|
17
|
+
*
|
|
18
|
+
* Not when the visitor asked for less data: Save-Data is the one signal a
|
|
19
|
+
* browser gives that speculative requests are unwelcome.
|
|
11
20
|
*
|
|
12
21
|
* One observer for every link, and the work is done when the browser is
|
|
13
22
|
* idle - a list scrolled into view is many links at once, and the browser's
|
|
@@ -15,7 +24,7 @@
|
|
|
15
24
|
* yet. Each link prefetches once; the router keeps the payload for its TTL.
|
|
16
25
|
*/
|
|
17
26
|
/**
|
|
18
|
-
* Prefetch when the link is on screen
|
|
19
|
-
*
|
|
27
|
+
* Prefetch when the link is on screen. Returns the function that stops
|
|
28
|
+
* watching; a no-op where this does not apply.
|
|
20
29
|
*/
|
|
21
30
|
export declare function prefetchWhenVisible(element: Element | null, fire: () => void): () => void;
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Prefetching a link as it comes into view
|
|
2
|
+
* Prefetching a link as it comes into view.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* a
|
|
4
|
+
* A navigation is as fast as what is already in the browser when the click
|
|
5
|
+
* lands, and a hover is too late to fetch that: a pointer that has settled
|
|
6
|
+
* on a link is 200-300 ms from clicking it, and on a phone the first signal
|
|
7
|
+
* is touchstart, 100-300 ms before the click - about a round trip either
|
|
8
|
+
* way, so a fetch started there has barely left when the navigation needs
|
|
9
|
+
* it. Next prefetches the links on screen instead, and that is what makes
|
|
10
|
+
* its clicks feel like a single-page app's: the payload was there before
|
|
11
|
+
* the pointer moved. So, on every device, the links on screen are fetched -
|
|
12
|
+
* the bytes only; decoding a payload loads the chunks it names, and that
|
|
13
|
+
* waits for the hover or the touch that says which link is meant. It used
|
|
14
|
+
* to be phones only, with a hover-capable device left to the hover: a click
|
|
15
|
+
* that came quicker than the round trip waited for it, and desktop was
|
|
16
|
+
* fast but not instant.
|
|
17
|
+
*
|
|
18
|
+
* Not when the visitor asked for less data: Save-Data is the one signal a
|
|
19
|
+
* browser gives that speculative requests are unwelcome.
|
|
11
20
|
*
|
|
12
21
|
* One observer for every link, and the work is done when the browser is
|
|
13
22
|
* idle - a list scrolled into view is many links at once, and the browser's
|
|
@@ -16,8 +25,9 @@
|
|
|
16
25
|
*/
|
|
17
26
|
let observer = null;
|
|
18
27
|
const pending = new WeakMap();
|
|
19
|
-
function
|
|
20
|
-
|
|
28
|
+
function savingData() {
|
|
29
|
+
const connection = navigator.connection;
|
|
30
|
+
return connection?.saveData === true;
|
|
21
31
|
}
|
|
22
32
|
function whenIdle(fn) {
|
|
23
33
|
const idle = window.requestIdleCallback;
|
|
@@ -48,11 +58,11 @@ function observerFor() {
|
|
|
48
58
|
return observer;
|
|
49
59
|
}
|
|
50
60
|
/**
|
|
51
|
-
* Prefetch when the link is on screen
|
|
52
|
-
*
|
|
61
|
+
* Prefetch when the link is on screen. Returns the function that stops
|
|
62
|
+
* watching; a no-op where this does not apply.
|
|
53
63
|
*/
|
|
54
64
|
export function prefetchWhenVisible(element, fire) {
|
|
55
|
-
if (!element ||
|
|
65
|
+
if (!element || savingData())
|
|
56
66
|
return () => { };
|
|
57
67
|
const io = observerFor();
|
|
58
68
|
if (!io)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewportPrefetch.js","sourceRoot":"","sources":["../../src/js/viewportPrefetch.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"viewportPrefetch.js","sourceRoot":"","sources":["../../src/js/viewportPrefetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,IAAI,QAAQ,GAAgC,IAAI,CAAA;AAChD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAuB,CAAA;AAElD,SAAS,UAAU;IACjB,MAAM,UAAU,GAAI,SAAqD,CAAC,UAAU,CAAA;IAEpF,OAAO,UAAU,EAAE,QAAQ,KAAK,IAAI,CAAA;AACtC,CAAC;AAED,SAAS,QAAQ,CAAC,EAAc;IAC9B,MAAM,IAAI,GAAI,MAAyF,CAAC,mBAAmB,CAAA;IAE3H,IAAI,IAAI;QAAE,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;;QAChC,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,WAAW;IAClB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,IAAI,OAAO,oBAAoB,KAAK,WAAW;QAAE,OAAO,IAAI,CAAA;IAE5D,QAAQ,GAAG,IAAI,oBAAoB,CACjC,CAAC,OAAO,EAAE,EAAE;QACV,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,cAAc;gBAAE,SAAQ;YAEnC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YAEtC,QAAS,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YAE5B,IAAI,IAAI;gBAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;IACD,sEAAsE;IACtE,sBAAsB;IACtB,EAAE,UAAU,EAAE,OAAO,EAAE,CACxB,CAAA;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAuB,EAAE,IAAgB;IAC3E,IAAI,CAAC,OAAO,IAAI,UAAU,EAAE;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IAE7C,MAAM,EAAE,GAAG,WAAW,EAAE,CAAA;IAExB,IAAI,CAAC,EAAE;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IAExB,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAC1B,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAEnB,OAAO,GAAG,EAAE;QACV,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACvB,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACvB,CAAC,CAAA;AACH,CAAC","sourcesContent":["/**\n * Prefetching a link as it comes into view.\n *\n * A navigation is as fast as what is already in the browser when the click\n * lands, and a hover is too late to fetch that: a pointer that has settled\n * on a link is 200-300 ms from clicking it, and on a phone the first signal\n * is touchstart, 100-300 ms before the click - about a round trip either\n * way, so a fetch started there has barely left when the navigation needs\n * it. Next prefetches the links on screen instead, and that is what makes\n * its clicks feel like a single-page app's: the payload was there before\n * the pointer moved. So, on every device, the links on screen are fetched -\n * the bytes only; decoding a payload loads the chunks it names, and that\n * waits for the hover or the touch that says which link is meant. It used\n * to be phones only, with a hover-capable device left to the hover: a click\n * that came quicker than the round trip waited for it, and desktop was\n * fast but not instant.\n *\n * Not when the visitor asked for less data: Save-Data is the one signal a\n * browser gives that speculative requests are unwelcome.\n *\n * One observer for every link, and the work is done when the browser is\n * idle - a list scrolled into view is many links at once, and the browser's\n * per-origin connections should not all be taken by pages nobody has tapped\n * yet. Each link prefetches once; the router keeps the payload for its TTL.\n */\n\nlet observer: IntersectionObserver | null = null\nconst pending = new WeakMap<Element, () => void>()\n\nfunction savingData(): boolean {\n const connection = (navigator as { connection?: { saveData?: boolean } }).connection\n\n return connection?.saveData === true\n}\n\nfunction whenIdle(fn: () => void): void {\n const idle = (window as { requestIdleCallback?: (fn: () => void, opts?: { timeout: number }) => void }).requestIdleCallback\n\n if (idle) idle(fn, { timeout: 1000 })\n else setTimeout(fn, 50)\n}\n\nfunction observerFor(): IntersectionObserver | null {\n if (observer) return observer\n if (typeof IntersectionObserver === \"undefined\") return null\n\n observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (!entry.isIntersecting) continue\n\n const fire = pending.get(entry.target)\n\n observer!.unobserve(entry.target)\n pending.delete(entry.target)\n\n if (fire) whenIdle(fire)\n }\n },\n // A little ahead of the fold: a link about to scroll into view is one\n // about to be tapped.\n { rootMargin: \"200px\" },\n )\n\n return observer\n}\n\n/**\n * Prefetch when the link is on screen. Returns the function that stops\n * watching; a no-op where this does not apply.\n */\nexport function prefetchWhenVisible(element: Element | null, fire: () => void): () => void {\n if (!element || savingData()) return () => {}\n\n const io = observerFor()\n\n if (!io) return () => {}\n\n pending.set(element, fire)\n io.observe(element)\n\n return () => {\n pending.delete(element)\n io.unobserve(element)\n }\n}\n"]}
|
package/dist/vite.js
CHANGED
|
@@ -5558,7 +5558,11 @@ export function rscKit(options = {}) {
|
|
|
5558
5558
|
// documents, for as long as the browser holds the script.
|
|
5559
5559
|
nitro.options.routeRules = {
|
|
5560
5560
|
...(nitro.options.routeRules ?? {}),
|
|
5561
|
-
|
|
5561
|
+
// Spelled with max-age=0 rather than no-cache: a CDN's browser
|
|
5562
|
+
// cache TTL - Cloudflare's, four hours - applies where the origin
|
|
5563
|
+
// names no max-age, and rewrote no-cache to max-age=14400; a
|
|
5564
|
+
// max-age of zero it leaves alone, as it leaves the documents'.
|
|
5565
|
+
"/sw.js": { ...(nitro.options.routeRules?.["/sw.js"] ?? {}), headers: { "cache-control": "public, max-age=0, must-revalidate", ...(nitro.options.routeRules?.["/sw.js"]?.headers ?? {}) } },
|
|
5562
5566
|
};
|
|
5563
5567
|
// The names of functions survive Nitro's bundle. The pages were
|
|
5564
5568
|
// prerendered against Vite's own server bundles, where a dependency
|
|
@@ -5812,6 +5816,17 @@ export function rscKit(options = {}) {
|
|
|
5812
5816
|
rollupOptions: {
|
|
5813
5817
|
input: { index: join(genDir, "entry.rsc.tsx") },
|
|
5814
5818
|
external: serverExternals,
|
|
5819
|
+
// The server-references map is `id: () => import(file)` for
|
|
5820
|
+
// every "use server" file, and the page that passes an action
|
|
5821
|
+
// to <Form> imports the same file statically. Rolldown says
|
|
5822
|
+
// so for each one: "dynamically imported by
|
|
5823
|
+
// virtual:vite-rsc/server-references but also statically
|
|
5824
|
+
// imported by page.tsx, dynamic import will not move module
|
|
5825
|
+
// into another chunk". Nothing was meant to move: a server
|
|
5826
|
+
// bundle has no chunk to lazy-load from a browser, and the
|
|
5827
|
+
// map is a lookup table, not a split point. One line per
|
|
5828
|
+
// action in every build was a paragraph nobody could act on.
|
|
5829
|
+
checks: { ineffectiveDynamicImport: false },
|
|
5815
5830
|
},
|
|
5816
5831
|
},
|
|
5817
5832
|
resolve: { noExternal: bundledClientPackages },
|
|
@@ -5822,6 +5837,8 @@ export function rscKit(options = {}) {
|
|
|
5822
5837
|
rollupOptions: {
|
|
5823
5838
|
input: { index: join(genDir, "entry.ssr.tsx") },
|
|
5824
5839
|
external: serverExternals,
|
|
5840
|
+
// Same table, same reason.
|
|
5841
|
+
checks: { ineffectiveDynamicImport: false },
|
|
5825
5842
|
},
|
|
5826
5843
|
},
|
|
5827
5844
|
resolve: { noExternal: bundledClientPackages },
|