A tool for people curious about the React Server Components protocol
rscexplorer.dev/
rsc
react
1#!/usr/bin/env node
2
3import { execSync } from "child_process";
4import { parseArgs } from "util";
5import { readFileSync } from "fs";
6import ALL_VERSIONS from "./versions.json" with { type: "json" };
7
8const REACT_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"];
9
10function run(cmd) {
11 console.log(`\n> ${cmd}`);
12 execSync(cmd, { stdio: "inherit" });
13}
14
15function getLatestVersion() {
16 const pkg = JSON.parse(readFileSync("package.json", "utf-8"));
17 return pkg.dependencies.react;
18}
19
20function installReactVersion(version) {
21 const packages = REACT_PACKAGES.map((p) => `${p}@${version}`).join(" ");
22 run(`npm install ${packages} --no-save`);
23}
24
25function testVersion(version) {
26 console.log(`\n--- Running tests for React ${version} ---`);
27 run("npm test");
28}
29
30function buildForVersion(version, outDir) {
31 console.log(`\n========================================`);
32 console.log(`Building React ${version} (dev + prod) → ${outDir || `dist/${version}`}`);
33 console.log(`========================================`);
34
35 installReactVersion(version);
36 testVersion(version);
37
38 const dir = outDir || `dist/${version}`;
39 // Base path for assets (e.g., /19.1.0/ or / for root)
40 const basePath = outDir === "dist" ? "/" : `/${version}/`;
41 const devBasePath = outDir === "dist" ? "/dev/" : `/${version}/dev/`;
42
43 // Production build
44 console.log(`\n--- Production build ---`);
45 run(`npm run build -- --outDir=${dir} --base=${basePath}`);
46
47 // Development build (unminified, development mode)
48 console.log(`\n--- Development build ---`);
49 run(
50 `npm run build -- --outDir=${dir}/dev --base=${devBasePath} --mode=development --minify=false`,
51 );
52}
53
54function restorePackages() {
55 console.log(`\n========================================`);
56 console.log(`Restoring original packages`);
57 console.log(`========================================`);
58 run("npm install");
59}
60
61// Parse arguments
62const { values } = parseArgs({
63 options: {
64 version: { type: "string", short: "v" },
65 all: { type: "boolean", short: "a" },
66 },
67 allowPositionals: true,
68});
69
70try {
71 if (values.all) {
72 // Build latest (from package.json) to dist/ root first (cleans dist/)
73 const latest = getLatestVersion();
74 buildForVersion(latest, "dist");
75 // Then build all versions to dist/{version}/ (each cleans only its own dir)
76 for (const version of ALL_VERSIONS) {
77 buildForVersion(version);
78 }
79 } else if (values.version) {
80 // Build single version
81 buildForVersion(values.version);
82 } else {
83 console.error("Usage:");
84 console.error(" node scripts/build-version.js --version=19.2.0");
85 console.error(" node scripts/build-version.js --all");
86 process.exit(1);
87 }
88
89 restorePackages();
90 console.log("\nDone!");
91} catch (err) {
92 console.error("\nBuild failed:", err.message);
93 // Still try to restore packages on failure
94 try {
95 restorePackages();
96 } catch {}
97 process.exit(1);
98}