@ecopages/react 0.2.0-alpha.5 → 0.2.0-alpha.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/CHANGELOG.md +22 -41
- package/README.md +135 -29
- package/package.json +3 -3
- package/src/react-hmr-strategy.d.ts +22 -30
- package/src/react-hmr-strategy.js +57 -120
- package/src/react-hmr-strategy.ts +76 -145
- package/src/react-renderer.d.ts +130 -11
- package/src/react-renderer.js +368 -64
- package/src/react-renderer.ts +490 -90
- package/src/react.plugin.d.ts +17 -5
- package/src/react.plugin.js +44 -13
- package/src/react.plugin.ts +49 -14
- package/src/router-adapter.d.ts +2 -2
- package/src/router-adapter.ts +2 -2
- package/src/services/react-bundle.service.d.ts +2 -30
- package/src/services/react-bundle.service.js +19 -94
- package/src/services/react-bundle.service.ts +20 -129
- package/src/services/react-hydration-asset.service.js +3 -3
- package/src/services/react-hydration-asset.service.ts +7 -4
- package/src/services/react-page-module.service.d.ts +3 -0
- package/src/services/react-page-module.service.js +20 -16
- package/src/services/react-page-module.service.ts +27 -17
- package/src/services/react-runtime-bundle.service.d.ts +12 -12
- package/src/services/react-runtime-bundle.service.js +98 -180
- package/src/services/react-runtime-bundle.service.ts +112 -211
- package/src/utils/client-graph-boundary-plugin.js +78 -1
- package/src/utils/client-graph-boundary-plugin.ts +122 -1
- package/src/utils/hydration-scripts.d.ts +18 -1
- package/src/utils/hydration-scripts.js +83 -32
- package/src/utils/hydration-scripts.ts +159 -38
- package/src/utils/react-dom-runtime-interop-plugin.d.ts +5 -0
- package/src/utils/react-dom-runtime-interop-plugin.js +29 -0
- package/src/utils/react-dom-runtime-interop-plugin.ts +33 -0
- package/src/utils/react-mdx-loader-plugin.js +13 -5
- package/src/utils/react-mdx-loader-plugin.ts +28 -5
- package/src/utils/react-runtime-specifier-map.d.ts +6 -0
- package/src/utils/react-runtime-specifier-map.js +37 -0
- package/src/utils/react-runtime-specifier-map.ts +45 -0
- package/src/utils/use-sync-external-store-shim-plugin.d.ts +5 -0
- package/src/utils/use-sync-external-store-shim-plugin.js +41 -0
- package/src/utils/use-sync-external-store-shim-plugin.ts +45 -0
|
@@ -4,10 +4,10 @@ import { RESOLVED_ASSETS_DIR } from "@ecopages/core/constants";
|
|
|
4
4
|
import {
|
|
5
5
|
AssetFactory
|
|
6
6
|
} from "@ecopages/core/services/asset-processing-service";
|
|
7
|
-
import { createHydrationScript } from "../utils/hydration-scripts.js";
|
|
8
|
-
import { createIslandHydrationScript } from "../utils/hydration-scripts.js";
|
|
7
|
+
import { createHydrationScript, createIslandHydrationScript } from "../utils/hydration-scripts.js";
|
|
9
8
|
import { collectDeclaredModulesInConfig } from "../utils/declared-modules.js";
|
|
10
9
|
class ReactHydrationAssetService {
|
|
10
|
+
config;
|
|
11
11
|
constructor(config) {
|
|
12
12
|
this.config = config;
|
|
13
13
|
}
|
|
@@ -59,7 +59,7 @@ class ReactHydrationAssetService {
|
|
|
59
59
|
dependencies.push(
|
|
60
60
|
AssetFactory.createContentScript({
|
|
61
61
|
position: "head",
|
|
62
|
-
content: `window.
|
|
62
|
+
content: `window.__ECO_PAGES__=window.__ECO_PAGES__||{};window.__ECO_PAGES__.page={module:"${importPath}",props:${JSON.stringify(props)}};`,
|
|
63
63
|
name: `${componentName}-props`,
|
|
64
64
|
bundle: false,
|
|
65
65
|
attributes: {
|
|
@@ -18,8 +18,7 @@ import {
|
|
|
18
18
|
type ProcessedAsset,
|
|
19
19
|
} from '@ecopages/core/services/asset-processing-service';
|
|
20
20
|
import type { AssetProcessingService } from '@ecopages/core/services/asset-processing-service';
|
|
21
|
-
import { createHydrationScript } from '../utils/hydration-scripts.ts';
|
|
22
|
-
import { createIslandHydrationScript } from '../utils/hydration-scripts.ts';
|
|
21
|
+
import { createHydrationScript, createIslandHydrationScript } from '../utils/hydration-scripts.ts';
|
|
23
22
|
import { collectDeclaredModulesInConfig } from '../utils/declared-modules.ts';
|
|
24
23
|
import type { ReactBundleService } from './react-bundle.service.ts';
|
|
25
24
|
import type { ReactHmrPageMetadataCache } from './react-hmr-page-metadata-cache.ts';
|
|
@@ -40,7 +39,11 @@ export interface ReactHydrationAssetServiceConfig {
|
|
|
40
39
|
* Manages the creation of client-side hydration assets for React pages and component islands.
|
|
41
40
|
*/
|
|
42
41
|
export class ReactHydrationAssetService {
|
|
43
|
-
|
|
42
|
+
private readonly config: ReactHydrationAssetServiceConfig;
|
|
43
|
+
|
|
44
|
+
constructor(config: ReactHydrationAssetServiceConfig) {
|
|
45
|
+
this.config = config;
|
|
46
|
+
}
|
|
44
47
|
|
|
45
48
|
/**
|
|
46
49
|
* Resolves the import path for the bundled page component.
|
|
@@ -105,7 +108,7 @@ export class ReactHydrationAssetService {
|
|
|
105
108
|
dependencies.push(
|
|
106
109
|
AssetFactory.createContentScript({
|
|
107
110
|
position: 'head',
|
|
108
|
-
content: `window.
|
|
111
|
+
content: `window.__ECO_PAGES__=window.__ECO_PAGES__||{};window.__ECO_PAGES__.page={module:"${importPath}",props:${JSON.stringify(props)}};`,
|
|
109
112
|
name: `${componentName}-props`,
|
|
110
113
|
bundle: false,
|
|
111
114
|
attributes: {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
9
|
import type { EcoComponentConfig, EcoPageFile } from '@ecopages/core';
|
|
10
|
+
import type { BuildExecutor } from '@ecopages/core/build/build-adapter';
|
|
10
11
|
import type { CompileOptions } from '@mdx-js/mdx';
|
|
11
12
|
/**
|
|
12
13
|
* Configuration for the ReactPageModuleService.
|
|
@@ -14,6 +15,8 @@ import type { CompileOptions } from '@mdx-js/mdx';
|
|
|
14
15
|
export interface ReactPageModuleServiceConfig {
|
|
15
16
|
rootDir: string;
|
|
16
17
|
distDir: string;
|
|
18
|
+
workDir: string;
|
|
19
|
+
buildExecutor: BuildExecutor;
|
|
17
20
|
layoutsDir?: string;
|
|
18
21
|
componentsDir?: string;
|
|
19
22
|
mdxCompilerOptions?: CompileOptions;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { pathToFileURL } from "node:url";
|
|
3
3
|
import { rapidhash } from "@ecopages/core/hash";
|
|
4
|
-
import {
|
|
4
|
+
import { build } from "@ecopages/core/build/build-adapter";
|
|
5
5
|
import { fileSystem } from "@ecopages/file-system";
|
|
6
6
|
import { collectDeclaredModulesInConfig } from "../utils/declared-modules.js";
|
|
7
7
|
class ReactPageModuleService {
|
|
8
|
+
config;
|
|
8
9
|
constructor(config) {
|
|
9
10
|
this.config = config;
|
|
10
11
|
}
|
|
@@ -31,24 +32,27 @@ class ReactPageModuleService {
|
|
|
31
32
|
development: process?.env?.NODE_ENV === "development"
|
|
32
33
|
}
|
|
33
34
|
);
|
|
34
|
-
const outdir = path.join(this.config.
|
|
35
|
+
const outdir = path.join(this.config.workDir, ".server-modules-react-mdx");
|
|
35
36
|
const fileBaseName = path.basename(filePath, path.extname(filePath));
|
|
36
37
|
const fileHash = fileSystem.hash(filePath);
|
|
37
38
|
const cacheBuster = process?.env?.NODE_ENV === "development" ? `-${Date.now()}` : "";
|
|
38
39
|
const outputFileName = `${fileBaseName}-${fileHash}${cacheBuster}.js`;
|
|
39
|
-
const buildResult = await
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
40
|
+
const buildResult = await build(
|
|
41
|
+
{
|
|
42
|
+
entrypoints: [filePath],
|
|
43
|
+
root: this.config.rootDir,
|
|
44
|
+
outdir,
|
|
45
|
+
target: "node",
|
|
46
|
+
format: "esm",
|
|
47
|
+
sourcemap: "none",
|
|
48
|
+
splitting: false,
|
|
49
|
+
minify: false,
|
|
50
|
+
treeshaking: false,
|
|
51
|
+
naming: outputFileName,
|
|
52
|
+
plugins: [mdxPlugin]
|
|
53
|
+
},
|
|
54
|
+
this.config.buildExecutor
|
|
55
|
+
);
|
|
52
56
|
if (!buildResult.success) {
|
|
53
57
|
const details = buildResult.logs.map((log) => log.message).join(" | ");
|
|
54
58
|
throw new Error(`Failed to compile MDX page module: ${details}`);
|
|
@@ -91,7 +95,7 @@ class ReactPageModuleService {
|
|
|
91
95
|
if (fileSystem.exists(resolvedDependency)) {
|
|
92
96
|
return {
|
|
93
97
|
...config,
|
|
94
|
-
__eco: buildEcoMeta(
|
|
98
|
+
__eco: buildEcoMeta(path.join(candidateDir, path.basename(pagePath)))
|
|
95
99
|
};
|
|
96
100
|
}
|
|
97
101
|
}
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
import { pathToFileURL } from 'node:url';
|
|
12
12
|
import type { EcoComponentConfig, EcoPageFile } from '@ecopages/core';
|
|
13
|
+
import type { BuildExecutor } from '@ecopages/core/build/build-adapter';
|
|
13
14
|
import { rapidhash } from '@ecopages/core/hash';
|
|
14
|
-
import {
|
|
15
|
+
import { build } from '@ecopages/core/build/build-adapter';
|
|
15
16
|
import { fileSystem } from '@ecopages/file-system';
|
|
16
17
|
import type { CompileOptions } from '@mdx-js/mdx';
|
|
17
18
|
import { collectDeclaredModulesInConfig } from '../utils/declared-modules.ts';
|
|
@@ -22,6 +23,8 @@ import { collectDeclaredModulesInConfig } from '../utils/declared-modules.ts';
|
|
|
22
23
|
export interface ReactPageModuleServiceConfig {
|
|
23
24
|
rootDir: string;
|
|
24
25
|
distDir: string;
|
|
26
|
+
workDir: string;
|
|
27
|
+
buildExecutor: BuildExecutor;
|
|
25
28
|
layoutsDir?: string;
|
|
26
29
|
componentsDir?: string;
|
|
27
30
|
mdxCompilerOptions?: CompileOptions;
|
|
@@ -35,7 +38,11 @@ export interface ReactPageModuleServiceConfig {
|
|
|
35
38
|
* resolution, and hydration analysis for React pages.
|
|
36
39
|
*/
|
|
37
40
|
export class ReactPageModuleService {
|
|
38
|
-
|
|
41
|
+
private readonly config: ReactPageModuleServiceConfig;
|
|
42
|
+
|
|
43
|
+
constructor(config: ReactPageModuleServiceConfig) {
|
|
44
|
+
this.config = config;
|
|
45
|
+
}
|
|
39
46
|
|
|
40
47
|
/**
|
|
41
48
|
* Checks if the given file path corresponds to an MDX file based on configured extensions.
|
|
@@ -62,25 +69,28 @@ export class ReactPageModuleService {
|
|
|
62
69
|
},
|
|
63
70
|
);
|
|
64
71
|
|
|
65
|
-
const outdir = path.join(this.config.
|
|
72
|
+
const outdir = path.join(this.config.workDir, '.server-modules-react-mdx');
|
|
66
73
|
const fileBaseName = path.basename(filePath, path.extname(filePath));
|
|
67
74
|
const fileHash = fileSystem.hash(filePath);
|
|
68
75
|
const cacheBuster = process?.env?.NODE_ENV === 'development' ? `-${Date.now()}` : '';
|
|
69
76
|
const outputFileName = `${fileBaseName}-${fileHash}${cacheBuster}.js`;
|
|
70
77
|
|
|
71
|
-
const buildResult = await
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
const buildResult = await build(
|
|
79
|
+
{
|
|
80
|
+
entrypoints: [filePath],
|
|
81
|
+
root: this.config.rootDir,
|
|
82
|
+
outdir,
|
|
83
|
+
target: 'node',
|
|
84
|
+
format: 'esm',
|
|
85
|
+
sourcemap: 'none',
|
|
86
|
+
splitting: false,
|
|
87
|
+
minify: false,
|
|
88
|
+
treeshaking: false,
|
|
89
|
+
naming: outputFileName,
|
|
90
|
+
plugins: [mdxPlugin],
|
|
91
|
+
},
|
|
92
|
+
this.config.buildExecutor,
|
|
93
|
+
);
|
|
84
94
|
|
|
85
95
|
if (!buildResult.success) {
|
|
86
96
|
const details = buildResult.logs.map((log) => log.message).join(' | ');
|
|
@@ -138,7 +148,7 @@ export class ReactPageModuleService {
|
|
|
138
148
|
if (fileSystem.exists(resolvedDependency)) {
|
|
139
149
|
return {
|
|
140
150
|
...config,
|
|
141
|
-
__eco: buildEcoMeta(
|
|
151
|
+
__eco: buildEcoMeta(path.join(candidateDir, path.basename(pagePath))),
|
|
142
152
|
};
|
|
143
153
|
}
|
|
144
154
|
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* Runtime bundle service for React integration.
|
|
3
3
|
*
|
|
4
4
|
* Owns creation of the browser runtime assets for React and React DOM,
|
|
5
|
-
* including
|
|
6
|
-
* interop rewriting.
|
|
5
|
+
* including shared runtime entry generation and specifier mapping.
|
|
7
6
|
*
|
|
8
7
|
* @module
|
|
9
8
|
*/
|
|
@@ -21,18 +20,19 @@ export type ReactRuntimeImports = {
|
|
|
21
20
|
export interface ReactRuntimeBundleServiceConfig {
|
|
22
21
|
routerAdapter?: ReactRouterAdapter;
|
|
23
22
|
}
|
|
23
|
+
type RuntimeMode = 'development' | 'production';
|
|
24
24
|
export declare class ReactRuntimeBundleService {
|
|
25
25
|
private readonly config;
|
|
26
26
|
constructor(config: ReactRuntimeBundleServiceConfig);
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
private get isDevelopment();
|
|
28
|
+
private getCurrentRuntimeMode;
|
|
29
|
+
private createRuntimeDefines;
|
|
30
|
+
private getReactVendorFileName;
|
|
31
|
+
private getReactDomVendorFileName;
|
|
32
|
+
private getRouterVendorFileName;
|
|
33
|
+
getRuntimeImports(mode?: RuntimeMode): ReactRuntimeImports;
|
|
34
|
+
getSpecifierMap(mode?: RuntimeMode): Record<string, string>;
|
|
29
35
|
getDependencies(): AssetDefinition[];
|
|
30
|
-
createRuntimeAliasPlugin(): EcoBuildPlugin;
|
|
31
|
-
private buildImportMapSourceUrl;
|
|
32
|
-
private createRuntimeSpecifierAliasPlugin;
|
|
33
|
-
private createReactDomRuntimeInteropPlugin;
|
|
34
|
-
private getRuntimeArtifactsDir;
|
|
35
|
-
private createRuntimeEntry;
|
|
36
|
-
private getModuleExportNames;
|
|
37
|
-
private isValidExportName;
|
|
36
|
+
createRuntimeAliasPlugin(mode?: RuntimeMode): EcoBuildPlugin;
|
|
38
37
|
}
|
|
38
|
+
export {};
|
|
@@ -1,205 +1,123 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { createRuntimeSpecifierAliasPlugin } from "@ecopages/core/build/runtime-specifier-alias-plugin";
|
|
2
|
+
import {
|
|
3
|
+
buildBrowserRuntimeAssetUrl,
|
|
4
|
+
createBrowserRuntimeModuleAsset,
|
|
5
|
+
createBrowserRuntimeScriptAsset
|
|
6
|
+
} from "@ecopages/core/services/asset-processing-service";
|
|
7
|
+
import { createReactDomRuntimeInteropPlugin } from "../utils/react-dom-runtime-interop-plugin.js";
|
|
8
|
+
import { buildReactRuntimeSpecifierMap } from "../utils/react-runtime-specifier-map.js";
|
|
5
9
|
class ReactRuntimeBundleService {
|
|
10
|
+
config;
|
|
6
11
|
constructor(config) {
|
|
7
12
|
this.config = config;
|
|
8
13
|
}
|
|
9
|
-
|
|
14
|
+
get isDevelopment() {
|
|
15
|
+
return process.env.NODE_ENV === "development";
|
|
16
|
+
}
|
|
17
|
+
getCurrentRuntimeMode() {
|
|
18
|
+
return this.isDevelopment ? "development" : "production";
|
|
19
|
+
}
|
|
20
|
+
createRuntimeDefines(mode) {
|
|
21
|
+
const nodeEnv = JSON.stringify(mode);
|
|
22
|
+
return {
|
|
23
|
+
"process.env.NODE_ENV": nodeEnv,
|
|
24
|
+
"import.meta.env.NODE_ENV": nodeEnv
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
getReactVendorFileName(mode) {
|
|
28
|
+
return mode === "development" ? "react.development.js" : "react.js";
|
|
29
|
+
}
|
|
30
|
+
getReactDomVendorFileName(mode) {
|
|
31
|
+
return mode === "development" ? "react-dom.development.js" : "react-dom.js";
|
|
32
|
+
}
|
|
33
|
+
getRouterVendorFileName(mode) {
|
|
34
|
+
if (!this.config.routerAdapter) {
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
return mode === "development" ? `${this.config.routerAdapter.bundle.outputName}.development.js` : `${this.config.routerAdapter.bundle.outputName}.js`;
|
|
38
|
+
}
|
|
39
|
+
getRuntimeImports(mode = this.getCurrentRuntimeMode()) {
|
|
40
|
+
const reactVendorFileName = this.getReactVendorFileName(mode);
|
|
41
|
+
const reactDomVendorFileName = this.getReactDomVendorFileName(mode);
|
|
10
42
|
const runtimeImports = {
|
|
11
|
-
react:
|
|
12
|
-
reactDomClient:
|
|
13
|
-
reactJsxRuntime:
|
|
14
|
-
reactJsxDevRuntime:
|
|
15
|
-
reactDom:
|
|
43
|
+
react: buildBrowserRuntimeAssetUrl(reactVendorFileName),
|
|
44
|
+
reactDomClient: buildBrowserRuntimeAssetUrl(reactDomVendorFileName),
|
|
45
|
+
reactJsxRuntime: buildBrowserRuntimeAssetUrl(reactVendorFileName),
|
|
46
|
+
reactJsxDevRuntime: buildBrowserRuntimeAssetUrl(reactVendorFileName),
|
|
47
|
+
reactDom: buildBrowserRuntimeAssetUrl(reactDomVendorFileName)
|
|
16
48
|
};
|
|
17
49
|
if (this.config.routerAdapter) {
|
|
18
|
-
runtimeImports.router = this.
|
|
50
|
+
runtimeImports.router = buildBrowserRuntimeAssetUrl(this.getRouterVendorFileName(mode));
|
|
19
51
|
}
|
|
20
52
|
return runtimeImports;
|
|
21
53
|
}
|
|
22
|
-
getSpecifierMap() {
|
|
23
|
-
|
|
24
|
-
const map = {
|
|
25
|
-
react: runtimeImports.react,
|
|
26
|
-
"react/jsx-runtime": runtimeImports.reactJsxRuntime,
|
|
27
|
-
"react/jsx-dev-runtime": runtimeImports.reactJsxDevRuntime,
|
|
28
|
-
"react-dom": runtimeImports.reactDom,
|
|
29
|
-
"react-dom/client": runtimeImports.reactDomClient
|
|
30
|
-
};
|
|
31
|
-
if (this.config.routerAdapter && runtimeImports.router) {
|
|
32
|
-
map[this.config.routerAdapter.importMapKey] = runtimeImports.router;
|
|
33
|
-
}
|
|
34
|
-
return map;
|
|
54
|
+
getSpecifierMap(mode = this.getCurrentRuntimeMode()) {
|
|
55
|
+
return buildReactRuntimeSpecifierMap(this.getRuntimeImports(mode), this.config.routerAdapter);
|
|
35
56
|
}
|
|
36
57
|
getDependencies() {
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const reactEntry = this.createRuntimeEntry(
|
|
44
|
-
[
|
|
45
|
-
{ specifier: "react", defaultExport: true },
|
|
46
|
-
{ specifier: "react/jsx-runtime" },
|
|
47
|
-
{ specifier: "react/jsx-dev-runtime" }
|
|
48
|
-
],
|
|
49
|
-
"react-entry.mjs"
|
|
50
|
-
);
|
|
51
|
-
const reactDomEntry = this.createRuntimeEntry(
|
|
52
|
-
[{ specifier: "react-dom", defaultExport: true }, { specifier: "react-dom/client" }],
|
|
53
|
-
"react-dom-entry.mjs"
|
|
54
|
-
);
|
|
55
|
-
const dependencies = [
|
|
56
|
-
AssetFactory.createNodeModuleScript({
|
|
57
|
-
position: "head",
|
|
58
|
-
importPath: reactEntry,
|
|
59
|
-
name: "react",
|
|
60
|
-
excludeFromHtml: true,
|
|
61
|
-
bundleOptions: { naming: "react.js" },
|
|
62
|
-
attributes: runtimeAttrs
|
|
63
|
-
}),
|
|
64
|
-
AssetFactory.createNodeModuleScript({
|
|
65
|
-
position: "head",
|
|
66
|
-
importPath: reactDomEntry,
|
|
67
|
-
name: "react-dom",
|
|
68
|
-
excludeFromHtml: true,
|
|
69
|
-
bundleOptions: {
|
|
70
|
-
naming: "react-dom.js",
|
|
71
|
-
plugins: [reactRuntimeAliasPlugin, reactDomRuntimeInteropPlugin]
|
|
58
|
+
const reactDomRuntimeInteropPlugin = createReactDomRuntimeInteropPlugin();
|
|
59
|
+
const dependencies = [];
|
|
60
|
+
for (const mode of ["production", "development"]) {
|
|
61
|
+
const reactRuntimeAliasPlugin = createRuntimeSpecifierAliasPlugin(
|
|
62
|
+
{
|
|
63
|
+
react: buildBrowserRuntimeAssetUrl(this.getReactVendorFileName(mode))
|
|
72
64
|
},
|
|
73
|
-
|
|
74
|
-
})
|
|
75
|
-
];
|
|
76
|
-
if (this.config.routerAdapter) {
|
|
77
|
-
const runtimeAliasPlugin = this.createRuntimeAliasPlugin();
|
|
78
|
-
const mappedSpecifiers = new Set(Object.keys(this.getSpecifierMap()));
|
|
79
|
-
const unresolvedExternals = this.config.routerAdapter.bundle.externals.filter(
|
|
80
|
-
(external) => !mappedSpecifiers.has(external)
|
|
65
|
+
{ name: `react-plugin-runtime-specifier-alias-${mode}` }
|
|
81
66
|
);
|
|
67
|
+
const reactDomBundlePlugins = [reactRuntimeAliasPlugin, reactDomRuntimeInteropPlugin].filter(
|
|
68
|
+
(plugin) => plugin !== null
|
|
69
|
+
);
|
|
70
|
+
const runtimeAliasPlugin = this.createRuntimeAliasPlugin(mode);
|
|
71
|
+
const mappedSpecifiers = new Set(Object.keys(this.getSpecifierMap(mode)));
|
|
82
72
|
dependencies.push(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
73
|
+
createBrowserRuntimeModuleAsset({
|
|
74
|
+
modules: [
|
|
75
|
+
{ specifier: "react", defaultExport: true },
|
|
76
|
+
{ specifier: "react/jsx-runtime" },
|
|
77
|
+
{ specifier: "react/jsx-dev-runtime" }
|
|
78
|
+
],
|
|
79
|
+
name: "react",
|
|
80
|
+
fileName: this.getReactVendorFileName(mode),
|
|
81
|
+
cacheDirName: `ecopages-react-runtime-${mode}`,
|
|
88
82
|
bundleOptions: {
|
|
89
|
-
|
|
90
|
-
external: unresolvedExternals,
|
|
91
|
-
plugins: [runtimeAliasPlugin]
|
|
92
|
-
},
|
|
93
|
-
attributes: runtimeAttrs
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
return dependencies;
|
|
98
|
-
}
|
|
99
|
-
createRuntimeAliasPlugin() {
|
|
100
|
-
const specifierMap = this.getSpecifierMap();
|
|
101
|
-
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
102
|
-
const filter = new RegExp(
|
|
103
|
-
`^(${Object.keys(specifierMap).map((key) => escapeRegExp(key)).join("|")})$`
|
|
104
|
-
);
|
|
105
|
-
return {
|
|
106
|
-
name: "react-plugin-runtime-alias",
|
|
107
|
-
setup(build) {
|
|
108
|
-
build.onResolve({ filter }, (args) => {
|
|
109
|
-
const mappedPath = specifierMap[args.path];
|
|
110
|
-
if (!mappedPath) {
|
|
111
|
-
return void 0;
|
|
83
|
+
define: this.createRuntimeDefines(mode)
|
|
112
84
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return `/${AssetFactory.RESOLVED_ASSETS_VENDORS_DIR}/${fileName}`;
|
|
123
|
-
}
|
|
124
|
-
createRuntimeSpecifierAliasPlugin(specifierMap, external = true) {
|
|
125
|
-
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
126
|
-
const filter = new RegExp(
|
|
127
|
-
`^(${Object.keys(specifierMap).map((key) => escapeRegExp(key)).join("|")})$`
|
|
128
|
-
);
|
|
129
|
-
return {
|
|
130
|
-
name: "react-plugin-runtime-specifier-alias",
|
|
131
|
-
setup(build) {
|
|
132
|
-
build.onResolve({ filter }, (args) => {
|
|
133
|
-
const mappedPath = specifierMap[args.path];
|
|
134
|
-
if (!mappedPath) {
|
|
135
|
-
return void 0;
|
|
136
|
-
}
|
|
137
|
-
return {
|
|
138
|
-
path: mappedPath,
|
|
139
|
-
external
|
|
140
|
-
};
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
createReactDomRuntimeInteropPlugin() {
|
|
146
|
-
const reactDomFileFilter = /[\\/]react-dom[\\/].*\.js$/;
|
|
147
|
-
const reactRequirePattern = /\brequire\((['"])react\1\)/g;
|
|
148
|
-
return {
|
|
149
|
-
name: "react-dom-runtime-interop",
|
|
150
|
-
setup(build) {
|
|
151
|
-
build.onLoad({ filter: reactDomFileFilter }, (args) => {
|
|
152
|
-
const content = fs.readFileSync(args.path, "utf-8");
|
|
153
|
-
if (!reactRequirePattern.test(content)) {
|
|
154
|
-
return void 0;
|
|
85
|
+
}),
|
|
86
|
+
createBrowserRuntimeModuleAsset({
|
|
87
|
+
modules: [{ specifier: "react-dom", defaultExport: true }, { specifier: "react-dom/client" }],
|
|
88
|
+
name: "react-dom",
|
|
89
|
+
fileName: this.getReactDomVendorFileName(mode),
|
|
90
|
+
cacheDirName: `ecopages-react-runtime-${mode}`,
|
|
91
|
+
bundleOptions: {
|
|
92
|
+
define: this.createRuntimeDefines(mode),
|
|
93
|
+
plugins: reactDomBundlePlugins
|
|
155
94
|
}
|
|
156
|
-
|
|
157
|
-
const rewritten = content.replace(reactRequirePattern, "__ecopages_react_runtime");
|
|
158
|
-
return {
|
|
159
|
-
contents: `import * as __ecopages_react_runtime from 'react';
|
|
160
|
-
${rewritten}`,
|
|
161
|
-
loader: "js",
|
|
162
|
-
resolveDir: path.dirname(args.path)
|
|
163
|
-
};
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
getRuntimeArtifactsDir() {
|
|
169
|
-
const tmpDir = path.join(process.cwd(), "node_modules", ".cache", "ecopages-react-runtime");
|
|
170
|
-
fs.mkdirSync(tmpDir, { recursive: true });
|
|
171
|
-
return tmpDir;
|
|
172
|
-
}
|
|
173
|
-
createRuntimeEntry(modules, fileName) {
|
|
174
|
-
const tmpDir = this.getRuntimeArtifactsDir();
|
|
175
|
-
const requireFromRoot = createRequire(path.join(process.cwd(), "package.json"));
|
|
176
|
-
const seenExports = /* @__PURE__ */ new Set();
|
|
177
|
-
const statements = [];
|
|
178
|
-
for (const module of modules) {
|
|
179
|
-
if (module.defaultExport) {
|
|
180
|
-
statements.push(`import __ecopages_default_export__ from '${module.specifier}';`);
|
|
181
|
-
statements.push("export default __ecopages_default_export__;");
|
|
182
|
-
}
|
|
183
|
-
const exportNames = this.getModuleExportNames(module.specifier, requireFromRoot).filter(
|
|
184
|
-
(name) => !seenExports.has(name)
|
|
95
|
+
})
|
|
185
96
|
);
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
97
|
+
if (this.config.routerAdapter) {
|
|
98
|
+
const unresolvedExternals = this.config.routerAdapter.bundle.externals.filter(
|
|
99
|
+
(external) => !mappedSpecifiers.has(external)
|
|
100
|
+
);
|
|
101
|
+
dependencies.push(
|
|
102
|
+
createBrowserRuntimeScriptAsset({
|
|
103
|
+
importPath: this.config.routerAdapter.bundle.importPath,
|
|
104
|
+
name: this.config.routerAdapter.bundle.outputName,
|
|
105
|
+
fileName: this.getRouterVendorFileName(mode),
|
|
106
|
+
bundleOptions: {
|
|
107
|
+
define: this.createRuntimeDefines(mode),
|
|
108
|
+
external: unresolvedExternals,
|
|
109
|
+
plugins: [runtimeAliasPlugin]
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
);
|
|
191
113
|
}
|
|
192
114
|
}
|
|
193
|
-
|
|
194
|
-
fs.writeFileSync(filePath, statements.join("\n"), "utf-8");
|
|
195
|
-
return filePath;
|
|
196
|
-
}
|
|
197
|
-
getModuleExportNames(specifier, requireFromRoot) {
|
|
198
|
-
const moduleExports = requireFromRoot(specifier);
|
|
199
|
-
return Object.keys(moduleExports).filter((name) => name !== "__esModule" && name !== "default").filter((name) => this.isValidExportName(name)).sort();
|
|
115
|
+
return dependencies;
|
|
200
116
|
}
|
|
201
|
-
|
|
202
|
-
return
|
|
117
|
+
createRuntimeAliasPlugin(mode = this.getCurrentRuntimeMode()) {
|
|
118
|
+
return createRuntimeSpecifierAliasPlugin(this.getSpecifierMap(mode), {
|
|
119
|
+
name: `react-plugin-runtime-alias-${mode}`
|
|
120
|
+
});
|
|
203
121
|
}
|
|
204
122
|
}
|
|
205
123
|
export {
|