@rsc-kit/core 0.30.9 → 0.30.10
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/vite.d.ts +17 -0
- package/dist/vite.js +99 -1
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
package/dist/vite.d.ts
CHANGED
|
@@ -491,6 +491,23 @@ export type TypecheckOutcome = {
|
|
|
491
491
|
* is the message, because that is what the developer would have read.
|
|
492
492
|
*/
|
|
493
493
|
export declare function typecheckProject(root: string): TypecheckOutcome;
|
|
494
|
+
/**
|
|
495
|
+
* The engine's modules that exist for the server, by file under the package
|
|
496
|
+
* and the entry point an app imports them through.
|
|
497
|
+
*
|
|
498
|
+
* Importing one from a file the browser also imports does not fail at runtime:
|
|
499
|
+
* the module loads, a dynamic import of a Node builtin is left dangling, and
|
|
500
|
+
* Vite prints that it was "externalized for browser compatibility". The
|
|
501
|
+
* warning is the only trace of a server module having shipped to every visitor
|
|
502
|
+
* - `redirect()` reached the dashboard's bundle through a helper file that a
|
|
503
|
+
* client component and a page both imported. Named here so it is refused.
|
|
504
|
+
*
|
|
505
|
+
* Internal files that only a server entry reaches are listed against the entry,
|
|
506
|
+
* so the message names what the app imported rather than what that imports.
|
|
507
|
+
*/
|
|
508
|
+
export declare const SERVER_ONLY: Record<string, string>;
|
|
509
|
+
/** The entry point a module of this package is reached through, when it is a server-only one. */
|
|
510
|
+
export declare function serverOnlyEntry(id: string, root: string): string | null;
|
|
494
511
|
/**
|
|
495
512
|
* A Nitro runtime plugin, so a rollout stops a server cleanly.
|
|
496
513
|
*
|
package/dist/vite.js
CHANGED
|
@@ -17,7 +17,7 @@ import { gzipSync } from "node:zlib";
|
|
|
17
17
|
import { createHash } from "node:crypto";
|
|
18
18
|
import { createRequire } from "node:module";
|
|
19
19
|
import { spawnSync } from "node:child_process";
|
|
20
|
-
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
20
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
21
21
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
22
22
|
import rsc, { getPluginApi } from "@vitejs/plugin-rsc";
|
|
23
23
|
import { loadEnv, parseAst } from "vite";
|
|
@@ -6706,6 +6706,103 @@ function typecheckPlugin() {
|
|
|
6706
6706
|
},
|
|
6707
6707
|
};
|
|
6708
6708
|
}
|
|
6709
|
+
/**
|
|
6710
|
+
* The engine's modules that exist for the server, by file under the package
|
|
6711
|
+
* and the entry point an app imports them through.
|
|
6712
|
+
*
|
|
6713
|
+
* Importing one from a file the browser also imports does not fail at runtime:
|
|
6714
|
+
* the module loads, a dynamic import of a Node builtin is left dangling, and
|
|
6715
|
+
* Vite prints that it was "externalized for browser compatibility". The
|
|
6716
|
+
* warning is the only trace of a server module having shipped to every visitor
|
|
6717
|
+
* - `redirect()` reached the dashboard's bundle through a helper file that a
|
|
6718
|
+
* client component and a page both imported. Named here so it is refused.
|
|
6719
|
+
*
|
|
6720
|
+
* Internal files that only a server entry reaches are listed against the entry,
|
|
6721
|
+
* so the message names what the app imported rather than what that imports.
|
|
6722
|
+
*/
|
|
6723
|
+
export const SERVER_ONLY = {
|
|
6724
|
+
request: "request",
|
|
6725
|
+
redirect: "redirect",
|
|
6726
|
+
revalidate: "revalidate",
|
|
6727
|
+
cache: "cache",
|
|
6728
|
+
"js/section": "section",
|
|
6729
|
+
"js/refreshOn": "section",
|
|
6730
|
+
host: "host",
|
|
6731
|
+
hostCalls: "host-calls",
|
|
6732
|
+
prerender: "prerender",
|
|
6733
|
+
export: "export",
|
|
6734
|
+
files: "files",
|
|
6735
|
+
"build-rsc-vite": "build",
|
|
6736
|
+
runtime: "runtime",
|
|
6737
|
+
embed: "embed",
|
|
6738
|
+
typegen: "typegen",
|
|
6739
|
+
conformance: "conformance",
|
|
6740
|
+
testing: "testing",
|
|
6741
|
+
vite: "vite",
|
|
6742
|
+
};
|
|
6743
|
+
/** The entry point a module of this package is reached through, when it is a server-only one. */
|
|
6744
|
+
export function serverOnlyEntry(id, root) {
|
|
6745
|
+
const file = relative(root, id.split("?")[0]).replace(/\\/g, "/");
|
|
6746
|
+
if (file.startsWith("..") || isAbsolute(file))
|
|
6747
|
+
return null;
|
|
6748
|
+
const key = file.replace(/\.(c|m)?(j|t)sx?$/, "");
|
|
6749
|
+
return SERVER_ONLY[key] ?? null;
|
|
6750
|
+
}
|
|
6751
|
+
/**
|
|
6752
|
+
* Refuse a server-only module in the browser bundle, with the files that
|
|
6753
|
+
* brought it there.
|
|
6754
|
+
*
|
|
6755
|
+
* Only the client environment: the ssr one renders client components to HTML on
|
|
6756
|
+
* the server and imports the request module legitimately, and the rsc one is
|
|
6757
|
+
* where these belong. In a build it is read off the finished module graph; in
|
|
6758
|
+
* dev, as the browser asks for each module.
|
|
6759
|
+
*/
|
|
6760
|
+
function serverOnlyInTheBrowser() {
|
|
6761
|
+
const fail = (entry, chain) => {
|
|
6762
|
+
const files = chain.map((file) => relative(projectRoot, file).replace(/\\/g, "/"));
|
|
6763
|
+
const lines = files.map((file, i) => ` ${i === 0 ? "imported by" : "which is imported by"} ${file}`);
|
|
6764
|
+
throw new Error(`[rsc-kit] '${PACKAGE_NAME}/${entry}' is for the server, and ended up in the browser bundle:\n` +
|
|
6765
|
+
lines.join("\n") +
|
|
6766
|
+
"\n\nA file the browser imports must not import it, even to call it only on the server. " +
|
|
6767
|
+
"Move what needs it into a file that only server components import, and keep what a client " +
|
|
6768
|
+
"component needs in another.");
|
|
6769
|
+
};
|
|
6770
|
+
const chainOf = (start, importersOf) => {
|
|
6771
|
+
const chain = [];
|
|
6772
|
+
for (let id = importersOf(start)[0]; id && chain.length < 6; id = importersOf(id)[0]) {
|
|
6773
|
+
if (chain.includes(id))
|
|
6774
|
+
break;
|
|
6775
|
+
chain.push(id.split("?")[0]);
|
|
6776
|
+
}
|
|
6777
|
+
return chain;
|
|
6778
|
+
};
|
|
6779
|
+
return {
|
|
6780
|
+
name: "rsc-kit:server-only",
|
|
6781
|
+
applyToEnvironment: (environment) => environment.name === "client",
|
|
6782
|
+
// In dev, the first request for it. The graph the browser asks for grows as
|
|
6783
|
+
// pages are visited, so this is where a leak shows up there.
|
|
6784
|
+
transform(_code, id) {
|
|
6785
|
+
if (this.environment.mode === "build")
|
|
6786
|
+
return;
|
|
6787
|
+
const entry = serverOnlyEntry(id, packageDir);
|
|
6788
|
+
if (!entry)
|
|
6789
|
+
return;
|
|
6790
|
+
// Only a dev environment has a module graph; a build reads the bundler's.
|
|
6791
|
+
const graph = this.environment.moduleGraph;
|
|
6792
|
+
const importers = (of) => [...(graph?.getModuleById(of)?.importers ?? [])].map((m) => m.id ?? "");
|
|
6793
|
+
fail(entry, chainOf(id, importers));
|
|
6794
|
+
},
|
|
6795
|
+
buildEnd() {
|
|
6796
|
+
if (this.environment.mode !== "build")
|
|
6797
|
+
return;
|
|
6798
|
+
for (const id of this.getModuleIds()) {
|
|
6799
|
+
const entry = serverOnlyEntry(id, packageDir);
|
|
6800
|
+
if (entry)
|
|
6801
|
+
fail(entry, chainOf(id, (of) => this.getModuleInfo(of)?.importers ?? []));
|
|
6802
|
+
}
|
|
6803
|
+
},
|
|
6804
|
+
};
|
|
6805
|
+
}
|
|
6709
6806
|
/**
|
|
6710
6807
|
* Which server files import a client library, read off the rsc environment's
|
|
6711
6808
|
* module graph once it is built. plugin-rsc classifies the client packages
|
|
@@ -7737,6 +7834,7 @@ export function rscKit(options = {}) {
|
|
|
7737
7834
|
stableComponentNames(),
|
|
7738
7835
|
typecheckPlugin(),
|
|
7739
7836
|
clientImportsAudit(),
|
|
7837
|
+
serverOnlyInTheBrowser(),
|
|
7740
7838
|
routesPlugin,
|
|
7741
7839
|
];
|
|
7742
7840
|
}
|