vite-plugin-react-server 0.3.0 → 0.3.3
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/README.md +73 -40
- package/dist/assertServerCondition.d.ts +2 -0
- package/dist/assertServerCondition.d.ts.map +1 -0
- package/dist/bin/patch.js +51 -0
- package/dist/bin/patch.js.map +1 -0
- package/dist/build/createBuildConfig.d.ts +7 -6
- package/dist/build/createBuildConfig.d.ts.map +1 -1
- package/dist/build/mergeInputs.d.ts +5 -0
- package/dist/build/mergeInputs.d.ts.map +1 -0
- package/dist/helpers/inputNormalizer.d.ts +6 -0
- package/dist/helpers/inputNormalizer.d.ts.map +1 -0
- package/dist/helpers/normalizedRelativePath.d.ts +3 -1
- package/dist/helpers/normalizedRelativePath.d.ts.map +1 -1
- package/dist/helpers/tryManifest.d.ts +10 -3
- package/dist/helpers/tryManifest.d.ts.map +1 -1
- package/dist/html/createPageLoader.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/options.d.ts +13 -8
- package/dist/options.d.ts.map +1 -1
- package/dist/plugin.d.ts +2 -7
- package/dist/plugin.d.ts.map +1 -1
- package/dist/react-client/plugin.js +1 -1
- package/dist/react-server/plugin.d.ts.map +1 -1
- package/dist/react-server/plugin.js +108 -61
- package/dist/react-server/plugin.js.map +1 -1
- package/dist/src/build/createBuildConfig.js +44 -0
- package/dist/src/build/createBuildConfig.js.map +1 -0
- package/dist/src/build/mergeInputs.js +16 -0
- package/dist/src/build/mergeInputs.js.map +1 -0
- package/dist/src/checkFilesExist.js.map +1 -0
- package/dist/src/collect-css-manifest.js.map +1 -0
- package/dist/src/components.js.map +1 -0
- package/dist/src/getEnv.js.map +1 -0
- package/dist/src/helpers/inputNormalizer.js +11 -0
- package/dist/src/helpers/inputNormalizer.js.map +1 -0
- package/dist/src/helpers/normalizedRelativePath.js +34 -0
- package/dist/src/helpers/normalizedRelativePath.js.map +1 -0
- package/dist/src/helpers/tryManifest.js +27 -0
- package/dist/src/helpers/tryManifest.js.map +1 -0
- package/dist/{html → src/html}/createPageLoader.js +3 -1
- package/dist/src/html/createPageLoader.js.map +1 -0
- package/dist/{options.js → src/options.js} +80 -24
- package/dist/src/options.js.map +1 -0
- package/dist/src/react-server/createHandler.js.map +1 -0
- package/dist/src/react-server/createRscStream.js.map +1 -0
- package/dist/src/resolvePage.js.map +1 -0
- package/dist/src/resolveProps.js.map +1 -0
- package/dist/src/worker/createHtmlStream.js +62 -0
- package/dist/src/worker/createHtmlStream.js.map +1 -0
- package/dist/{worker → src/worker}/createWorker.js +9 -8
- package/dist/src/worker/createWorker.js.map +1 -0
- package/dist/src/worker/renderPages.js.map +1 -0
- package/dist/types.d.ts +7 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/worker/createWorker.d.ts +8 -1
- package/dist/worker/createWorker.d.ts.map +1 -1
- package/dist/worker/loader.js +7 -0
- package/dist/worker/loader.js.map +1 -0
- package/dist/worker/worker.js +112 -0
- package/dist/worker/worker.js.map +1 -0
- package/package.json +108 -111
- package/patches/react-server-dom-esm+0.0.1.patch +14519 -0
- package/src/assertServerCondition.ts +13 -0
- package/src/build/createBuildConfig.ts +27 -44
- package/src/build/mergeInputs.ts +42 -0
- package/src/helpers/inputNormalizer.ts +22 -0
- package/src/helpers/normalizedRelativePath.ts +25 -25
- package/src/helpers/tryManifest.ts +19 -5
- package/src/html/createPageLoader.ts +2 -0
- package/src/options.ts +119 -47
- package/src/plugin.ts +4 -30
- package/src/react-server/createSsrHandler.ts +1 -1
- package/src/react-server/plugin.ts +116 -56
- package/src/types.ts +19 -1
- package/src/worker/createWorker.ts +12 -7
- package/tsconfig.json +2 -0
- package/dist/build/createBuildConfig.js +0 -55
- package/dist/build/createBuildConfig.js.map +0 -1
- package/dist/checkFilesExist.js.map +0 -1
- package/dist/collect-css-manifest.js.map +0 -1
- package/dist/components.js.map +0 -1
- package/dist/getEnv.js.map +0 -1
- package/dist/helpers/normalizedRelativePath.js +0 -31
- package/dist/helpers/normalizedRelativePath.js.map +0 -1
- package/dist/html/createPageLoader.js.map +0 -1
- package/dist/options.js.map +0 -1
- package/dist/plugin.js +0 -31
- package/dist/plugin.js.map +0 -1
- package/dist/react-server/createHandler.js.map +0 -1
- package/dist/react-server/createRscStream.js.map +0 -1
- package/dist/resolvePage.js.map +0 -1
- package/dist/resolveProps.js.map +0 -1
- package/dist/transformer/index.js +0 -54
- package/dist/transformer/index.js.map +0 -1
- package/dist/transformer/preserveDirectives.js +0 -72
- package/dist/transformer/preserveDirectives.js.map +0 -1
- package/dist/transformer/transformer.js +0 -80
- package/dist/transformer/transformer.js.map +0 -1
- package/dist/worker/createWorker.js.map +0 -1
- package/dist/worker/renderPages.js.map +0 -1
- /package/dist/{checkFilesExist.js → src/checkFilesExist.js} +0 -0
- /package/dist/{collect-css-manifest.js → src/collect-css-manifest.js} +0 -0
- /package/dist/{components.js → src/components.js} +0 -0
- /package/dist/{getEnv.js → src/getEnv.js} +0 -0
- /package/dist/{react-server → src/react-server}/createHandler.js +0 -0
- /package/dist/{react-server → src/react-server}/createRscStream.js +0 -0
- /package/dist/{resolvePage.js → src/resolvePage.js} +0 -0
- /package/dist/{resolveProps.js → src/resolveProps.js} +0 -0
- /package/dist/{worker → src/worker}/renderPages.js +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
function assertServerCondition<P extends typeof process>(p: P): asserts p is P & { env: { NODE_OPTIONS: string } } {
|
|
2
|
+
const nodeOptions = p.env['NODE_OPTIONS'];
|
|
3
|
+
if (!nodeOptions?.match(/--conditions[= ]react-server/)) {
|
|
4
|
+
if(!nodeOptions?.match(/--conditions/)) {
|
|
5
|
+
console.warn(`process.env['NODE_OPTIONS'] is missing \`--conditions\` flag, it should be like \`--conditions=react-server\` or \`--conditions react-server\`, but was ${JSON.stringify(process.env['NODE_OPTIONS'])}`);
|
|
6
|
+
}
|
|
7
|
+
if(!nodeOptions?.match(/react-server/)) {
|
|
8
|
+
throw new Error(`process.env['NODE_OPTIONS'] is missing \`react-server\` flag, it should be like \`--conditions=react-server\` or \`--conditions react-server\`, but was ${JSON.stringify(process.env['NODE_OPTIONS'])}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
};
|
|
13
|
+
assertServerCondition(process);
|
|
@@ -1,62 +1,43 @@
|
|
|
1
|
-
import { dirname, resolve } from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
1
|
import type { InlineConfig } from "vite";
|
|
4
|
-
import {
|
|
5
|
-
import type {
|
|
6
|
-
|
|
2
|
+
import type { ResolvedUserConfig, ResolvedUserOptions } from "../types.js";
|
|
3
|
+
import type { InputOption } from "rollup";
|
|
4
|
+
import { mergeInputs } from "./mergeInputs.js";
|
|
5
|
+
import { createInputNormalizer } from "../helpers/inputNormalizer.js";
|
|
7
6
|
|
|
8
7
|
type CreateBuildConfigOptions = {
|
|
8
|
+
input: InputOption;
|
|
9
|
+
userOptions: ResolvedUserOptions;
|
|
10
|
+
userConfig: ResolvedUserConfig;
|
|
9
11
|
root: string;
|
|
10
|
-
|
|
11
|
-
outDir: string;
|
|
12
|
-
entries: string[];
|
|
13
|
-
options?: StreamPluginOptions;
|
|
12
|
+
moduleBaseExceptions: string[];
|
|
14
13
|
};
|
|
15
14
|
|
|
15
|
+
|
|
16
16
|
export function createBuildConfig({
|
|
17
17
|
root,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
input,
|
|
19
|
+
userOptions,
|
|
20
|
+
userConfig,
|
|
21
|
+
moduleBaseExceptions
|
|
22
22
|
}: CreateBuildConfigOptions) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
entries.map((entry) => {
|
|
26
|
-
// Get the path relative to root
|
|
27
|
-
const relativePath = entry.replace(root + "/", "");
|
|
28
|
-
// Create a unique key based on the full path
|
|
29
|
-
const key = relativePath.replace(/\.[^/.]+$/, ""); // Remove extension
|
|
30
|
-
|
|
31
|
-
return [key, entry];
|
|
32
|
-
})
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
const workerPath = options?.workerPath
|
|
36
|
-
? resolve(root, options.workerPath)
|
|
37
|
-
: resolve(__dirname, "..", DEFAULT_CONFIG.WORKER_PATH);
|
|
23
|
+
const { output, input: inputConfig, ...restRollupOptions } =
|
|
24
|
+
userConfig.build.rollupOptions ?? {};
|
|
38
25
|
|
|
39
|
-
|
|
40
|
-
? resolve(root, options.loaderPath)
|
|
41
|
-
: resolve(__dirname, "..", DEFAULT_CONFIG.LOADER_PATH);
|
|
26
|
+
let mergedInputs = mergeInputs(input, inputConfig);
|
|
42
27
|
|
|
28
|
+
let inputNormalizer = createInputNormalizer({
|
|
29
|
+
root,
|
|
30
|
+
});
|
|
31
|
+
if(typeof mergedInputs === 'object' && mergedInputs != null) {
|
|
32
|
+
mergedInputs = Object.fromEntries(Object.entries(mergedInputs).map(inputNormalizer));
|
|
33
|
+
}
|
|
43
34
|
const config: InlineConfig = {
|
|
44
35
|
configFile: false,
|
|
45
|
-
|
|
46
|
-
base,
|
|
36
|
+
...userConfig,
|
|
47
37
|
build: {
|
|
48
|
-
|
|
49
|
-
ssr: true,
|
|
50
|
-
ssrEmitAssets: false,
|
|
51
|
-
manifest: true,
|
|
52
|
-
ssrManifest: true,
|
|
53
|
-
outDir,
|
|
38
|
+
...userConfig.build,
|
|
54
39
|
rollupOptions: {
|
|
55
|
-
input:
|
|
56
|
-
...entryInputs,
|
|
57
|
-
worker: workerPath,
|
|
58
|
-
loader: loaderPath,
|
|
59
|
-
},
|
|
40
|
+
input: mergedInputs,
|
|
60
41
|
output: {
|
|
61
42
|
format: "esm",
|
|
62
43
|
preserveModules: true,
|
|
@@ -65,7 +46,9 @@ export function createBuildConfig({
|
|
|
65
46
|
entryFileNames: "[name].js",
|
|
66
47
|
chunkFileNames: "[name].js",
|
|
67
48
|
assetFileNames: "[name][extname]",
|
|
49
|
+
...output,
|
|
68
50
|
},
|
|
51
|
+
...restRollupOptions,
|
|
69
52
|
},
|
|
70
53
|
},
|
|
71
54
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { InputOption } from "rollup";
|
|
2
|
+
|
|
3
|
+
export const mergeAsArray = (entries: InputOption) => {
|
|
4
|
+
return Array.isArray(entries)
|
|
5
|
+
? entries
|
|
6
|
+
: typeof entries === "object" && entries != null
|
|
7
|
+
? Object.values(entries)
|
|
8
|
+
: typeof entries === "string"
|
|
9
|
+
? [entries]
|
|
10
|
+
: [];
|
|
11
|
+
};
|
|
12
|
+
export const mergeAsObject = (entries: InputOption) => {
|
|
13
|
+
return Array.isArray(entries)
|
|
14
|
+
? Object.fromEntries(entries.map((entry) => [entry, entry]))
|
|
15
|
+
: typeof entries === "object" && entries != null
|
|
16
|
+
? entries
|
|
17
|
+
: typeof entries === "string"
|
|
18
|
+
? { [entries]: entries }
|
|
19
|
+
: {};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const mergeInputs = (
|
|
23
|
+
input: InputOption,
|
|
24
|
+
input2: InputOption | undefined
|
|
25
|
+
) => {
|
|
26
|
+
if (!input2) return input;
|
|
27
|
+
return Array.isArray(input)
|
|
28
|
+
? [...input, ...mergeAsArray(input2)]
|
|
29
|
+
: typeof input === "string"
|
|
30
|
+
? [input, ...mergeAsArray(input2)]
|
|
31
|
+
: input != null && typeof input2 === "object" && input2 != null
|
|
32
|
+
? { ...input, ...mergeAsObject(input2) }
|
|
33
|
+
: input != null
|
|
34
|
+
? input
|
|
35
|
+
: Array.isArray(input2)
|
|
36
|
+
? input2
|
|
37
|
+
: typeof input2 === "object" && input2 != null
|
|
38
|
+
? input2
|
|
39
|
+
: typeof input2 === "string"
|
|
40
|
+
? input2
|
|
41
|
+
: [];
|
|
42
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
|
|
3
|
+
type NormalizedInputOptions = {
|
|
4
|
+
// will automatically remove this part
|
|
5
|
+
root?: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const createInputNormalizer =
|
|
9
|
+
(
|
|
10
|
+
{
|
|
11
|
+
root = process.cwd(),
|
|
12
|
+
}: NormalizedInputOptions = {} as NormalizedInputOptions
|
|
13
|
+
) =>
|
|
14
|
+
([key, path]: [string, string]) =>
|
|
15
|
+
[
|
|
16
|
+
key,
|
|
17
|
+
path.startsWith(root)
|
|
18
|
+
? relative(root, path)
|
|
19
|
+
: path.startsWith("/")
|
|
20
|
+
? path
|
|
21
|
+
: `/${path}`,
|
|
22
|
+
];
|
|
@@ -4,56 +4,56 @@ type NormalizedRelativePathOptions = {
|
|
|
4
4
|
// will automatically remove this part
|
|
5
5
|
root: string;
|
|
6
6
|
// will automatically see this as a optional extra part of the rootDir that will be removed
|
|
7
|
-
outDir: string
|
|
7
|
+
outDir: string;
|
|
8
8
|
// will ensure it always starts with this path, if it does not it will be added
|
|
9
9
|
moduleBase: string;
|
|
10
10
|
// will ensure it never starts with a leading /, which in some cases is needed (vite entry), other cases it is not for example from project root /
|
|
11
11
|
noLeadingSlash: boolean;
|
|
12
|
+
// will ensure it never ends with a trailing /
|
|
13
|
+
noTrailingSlash: boolean;
|
|
14
|
+
// allowed exception to moduleBase rules
|
|
15
|
+
moduleBaseExceptions: string[];
|
|
12
16
|
};
|
|
13
17
|
|
|
14
18
|
export const createNormalizedRelativePath = (
|
|
15
19
|
options: NormalizedRelativePathOptions = {
|
|
16
20
|
root: process.cwd(),
|
|
17
|
-
outDir:
|
|
21
|
+
outDir: "dist",
|
|
18
22
|
moduleBase: "src",
|
|
19
23
|
noLeadingSlash: false,
|
|
24
|
+
noTrailingSlash: false,
|
|
25
|
+
moduleBaseExceptions: [],
|
|
20
26
|
}
|
|
21
27
|
) => {
|
|
22
|
-
|
|
28
|
+
let base =
|
|
23
29
|
options.noLeadingSlash && options.moduleBase.startsWith("/")
|
|
24
30
|
? options.moduleBase.slice(1)
|
|
25
31
|
: options.moduleBase;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
: (path: string) =>
|
|
34
|
-
(options.outDir as string) === path
|
|
35
|
-
? path.slice(options.outDir.length)
|
|
36
|
-
: path;
|
|
32
|
+
if (options.noTrailingSlash && base.endsWith("/")) {
|
|
33
|
+
base = base.slice(0, -1);
|
|
34
|
+
}
|
|
35
|
+
const removeOutDir = (path: string) =>
|
|
36
|
+
(options.outDir as string) === path
|
|
37
|
+
? path.slice(options.outDir.length)
|
|
38
|
+
: path;
|
|
37
39
|
|
|
38
40
|
const removeRoot = (path: string) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
: normalized;
|
|
41
|
+
const relative = path.startsWith(options.root)
|
|
42
|
+
? path.slice(options.root.length)
|
|
43
|
+
: path;
|
|
43
44
|
return relative;
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
const ensureModuleBase = (path: string) => {
|
|
48
|
+
let transformed = path;
|
|
47
49
|
if (options.noLeadingSlash && path.startsWith("/")) {
|
|
48
|
-
|
|
50
|
+
transformed = path.slice(1);
|
|
49
51
|
}
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
`Path ${path} does not start with module base ${base}, this will not work down the line.`
|
|
53
|
-
);
|
|
52
|
+
if (options.noTrailingSlash && transformed.endsWith("/")) {
|
|
53
|
+
transformed = transformed.slice(0, -1);
|
|
54
54
|
}
|
|
55
|
-
return
|
|
55
|
+
return transformed;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
return (path: string) => ensureModuleBase(removeOutDir(removeRoot(path)));
|
|
58
|
+
return (path: string) => ensureModuleBase(removeOutDir(removeRoot(normalizePath(path))));
|
|
59
59
|
};
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
+
import type { Manifest } from "vite";
|
|
3
4
|
|
|
4
|
-
type TryManifestOptions = {
|
|
5
|
+
type TryManifestOptions<SSR extends boolean> = {
|
|
5
6
|
root: string;
|
|
6
7
|
outDir: string;
|
|
7
|
-
ssrManifest:
|
|
8
|
+
ssrManifest: SSR;
|
|
8
9
|
};
|
|
9
10
|
|
|
10
|
-
export function tryManifest(options: TryManifestOptions) {
|
|
11
|
+
export function tryManifest<SSR extends boolean>(options: TryManifestOptions<SSR>): {
|
|
12
|
+
type: "success";
|
|
13
|
+
manifest: SSR extends true ? Record<string, string[]> : Manifest;
|
|
14
|
+
} | {
|
|
15
|
+
type: "error";
|
|
16
|
+
error: Error;
|
|
17
|
+
} {
|
|
11
18
|
const manifestPath = resolve(
|
|
12
19
|
options.root,
|
|
13
20
|
options.outDir,
|
|
@@ -15,9 +22,16 @@ export function tryManifest(options: TryManifestOptions) {
|
|
|
15
22
|
options.ssrManifest ? "ssr-manifest.json" : "manifest.json"
|
|
16
23
|
);
|
|
17
24
|
try {
|
|
18
|
-
|
|
25
|
+
const result= JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
26
|
+
return {
|
|
27
|
+
type: "success",
|
|
28
|
+
manifest: result,
|
|
29
|
+
}
|
|
19
30
|
} catch (e) {
|
|
20
31
|
console.log("No manifest found", manifestPath);
|
|
21
|
-
return
|
|
32
|
+
return {
|
|
33
|
+
type: "error",
|
|
34
|
+
error: e as Error,
|
|
35
|
+
}
|
|
22
36
|
}
|
|
23
37
|
}
|
package/src/options.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import type { ConfigEnv, ResolvedConfig, UserConfig } from "vite";
|
|
3
|
-
import type { ResolvedUserOptions, StreamPluginOptions } from "./types.js";
|
|
3
|
+
import type { ResolvedUserConfig, ResolvedUserOptions, StreamPluginOptions } from "./types.js";
|
|
4
|
+
import type { InputOption } from "rollup";
|
|
4
5
|
// Default configuration values
|
|
5
6
|
export const DEFAULT_CONFIG = {
|
|
6
7
|
FILE_REGEX: /\.(m|c)?(j|t)sx?$/,
|
|
@@ -14,9 +15,9 @@ export const DEFAULT_CONFIG = {
|
|
|
14
15
|
CLIENT_ENTRY: "/src/client.tsx",
|
|
15
16
|
PAGE_EXPORT: "Page",
|
|
16
17
|
PROPS_EXPORT: "props",
|
|
17
|
-
//
|
|
18
|
-
WORKER_PATH: "
|
|
19
|
-
LOADER_PATH: "
|
|
18
|
+
// Use package name paths instead of relative paths
|
|
19
|
+
WORKER_PATH: "vite-plugin-react-server/worker",
|
|
20
|
+
LOADER_PATH: "vite-plugin-react-server/loader",
|
|
20
21
|
RSC_EXTENSION: ".rsc",
|
|
21
22
|
HTML: ({ children }: { children: any }) => children,
|
|
22
23
|
COLLECT_CSS: true,
|
|
@@ -33,6 +34,10 @@ export const DEFAULT_CONFIG = {
|
|
|
33
34
|
client: "dist/client",
|
|
34
35
|
server: "dist/server",
|
|
35
36
|
},
|
|
37
|
+
AUTO_DISCOVER: {
|
|
38
|
+
pagePattern: "**/*.page.tsx",
|
|
39
|
+
propsPattern: "**/*.props.ts",
|
|
40
|
+
},
|
|
36
41
|
} as const;
|
|
37
42
|
|
|
38
43
|
export const resolveConfig = <T extends ResolvedConfig>(
|
|
@@ -51,7 +56,7 @@ export const resolveConfig = <T extends ResolvedConfig>(
|
|
|
51
56
|
|
|
52
57
|
export const resolveUserConfig = (
|
|
53
58
|
condition: "react-client" | "react-server",
|
|
54
|
-
input:
|
|
59
|
+
input: InputOption,
|
|
55
60
|
config: UserConfig,
|
|
56
61
|
configEnv: ConfigEnv,
|
|
57
62
|
userOptions: ResolvedUserOptions
|
|
@@ -59,8 +64,7 @@ export const resolveUserConfig = (
|
|
|
59
64
|
| { type: "error"; error: Error }
|
|
60
65
|
| {
|
|
61
66
|
type: "success";
|
|
62
|
-
userConfig:
|
|
63
|
-
Omit<UserConfig, "root" | "build" | "mode">;
|
|
67
|
+
userConfig: ResolvedUserConfig;
|
|
64
68
|
} => {
|
|
65
69
|
const isReactServer = condition === "react-server";
|
|
66
70
|
const isViteServer = configEnv.command === "serve";
|
|
@@ -74,14 +78,17 @@ export const resolveUserConfig = (
|
|
|
74
78
|
...config.build,
|
|
75
79
|
rollupOptions: {
|
|
76
80
|
...config.build?.rollupOptions,
|
|
77
|
-
input: input
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
+
input: input,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
if (
|
|
88
|
+
if (
|
|
89
|
+
typeof config.build?.assetsDir === "string" &&
|
|
90
|
+
userOptions.assetsDir !== config.build?.assetsDir
|
|
91
|
+
) {
|
|
85
92
|
return {
|
|
86
93
|
type: "error",
|
|
87
94
|
error: new Error(
|
|
@@ -111,7 +118,7 @@ export const resolveUserConfig = (
|
|
|
111
118
|
: "react-server condition was not set. Please use `NODE_OPTIONS='--conditions react-server' vite build --ssr`"
|
|
112
119
|
),
|
|
113
120
|
};
|
|
114
|
-
} else if (!configEnv.isSsrBuild && configEnv.command !==
|
|
121
|
+
} else if (!configEnv.isSsrBuild && configEnv.command !== "serve") {
|
|
115
122
|
return {
|
|
116
123
|
type: "error",
|
|
117
124
|
error: new Error(
|
|
@@ -122,7 +129,16 @@ export const resolveUserConfig = (
|
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
const { root: configRoot, mode: configMode, ...configRest } = config;
|
|
125
|
-
const {
|
|
132
|
+
const {
|
|
133
|
+
outDir: configOutDir,
|
|
134
|
+
assetsDir: configAssetsDir,
|
|
135
|
+
ssr: configSsr,
|
|
136
|
+
manifest: configManifest,
|
|
137
|
+
ssrManifest: configSsrManifest,
|
|
138
|
+
ssrEmitAssets: configSsrEmitAssets,
|
|
139
|
+
target: configTarget,
|
|
140
|
+
...configBuildRest
|
|
141
|
+
} = config.build ?? {};
|
|
126
142
|
|
|
127
143
|
return {
|
|
128
144
|
type: "success",
|
|
@@ -135,6 +151,7 @@ export const resolveUserConfig = (
|
|
|
135
151
|
ssr: configSsr ?? isReactServer,
|
|
136
152
|
manifest: configManifest ?? true,
|
|
137
153
|
ssrManifest: configSsrManifest ?? true,
|
|
154
|
+
ssrEmitAssets: configSsrEmitAssets ?? true,
|
|
138
155
|
target: configTarget ?? "es2020",
|
|
139
156
|
outDir:
|
|
140
157
|
typeof configOutDir === "string"
|
|
@@ -146,7 +163,7 @@ export const resolveUserConfig = (
|
|
|
146
163
|
typeof configAssetsDir === "string"
|
|
147
164
|
? configAssetsDir
|
|
148
165
|
: isReactServer
|
|
149
|
-
?
|
|
166
|
+
? ""
|
|
150
167
|
: DEFAULT_CONFIG.CLIENT_ASSETS_DIR,
|
|
151
168
|
},
|
|
152
169
|
},
|
|
@@ -156,37 +173,63 @@ export const resolveUserConfig = (
|
|
|
156
173
|
export const resolveOptions = (
|
|
157
174
|
options: StreamPluginOptions
|
|
158
175
|
):
|
|
159
|
-
| { type: "error"; error: Error }
|
|
160
176
|
| {
|
|
161
177
|
type: "success";
|
|
162
178
|
userOptions: ResolvedUserOptions;
|
|
179
|
+
}
|
|
180
|
+
| {
|
|
181
|
+
type: "error";
|
|
182
|
+
error: Error;
|
|
163
183
|
} => {
|
|
164
|
-
const
|
|
184
|
+
const {
|
|
185
|
+
workerPath: optionsWorkerPath,
|
|
186
|
+
loaderPath: optionsLoaderPath,
|
|
187
|
+
projectRoot: optionsProjectRoot,
|
|
188
|
+
moduleBase: optionsModuleBase,
|
|
189
|
+
moduleBasePath: optionsModuleBasePath,
|
|
190
|
+
moduleBaseURL: optionsModuleBaseURL,
|
|
191
|
+
build: optionsBuild,
|
|
192
|
+
Page: optionsPage,
|
|
193
|
+
props: optionsProps,
|
|
194
|
+
Html: optionsHtml,
|
|
195
|
+
pageExportName: optionsPageExportName,
|
|
196
|
+
propsExportName: optionsPropsExportName,
|
|
197
|
+
collectCss: optionsCollectCss,
|
|
198
|
+
collectAssets: optionsCollectAssets,
|
|
199
|
+
assetsDir: optionsAssetsDir,
|
|
200
|
+
clientEntry: optionsClientEntry,
|
|
201
|
+
serverOutDir: optionsServerOutDir,
|
|
202
|
+
clientOutDir: optionsClientOutDir,
|
|
203
|
+
autoDiscover: optionsAutoDiscover,
|
|
204
|
+
moduleBaseExceptions: optionsModuleBaseExceptions,
|
|
205
|
+
...restOptions
|
|
206
|
+
} = options;
|
|
207
|
+
const projectRoot = optionsProjectRoot ?? process.cwd();
|
|
165
208
|
/** the module base can be assumed to not have a leading slash */
|
|
166
209
|
const moduleBase =
|
|
167
|
-
typeof
|
|
168
|
-
?
|
|
169
|
-
?
|
|
170
|
-
:
|
|
210
|
+
typeof optionsModuleBase === "string"
|
|
211
|
+
? optionsModuleBase.startsWith(path.sep)
|
|
212
|
+
? optionsModuleBase.slice(path.sep.length)
|
|
213
|
+
: optionsModuleBase
|
|
171
214
|
: DEFAULT_CONFIG.MODULE_BASE;
|
|
172
215
|
|
|
173
216
|
if (
|
|
174
|
-
typeof
|
|
175
|
-
|
|
217
|
+
typeof optionsModuleBase === "string" &&
|
|
218
|
+
optionsModuleBase !== moduleBase
|
|
176
219
|
) {
|
|
177
220
|
return {
|
|
178
221
|
type: "error",
|
|
179
222
|
error: new Error(
|
|
180
|
-
`moduleBase ${
|
|
223
|
+
`moduleBase ${optionsModuleBase} is invalid, should be like ${moduleBase}`
|
|
181
224
|
),
|
|
182
225
|
};
|
|
183
226
|
}
|
|
184
227
|
|
|
185
228
|
const moduleBasePath =
|
|
186
|
-
typeof
|
|
187
|
-
? !
|
|
188
|
-
? `${path.sep}${
|
|
189
|
-
:
|
|
229
|
+
typeof optionsModuleBasePath === "string"
|
|
230
|
+
? !optionsModuleBasePath.startsWith(path.sep)
|
|
231
|
+
? `${path.sep}${optionsModuleBasePath}`
|
|
232
|
+
: optionsModuleBasePath
|
|
190
233
|
: `${path.sep}${moduleBase}`;
|
|
191
234
|
|
|
192
235
|
if (!moduleBasePath.includes(moduleBase)) {
|
|
@@ -199,10 +242,10 @@ export const resolveOptions = (
|
|
|
199
242
|
}
|
|
200
243
|
|
|
201
244
|
const moduleBaseURL =
|
|
202
|
-
typeof
|
|
203
|
-
? !
|
|
204
|
-
? path.join(
|
|
205
|
-
:
|
|
245
|
+
typeof optionsModuleBaseURL === "string"
|
|
246
|
+
? !optionsModuleBaseURL.endsWith(moduleBasePath)
|
|
247
|
+
? path.join(optionsModuleBaseURL, moduleBasePath)
|
|
248
|
+
: optionsModuleBaseURL
|
|
206
249
|
: moduleBasePath;
|
|
207
250
|
|
|
208
251
|
if (!moduleBaseURL.includes(moduleBasePath)) {
|
|
@@ -215,41 +258,70 @@ export const resolveOptions = (
|
|
|
215
258
|
}
|
|
216
259
|
|
|
217
260
|
if (
|
|
218
|
-
typeof
|
|
219
|
-
|
|
261
|
+
typeof optionsModuleBaseURL === "string" &&
|
|
262
|
+
optionsModuleBaseURL !== moduleBaseURL
|
|
220
263
|
) {
|
|
221
264
|
return {
|
|
222
265
|
type: "error",
|
|
223
266
|
error: new Error(
|
|
224
|
-
`moduleBaseURL ${
|
|
267
|
+
`moduleBaseURL ${optionsModuleBaseURL} is invalid, should be like ${moduleBaseURL}`
|
|
225
268
|
),
|
|
226
269
|
};
|
|
227
270
|
}
|
|
228
271
|
|
|
229
|
-
const build =
|
|
272
|
+
const build = optionsBuild
|
|
230
273
|
? {
|
|
231
|
-
client:
|
|
232
|
-
pages:
|
|
233
|
-
server:
|
|
274
|
+
client: optionsBuild.client ?? DEFAULT_CONFIG.BUILD.client,
|
|
275
|
+
pages: optionsBuild.pages ?? DEFAULT_CONFIG.BUILD.pages,
|
|
276
|
+
server: optionsBuild.server ?? DEFAULT_CONFIG.BUILD.server,
|
|
234
277
|
}
|
|
235
278
|
: DEFAULT_CONFIG.BUILD;
|
|
236
279
|
|
|
280
|
+
const autoDiscover =
|
|
281
|
+
typeof optionsAutoDiscover === "object"
|
|
282
|
+
? {
|
|
283
|
+
pagePattern:
|
|
284
|
+
typeof optionsAutoDiscover.pagePattern === "string"
|
|
285
|
+
? optionsAutoDiscover.pagePattern
|
|
286
|
+
: DEFAULT_CONFIG.AUTO_DISCOVER.pagePattern,
|
|
287
|
+
propsPattern:
|
|
288
|
+
typeof optionsAutoDiscover.propsPattern === "string"
|
|
289
|
+
? optionsAutoDiscover.propsPattern
|
|
290
|
+
: DEFAULT_CONFIG.AUTO_DISCOVER.propsPattern,
|
|
291
|
+
}
|
|
292
|
+
: DEFAULT_CONFIG.AUTO_DISCOVER;
|
|
293
|
+
|
|
294
|
+
const workerPath = typeof optionsWorkerPath === "string" ? optionsWorkerPath : DEFAULT_CONFIG.WORKER_PATH;
|
|
295
|
+
const loaderPath = typeof optionsLoaderPath === "string" ? optionsLoaderPath : DEFAULT_CONFIG.LOADER_PATH;
|
|
237
296
|
return {
|
|
238
297
|
type: "success",
|
|
239
298
|
userOptions: {
|
|
299
|
+
...DEFAULT_CONFIG,
|
|
300
|
+
...restOptions,
|
|
240
301
|
moduleBase,
|
|
241
302
|
moduleBasePath,
|
|
242
303
|
moduleBaseURL,
|
|
243
304
|
build,
|
|
244
|
-
Page:
|
|
245
|
-
props:
|
|
246
|
-
Html:
|
|
247
|
-
pageExportName:
|
|
248
|
-
propsExportName:
|
|
249
|
-
collectCss:
|
|
250
|
-
collectAssets:
|
|
305
|
+
Page: optionsPage ?? DEFAULT_CONFIG.PAGE,
|
|
306
|
+
props: optionsProps ?? DEFAULT_CONFIG.PROPS,
|
|
307
|
+
Html: optionsHtml ?? DEFAULT_CONFIG.HTML,
|
|
308
|
+
pageExportName: optionsPageExportName ?? DEFAULT_CONFIG.PAGE_EXPORT,
|
|
309
|
+
propsExportName: optionsPropsExportName ?? DEFAULT_CONFIG.PROPS_EXPORT,
|
|
310
|
+
collectCss: optionsCollectCss ?? DEFAULT_CONFIG.COLLECT_CSS,
|
|
311
|
+
collectAssets: optionsCollectAssets ?? DEFAULT_CONFIG.COLLECT_ASSETS,
|
|
251
312
|
projectRoot: projectRoot,
|
|
252
|
-
assetsDir:
|
|
313
|
+
assetsDir: optionsAssetsDir ?? DEFAULT_CONFIG.CLIENT_ASSETS_DIR,
|
|
314
|
+
workerPath: workerPath,
|
|
315
|
+
loaderPath: loaderPath,
|
|
316
|
+
clientEntry: optionsClientEntry ?? DEFAULT_CONFIG.CLIENT_ENTRY,
|
|
317
|
+
serverOutDir: optionsServerOutDir ?? DEFAULT_CONFIG.BUILD.server,
|
|
318
|
+
clientOutDir: optionsClientOutDir ?? DEFAULT_CONFIG.BUILD.client,
|
|
319
|
+
autoDiscover: autoDiscover,
|
|
320
|
+
moduleBaseExceptions: [
|
|
321
|
+
workerPath,
|
|
322
|
+
loaderPath,
|
|
323
|
+
...(optionsModuleBaseExceptions ?? []),
|
|
324
|
+
],
|
|
253
325
|
} satisfies ResolvedUserOptions,
|
|
254
326
|
};
|
|
255
327
|
};
|
package/src/plugin.ts
CHANGED
|
@@ -1,31 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { preserveDirectives } from "./transformer/preserveDirectives.js";
|
|
4
|
-
import type { StreamPluginOptions } from "./types.js";
|
|
1
|
+
import "./assertServerCondition.js";
|
|
2
|
+
export { reactStreamPlugin } from "./react-server/plugin.js";
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return nodeOptions?.match(/--conditions=react-server/) ? "server" : "client";
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const reactStreamPlugin = async (options: StreamPluginOptions) => {
|
|
12
|
-
const condition = getCondition();
|
|
13
|
-
try {
|
|
14
|
-
const resolvedOptions = resolveOptions(options);
|
|
15
|
-
if (resolvedOptions.type === "error") {
|
|
16
|
-
throw resolvedOptions.error;
|
|
17
|
-
}
|
|
18
|
-
options = resolvedOptions.userOptions;
|
|
19
|
-
} catch (error) {
|
|
20
|
-
throw new Error(
|
|
21
|
-
`[vite:react-stream:${condition}] ${(error as Error).message}`
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
return condition === "server"
|
|
25
|
-
? [
|
|
26
|
-
(await import(`./react-server/plugin.js`)).reactStreamPlugin(options),
|
|
27
|
-
viteReactClientTransformPlugin(),
|
|
28
|
-
preserveDirectives(),
|
|
29
|
-
]
|
|
30
|
-
: [(await import(`./react-client/plugin.js`)).reactStreamPlugin(options)];
|
|
31
|
-
};
|
|
4
|
+
// the main plugin is version is the server version, if you want the client version, use the `vite-plugin-react-server/client` import
|
|
5
|
+
// this is because the workflow assumes main thread = react server condition
|
|
@@ -30,7 +30,7 @@ export function createSsrHandler(
|
|
|
30
30
|
const worker = new Worker(
|
|
31
31
|
options?.workerPath
|
|
32
32
|
? resolve(server.config.root, options?.workerPath)
|
|
33
|
-
:
|
|
33
|
+
: DEFAULT_CONFIG.WORKER_PATH,
|
|
34
34
|
{
|
|
35
35
|
env: {
|
|
36
36
|
NODE_OPTIONS: "--conditions ''",
|