@lazarv/react-server 0.0.0-experimental-43e79e6-20230928

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.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/bin/cli.mjs +93 -0
  4. package/bin/commands/build.mjs +19 -0
  5. package/bin/commands/dev.mjs +23 -0
  6. package/bin/commands/start.mjs +16 -0
  7. package/bin/loader.mjs +38 -0
  8. package/client/ActionState.mjs +16 -0
  9. package/client/ClientOnly.jsx +14 -0
  10. package/client/ClientProvider.jsx +243 -0
  11. package/client/ErrorBoundary.jsx +45 -0
  12. package/client/FlightContext.mjs +3 -0
  13. package/client/Link.jsx +59 -0
  14. package/client/Params.mjs +15 -0
  15. package/client/ReactServerComponent.jsx +77 -0
  16. package/client/Refresh.jsx +52 -0
  17. package/client/components.mjs +28 -0
  18. package/client/context.mjs +6 -0
  19. package/client/entry.client.jsx +146 -0
  20. package/client/index.jsx +6 -0
  21. package/client/navigation.jsx +4 -0
  22. package/config/context.mjs +37 -0
  23. package/config/index.mjs +114 -0
  24. package/lib/build/action.mjs +57 -0
  25. package/lib/build/banner.mjs +13 -0
  26. package/lib/build/chunks.mjs +26 -0
  27. package/lib/build/client.mjs +114 -0
  28. package/lib/build/custom-logger.mjs +13 -0
  29. package/lib/build/dependencies.mjs +54 -0
  30. package/lib/build/resolve.mjs +101 -0
  31. package/lib/build/server.mjs +142 -0
  32. package/lib/build/static.mjs +89 -0
  33. package/lib/dev/action.mjs +63 -0
  34. package/lib/dev/create-logger.mjs +52 -0
  35. package/lib/dev/create-server.mjs +208 -0
  36. package/lib/dev/modules.mjs +20 -0
  37. package/lib/dev/ssr-handler.mjs +135 -0
  38. package/lib/handlers/error.mjs +153 -0
  39. package/lib/handlers/not-found.mjs +5 -0
  40. package/lib/handlers/redirect.mjs +1 -0
  41. package/lib/handlers/rewrite.mjs +1 -0
  42. package/lib/handlers/static.mjs +120 -0
  43. package/lib/handlers/trailing-slash.mjs +12 -0
  44. package/lib/plugins/react-server.mjs +73 -0
  45. package/lib/plugins/use-client.mjs +135 -0
  46. package/lib/plugins/use-server.mjs +175 -0
  47. package/lib/start/action.mjs +110 -0
  48. package/lib/start/create-server.mjs +111 -0
  49. package/lib/start/manifest.mjs +104 -0
  50. package/lib/start/ssr-handler.mjs +134 -0
  51. package/lib/sys.mjs +49 -0
  52. package/lib/utils/merge.mjs +31 -0
  53. package/lib/utils/server-address.mjs +14 -0
  54. package/memory-cache/index.mjs +125 -0
  55. package/package.json +81 -0
  56. package/react-server.d.ts +209 -0
  57. package/server/ErrorBoundary.jsx +14 -0
  58. package/server/RemoteComponent.jsx +210 -0
  59. package/server/Route.jsx +108 -0
  60. package/server/actions.mjs +72 -0
  61. package/server/cache.mjs +19 -0
  62. package/server/client-component.mjs +62 -0
  63. package/server/context.mjs +32 -0
  64. package/server/cookies.mjs +14 -0
  65. package/server/entry.server.jsx +972 -0
  66. package/server/error-boundary.jsx +2 -0
  67. package/server/http-headers.mjs +8 -0
  68. package/server/http-status.mjs +6 -0
  69. package/server/index.mjs +14 -0
  70. package/server/logger.mjs +15 -0
  71. package/server/module-loader.mjs +20 -0
  72. package/server/redirects.mjs +45 -0
  73. package/server/remote-component.jsx +2 -0
  74. package/server/request.mjs +37 -0
  75. package/server/revalidate.mjs +22 -0
  76. package/server/rewrites.mjs +0 -0
  77. package/server/router.jsx +6 -0
  78. package/server/runtime.mjs +32 -0
  79. package/server/symbols.mjs +24 -0
@@ -0,0 +1,77 @@
1
+ "use client";
2
+
3
+ import { startTransition, useContext, useEffect, useState } from "react";
4
+
5
+ import { ClientContext, useClient } from "./context.mjs";
6
+ import { FlightContext } from "./FlightContext.mjs";
7
+
8
+ function FlightComponent({ standalone = false, remote = false, children }) {
9
+ const { url, outlet } = useContext(FlightContext);
10
+ const client = useClient();
11
+ const { registerOutlet, subscribe, getFlightResponse } = client;
12
+ const [Component, setComponent] = useState(
13
+ remote
14
+ ? getFlightResponse(url, { outlet, standalone })
15
+ : children || getFlightResponse(url, { outlet, standalone })
16
+ );
17
+ const [error, setError] = useState(null);
18
+
19
+ useEffect(() => {
20
+ let mounted = true;
21
+ const unregisterOutlet = registerOutlet(outlet, url);
22
+ const unsubscribe = subscribe(outlet || url, (to, callback) => {
23
+ const Component = getFlightResponse(to, { outlet, standalone });
24
+ Component.then(
25
+ () => {
26
+ if (!mounted) return;
27
+ startTransition(async () => {
28
+ setError(null);
29
+ const {
30
+ value: { data: result },
31
+ } = Component.value.props;
32
+ setComponent(Component);
33
+ callback(null, result);
34
+ });
35
+ },
36
+ () => {
37
+ if (!mounted) return;
38
+ startTransition(() => {
39
+ setError(Component.reason);
40
+ const {
41
+ value: { data: result },
42
+ } = Component.value.props;
43
+ callback(Component.reason, result);
44
+ });
45
+ }
46
+ );
47
+ });
48
+ return () => {
49
+ mounted = false;
50
+ unregisterOutlet();
51
+ unsubscribe();
52
+ };
53
+ }, [url, outlet, standalone, subscribe, getFlightResponse]);
54
+
55
+ return (
56
+ <ClientContext.Provider value={{ ...client, error }}>
57
+ {Component}
58
+ </ClientContext.Provider>
59
+ );
60
+ }
61
+
62
+ /**
63
+ * @typedef {import("react").PropsWithChildren<{ url: string, standalone?: boolean }>} ReactServerComponentProps
64
+ * @param { ReactServerComponentProps } props
65
+ */
66
+ export default function ReactServerComponent({
67
+ url,
68
+ outlet = null,
69
+ standalone,
70
+ children,
71
+ }) {
72
+ return (
73
+ <FlightContext.Provider value={{ url, outlet }}>
74
+ <FlightComponent standalone={standalone}>{children}</FlightComponent>
75
+ </FlightContext.Provider>
76
+ );
77
+ }
@@ -0,0 +1,52 @@
1
+ "use client";
2
+
3
+ import { useClient } from "@lazarv/react-server/client";
4
+ import { startTransition, useCallback } from "react";
5
+
6
+ export default function Refresh({
7
+ url,
8
+ outlet,
9
+ transition,
10
+ prefetch: prefetchEnabled,
11
+ ttl = Infinity,
12
+ onRefresh,
13
+ onError,
14
+ children,
15
+ ...props
16
+ }) {
17
+ const { refresh, prefetch } = useClient();
18
+
19
+ const tryRefresh = useCallback(async () => {
20
+ try {
21
+ await refresh(outlet || url);
22
+ onRefresh?.();
23
+ } catch (e) {
24
+ onError?.(e);
25
+ }
26
+ }, [refresh, outlet, url, onRefresh, onError]);
27
+
28
+ const handleRefresh = async (e) => {
29
+ e.preventDefault();
30
+ if (transition !== false) {
31
+ startTransition(tryRefresh);
32
+ } else {
33
+ tryRefresh();
34
+ }
35
+ };
36
+
37
+ const handlePrefetch = () =>
38
+ prefetchEnabled === true && prefetch(url, { outlet, ttl });
39
+
40
+ return (
41
+ <a
42
+ {...props}
43
+ href={url}
44
+ onClick={handleRefresh}
45
+ onFocus={handlePrefetch}
46
+ onMouseOver={handlePrefetch}
47
+ onTouchStart={handlePrefetch}
48
+ >
49
+ {children}
50
+ </a>
51
+ );
52
+ }
@@ -0,0 +1,28 @@
1
+ export function client$(Component, name = "default") {
2
+ if (typeof window !== "undefined") return Component;
3
+
4
+ let id = "default";
5
+ try {
6
+ throw new Error();
7
+ } catch (e) {
8
+ const [, , source] = e.stack.split("\n");
9
+ id =
10
+ /\((.*):[0-9]+:[0-9]+\)/.exec(source)?.[1] ??
11
+ /file:\/\/(.*):[0-9]+:[0-9]+/.exec(source)?.[1] ??
12
+ "default";
13
+ }
14
+
15
+ Object.defineProperties(Component, {
16
+ $$typeof: {
17
+ value: Symbol.for("react.client.reference"),
18
+ },
19
+ $$id: {
20
+ value: `${id}::${name}`,
21
+ },
22
+ $$async: {
23
+ value: true,
24
+ },
25
+ });
26
+
27
+ return Component;
28
+ }
@@ -0,0 +1,6 @@
1
+ import { createContext, useContext } from "react";
2
+
3
+ export const ClientContext = createContext({});
4
+ export function useClient() {
5
+ return useContext(ClientContext);
6
+ }
@@ -0,0 +1,146 @@
1
+ import ClientProvider, {
2
+ PAGE_ROOT,
3
+ } from "@lazarv/react-server/client/ClientProvider.jsx";
4
+ import ReactServerComponent from "@lazarv/react-server/client/ReactServerComponent.jsx";
5
+ import { startTransition, StrictMode } from "react";
6
+ import { hydrateRoot } from "react-dom/client";
7
+
8
+ function ReactServer() {
9
+ return (
10
+ <ClientProvider>
11
+ <ReactServerComponent outlet={PAGE_ROOT} url={location.href} />
12
+ </ClientProvider>
13
+ );
14
+ }
15
+
16
+ if (import.meta.env.DEV) {
17
+ var formatRegExp = /%[sdj%]/g;
18
+ const format = (f, ...args) => {
19
+ let i = 0;
20
+ const len = args.length;
21
+ const str = String(f).replace(formatRegExp, function (x) {
22
+ if (x === "%%") return "%";
23
+ if (i >= len) return x;
24
+ switch (x) {
25
+ case "%s":
26
+ return String(args[i++]);
27
+ case "%d":
28
+ return Number(args[i++]);
29
+ case "%j":
30
+ try {
31
+ return JSON.stringify(args[i++]);
32
+ } catch (_) {
33
+ return "[Circular]";
34
+ }
35
+ default:
36
+ return x;
37
+ }
38
+ });
39
+ return str;
40
+ };
41
+
42
+ const { ErrorOverlay } = await import("/@vite/client");
43
+
44
+ const showErrorOverlay = async (error, source, force) => {
45
+ if (
46
+ localStorage.getItem("react-server:overlay") === "false" ||
47
+ sessionStorage.getItem("react-server:overlay") === "false"
48
+ ) {
49
+ return;
50
+ }
51
+
52
+ if (!window.__react_server_error_overlay__) {
53
+ if (typeof error === "string") {
54
+ const [message, ...stack] = error.split("\n");
55
+ error = {
56
+ message,
57
+ stack: stack.join("\n"),
58
+ };
59
+ }
60
+ error.plugin = "@lazarv/react-server";
61
+ const [, ...stacklines] = error.stack.split("\n");
62
+ error.stack = stacklines.map((it) => it.trim()).join("\n");
63
+ const [, id, line, column] = (stacklines?.[0] ?? "").match(
64
+ /\((.*):([0-9]+):([0-9]+)\)/
65
+ );
66
+ error.id = id || source;
67
+
68
+ if (!force && error.id.startsWith("http")) {
69
+ return setTimeout(() => showErrorOverlay(error, source, true));
70
+ }
71
+ window.__react_server_error_overlay__ = true;
72
+
73
+ error.loc = {
74
+ file: id,
75
+ column: parseInt(column, 10),
76
+ line: parseInt(line, 10),
77
+ length: 0,
78
+ lineText: "",
79
+ namespace: "",
80
+ suggestion: "",
81
+ };
82
+
83
+ try {
84
+ const sourceFile = await fetch(
85
+ error.id.startsWith("http")
86
+ ? error.id.replace("/@fs/", "/@source/")
87
+ : `/@source${error.id}`
88
+ );
89
+ const sourceCode = await sourceFile.text();
90
+
91
+ const lines = sourceCode.split("\n");
92
+ const start = Math.max(0, error.loc.line - 3);
93
+ const end = Math.min(lines.length, error.loc.line + 3);
94
+ const frame = lines
95
+ .slice(start, end)
96
+ .flatMap((l, i) => {
97
+ const curr = i + start;
98
+ const indent = " ".repeat(
99
+ Math.max(start, end).toString().length - curr.toString().length
100
+ );
101
+ return [
102
+ `${indent}${curr} | ${l}`,
103
+ ...(i === 2
104
+ ? [
105
+ `${indent}${curr
106
+ .toString()
107
+ .replaceAll(/./g, " ")} |${" ".repeat(
108
+ error.loc.column
109
+ )}^`,
110
+ ]
111
+ : []),
112
+ ];
113
+ })
114
+ .join("\n");
115
+ error.frame = `${error.message}\n${frame}\n`;
116
+ } catch (e) {
117
+ // noop
118
+ }
119
+
120
+ const overlay = new ErrorOverlay(error);
121
+ overlay.addEventListener("click", () => {
122
+ window.__react_server_error_overlay__ = false;
123
+ });
124
+ document.body.appendChild(overlay);
125
+ }
126
+ };
127
+
128
+ const originalConsoleError = console.error;
129
+ console.error = (...args) => {
130
+ showErrorOverlay(format(...args));
131
+ originalConsoleError(...args);
132
+ };
133
+
134
+ window.onerror = (message, source, lineno, colno, error) => {
135
+ showErrorOverlay(error, source, lineno, colno, message);
136
+ };
137
+ }
138
+
139
+ startTransition(() => {
140
+ hydrateRoot(
141
+ document,
142
+ <StrictMode>
143
+ <ReactServer />
144
+ </StrictMode>
145
+ );
146
+ });
@@ -0,0 +1,6 @@
1
+ export * from "./context.mjs";
2
+ export { default as ClientOnly } from "./ClientOnly.jsx";
3
+
4
+ export function client$(Component) {
5
+ return Component;
6
+ }
@@ -0,0 +1,4 @@
1
+ import Link from "@lazarv/react-server/client/Link.jsx";
2
+ import Refresh from "@lazarv/react-server/client/Refresh.jsx";
3
+
4
+ export { Link, Refresh };
@@ -0,0 +1,37 @@
1
+ import { getContext } from "@lazarv/react-server/server/context.mjs";
2
+ import {
3
+ CONFIG_CONTEXT,
4
+ CONFIG_ROOT,
5
+ } from "@lazarv/react-server/server/symbols.mjs";
6
+
7
+ export function forRoot(externalConfig) {
8
+ const config = getContext(CONFIG_CONTEXT) ?? externalConfig;
9
+ if (!config) {
10
+ throw new Error("Config not loaded");
11
+ }
12
+ return config[CONFIG_ROOT];
13
+ }
14
+
15
+ export function forChild(url, externalConfig) {
16
+ if (typeof url !== "string") {
17
+ url = url.pathname;
18
+ }
19
+ const config = getContext(CONFIG_CONTEXT) ?? externalConfig;
20
+ if (!config) {
21
+ throw new Error("Config not loaded");
22
+ }
23
+ if (!config[url]) {
24
+ const key = Object.keys(config)
25
+ .find((it) => url.startsWith(it))
26
+ ?.sort(([aKey], [bKey]) => bKey.length - aKey.length)?.[0];
27
+
28
+ if (key) {
29
+ const value = config[key];
30
+ if (value) {
31
+ config[url] = config[key];
32
+ }
33
+ }
34
+ }
35
+
36
+ return config[url] ?? forRoot(externalConfig);
37
+ }
@@ -0,0 +1,114 @@
1
+ import { basename, dirname, join, relative } from "node:path";
2
+ import { fileURLToPath, pathToFileURL } from "node:url";
3
+
4
+ import { build } from "esbuild";
5
+ import glob from "fast-glob";
6
+
7
+ import { CONFIG_PARENT, CONFIG_ROOT } from "../server/symbols.mjs";
8
+ export * from "./context.mjs";
9
+ import { createHash } from "node:crypto";
10
+ import { readFile, stat } from "node:fs/promises";
11
+
12
+ import * as sys from "../lib/sys.mjs";
13
+ import merge from "../lib/utils/merge.mjs";
14
+
15
+ const cwd = sys.cwd();
16
+ const defaultConfig = {};
17
+
18
+ export async function loadConfig(initialConfig) {
19
+ const config = {};
20
+ const configFiles = (
21
+ await glob(
22
+ join(
23
+ cwd,
24
+ "**/{react-server,+*,vite}.config.{json,js,ts,mjs,mts,ts.mjs,mts.mjs}"
25
+ )
26
+ )
27
+ ).map((file) => relative(cwd, file));
28
+
29
+ for await (const file of configFiles) {
30
+ try {
31
+ const key = dirname(file);
32
+ const filename = basename(file);
33
+
34
+ let configModule;
35
+ const src = join(cwd, key, filename);
36
+ if (/\.m?ts$/.test(filename)) {
37
+ const hash = createHash("shake256", { outputLength: 4 })
38
+ .update(await readFile(src, "utf8"))
39
+ .digest("hex");
40
+ try {
41
+ await stat(
42
+ `${join(cwd, ".react-server", key, filename)}.${hash}.mjs`
43
+ );
44
+ } catch (e) {
45
+ await build({
46
+ absWorkingDir: filename.includes("vite.config")
47
+ ? join(fileURLToPath(import.meta.url), "../..")
48
+ : cwd,
49
+ entryPoints: [src],
50
+ outfile: `${join(cwd, ".react-server", key, filename)}.${hash}.mjs`,
51
+ bundle: true,
52
+ platform: "node",
53
+ format: "esm",
54
+ external: filename.includes("vite.config") ? ["*"] : [],
55
+ minify: true,
56
+ tsconfig: join(cwd, "tsconfig.json"),
57
+ });
58
+ }
59
+ configModule = (
60
+ await import(
61
+ pathToFileURL(
62
+ `${join(cwd, ".react-server", key, filename)}.${hash}.mjs`
63
+ )
64
+ )
65
+ ).default;
66
+ } else {
67
+ configModule = (
68
+ await import(
69
+ pathToFileURL(src),
70
+ filename.endsWith(".json")
71
+ ? { assert: { type: "json" } }
72
+ : undefined
73
+ )
74
+ ).default;
75
+ }
76
+
77
+ config[key] = merge(config[key] ?? {}, configModule);
78
+ } catch (e) {
79
+ console.error(e);
80
+ }
81
+ }
82
+
83
+ const configKeys = Object.keys(config);
84
+ const root = configKeys.includes(".")
85
+ ? "."
86
+ : configKeys.find((key) => configKeys.every((it) => it.startsWith(key)));
87
+ config[CONFIG_ROOT] = config[root] = merge(
88
+ {},
89
+ defaultConfig,
90
+ initialConfig,
91
+ { root },
92
+ config[root]
93
+ );
94
+
95
+ for (const key of configKeys) {
96
+ if (key === CONFIG_ROOT || key === root) continue;
97
+ merge(
98
+ config[key],
99
+ ...configKeys
100
+ .filter((it) => it !== key && key.startsWith(it))
101
+ .sort((a, b) => b.length - a.length)
102
+ .map((key, index, parentConfigArray) => ({
103
+ ...config[key],
104
+ [CONFIG_PARENT]: parentConfigArray[index - 1] ?? config[CONFIG_ROOT],
105
+ }))
106
+ );
107
+ }
108
+
109
+ return config;
110
+ }
111
+
112
+ export function defineConfig(config) {
113
+ return config;
114
+ }
@@ -0,0 +1,57 @@
1
+ import { join } from "node:path";
2
+
3
+ import { rimraf } from "rimraf";
4
+
5
+ import { loadConfig } from "../../config/index.mjs";
6
+ import { ContextStorage } from "../../server/context.mjs";
7
+ import { CONFIG_CONTEXT } from "../../server/symbols.mjs";
8
+ import { cwd, setEnv } from "../sys.mjs";
9
+ import clientBuild from "./client.mjs";
10
+ import serverBuild from "./server.mjs";
11
+ import staticSiteGenerator from "./static.mjs";
12
+
13
+ export default async function build(root, options) {
14
+ const config = await loadConfig();
15
+
16
+ // eslint-disable-next-line no-async-promise-executor
17
+ return new Promise(async (resolve) => {
18
+ ContextStorage.run(
19
+ {
20
+ [CONFIG_CONTEXT]: config,
21
+ },
22
+ async () => {
23
+ try {
24
+ if (!options.dev) {
25
+ // enforce production mode
26
+ setEnv("NODE_ENV", "production");
27
+ }
28
+ // empty out dir
29
+ if (options.server && options.client)
30
+ await rimraf(join(cwd(), ".react-server"));
31
+ else if (options.server)
32
+ await rimraf(join(cwd(), ".react-server/server"));
33
+ else if (options.client)
34
+ await rimraf(join(cwd(), ".react-server/client"));
35
+ // build server
36
+ if (options.server) {
37
+ await serverBuild(root, options);
38
+ // empty line
39
+ console.log();
40
+ }
41
+ // build client
42
+ if (options.client) {
43
+ await clientBuild(root, options);
44
+ }
45
+ // static export
46
+ if (options.export) {
47
+ await rimraf(join(cwd(), ".react-server/dist"));
48
+ await staticSiteGenerator(root, options);
49
+ }
50
+ } catch (e) {
51
+ console.error(e);
52
+ }
53
+ resolve();
54
+ }
55
+ );
56
+ });
57
+ }
@@ -0,0 +1,13 @@
1
+ import colors from "picocolors";
2
+
3
+ import packageJson from "../../package.json" assert { type: "json" };
4
+
5
+ export default function banner(target, dev) {
6
+ console.log(
7
+ `${colors.cyan(
8
+ `${packageJson.name.split("/").pop()}/${packageJson.version}`,
9
+ )} ${colors.green(
10
+ `building ${target} for ${dev ? "development" : "production"}`,
11
+ )}`,
12
+ );
13
+ }
@@ -0,0 +1,26 @@
1
+ import * as dependencies from "./dependencies.mjs";
2
+
3
+ export const serverChunks = {
4
+ react: [
5
+ dependencies.react,
6
+ dependencies.reactJsxRuntime,
7
+ dependencies.reactDomClient,
8
+ dependencies.reactDomServerEdge,
9
+ dependencies.reactServerDomWebpackClientBrowser,
10
+ dependencies.reactServerDomWebpackClientEdge,
11
+ dependencies.reactServerDomWebpackServerEdge,
12
+ dependencies.reactErrorBoundary,
13
+ dependencies.scheduler,
14
+ ],
15
+ };
16
+
17
+ export const clientChunks = {
18
+ react: [
19
+ dependencies.react,
20
+ dependencies.reactJsxRuntime,
21
+ dependencies.reactDomClient,
22
+ dependencies.reactServerDomWebpackClientBrowser,
23
+ dependencies.reactErrorBoundary,
24
+ dependencies.scheduler,
25
+ ],
26
+ };
@@ -0,0 +1,114 @@
1
+ import { createRequire } from "node:module";
2
+
3
+ import replace from "@rollup/plugin-replace";
4
+ import viteReact from "@vitejs/plugin-react";
5
+ import { build as viteBuild } from "vite";
6
+
7
+ import { forRoot } from "../../config/index.mjs";
8
+ import merge from "../../lib/utils/merge.mjs";
9
+ import packageJson from "../../package.json" assert { type: "json" };
10
+ import viteReactServer from "../plugins/react-server.mjs";
11
+ import rollupUseClient from "../plugins/use-client.mjs";
12
+ import * as sys from "../sys.mjs";
13
+ import banner from "./banner.mjs";
14
+ import { clientChunks } from "./chunks.mjs";
15
+ import customLogger from "./custom-logger.mjs";
16
+ import { clientAlias } from "./resolve.mjs";
17
+
18
+ const __require = createRequire(import.meta.url);
19
+ const cwd = sys.cwd();
20
+
21
+ export default async function clientBuild(_, options) {
22
+ banner("client", options.dev);
23
+ const config = forRoot();
24
+ const buildConfig = {
25
+ root: __require.resolve(`${packageJson.name}`),
26
+ resolve: {
27
+ alias: [...clientAlias(options.dev), ...(config.resolve?.alias ?? [])],
28
+ },
29
+ customLogger,
30
+ build: {
31
+ target: "esnext",
32
+ outDir: ".react-server",
33
+ emptyOutDir: false,
34
+ minify: options.minify,
35
+ manifest: "client/manifest.json",
36
+ sourcemap: options.sourcemap,
37
+ rollupOptions: {
38
+ preserveEntrySignatures: "allow-extension",
39
+ output: {
40
+ dir: ".react-server",
41
+ format: "esm",
42
+ entryFileNames: "[name].[hash].mjs",
43
+ chunkFileNames: "client/@lazarv/react-server/[name].[hash].mjs",
44
+ manualChunks: (id) => {
45
+ if (clientChunks["react"].includes(id)) return "react";
46
+ if (id.includes("@lazarv/react-server") && id.endsWith(".mjs")) {
47
+ return "react-server";
48
+ }
49
+ },
50
+ },
51
+ input: {
52
+ "client/index": __require.resolve(
53
+ "@lazarv/react-server/client/entry.client.jsx",
54
+ { paths: [cwd] }
55
+ ),
56
+ "client/@lazarv/react-server/client/ClientOnly": __require.resolve(
57
+ "@lazarv/react-server/client/ClientOnly.jsx",
58
+ { paths: [cwd] }
59
+ ),
60
+ "client/@lazarv/react-server/client/ErrorBoundary": __require.resolve(
61
+ "@lazarv/react-server/client/ErrorBoundary.jsx",
62
+ { paths: [cwd] }
63
+ ),
64
+ "client/@lazarv/react-server/client/Link": __require.resolve(
65
+ "@lazarv/react-server/client/Link.jsx",
66
+ { paths: [cwd] }
67
+ ),
68
+ "client/@lazarv/react-server/client/Refresh": __require.resolve(
69
+ "@lazarv/react-server/client/Refresh.jsx",
70
+ { paths: [cwd] }
71
+ ),
72
+ "client/@lazarv/react-server/client/ReactServerComponent":
73
+ __require.resolve(
74
+ "@lazarv/react-server/client/ReactServerComponent.jsx",
75
+ { paths: [cwd] }
76
+ ),
77
+ },
78
+ plugins: [
79
+ replace({
80
+ preventAssignment: true,
81
+ "process.env.NODE_ENV": JSON.stringify(
82
+ options.dev ? "development" : "production"
83
+ ),
84
+ }),
85
+ rollupUseClient("client"),
86
+ ],
87
+ },
88
+ },
89
+ plugins: [
90
+ viteReactServer("client"),
91
+ viteReact(),
92
+ ...(config.plugins ?? []),
93
+ ],
94
+ css: {
95
+ ...config.css,
96
+ postcss: process.cwd(),
97
+ },
98
+ };
99
+
100
+ let viteConfig = buildConfig;
101
+
102
+ if (typeof config.build?.client?.config === "function")
103
+ viteConfig = config.build?.client?.config(buildConfig);
104
+
105
+ if (typeof config.build?.client?.config === "object")
106
+ viteConfig = merge(buildConfig, config.build?.client?.config);
107
+
108
+ if (typeof config.vite === "function") viteConfig = config.vite(viteConfig);
109
+
110
+ if (typeof config.vite === "object")
111
+ viteConfig = merge(viteConfig, config.vite);
112
+
113
+ return viteBuild(viteConfig);
114
+ }