@ecopages/react 0.2.0-alpha.1 → 0.2.0-alpha.11

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 (50) hide show
  1. package/CHANGELOG.md +9 -43
  2. package/README.md +143 -17
  3. package/package.json +3 -3
  4. package/src/react-hmr-strategy.d.ts +25 -21
  5. package/src/react-hmr-strategy.js +78 -110
  6. package/src/react-renderer.d.ts +135 -12
  7. package/src/react-renderer.js +439 -82
  8. package/src/react.plugin.d.ts +17 -5
  9. package/src/react.plugin.js +45 -13
  10. package/src/router-adapter.d.ts +2 -2
  11. package/src/services/react-bundle.service.d.ts +4 -25
  12. package/src/services/react-bundle.service.js +37 -91
  13. package/src/services/react-hydration-asset.service.js +3 -3
  14. package/src/services/react-page-module.service.d.ts +3 -0
  15. package/src/services/react-page-module.service.js +24 -17
  16. package/src/services/react-runtime-bundle.service.d.ts +12 -12
  17. package/src/services/react-runtime-bundle.service.js +98 -180
  18. package/src/utils/client-graph-boundary-plugin.js +149 -11
  19. package/src/utils/declared-modules.js +4 -1
  20. package/src/utils/foreign-jsx-override-plugin.d.ts +19 -0
  21. package/src/utils/foreign-jsx-override-plugin.js +43 -0
  22. package/src/utils/hydration-scripts.d.ts +18 -1
  23. package/src/utils/hydration-scripts.js +95 -37
  24. package/src/utils/reachability-analyzer.d.ts +12 -1
  25. package/src/utils/reachability-analyzer.js +101 -5
  26. package/src/utils/react-dom-runtime-interop-plugin.d.ts +5 -0
  27. package/src/utils/react-dom-runtime-interop-plugin.js +29 -0
  28. package/src/utils/react-mdx-loader-plugin.js +13 -5
  29. package/src/utils/react-runtime-specifier-map.d.ts +6 -0
  30. package/src/utils/react-runtime-specifier-map.js +37 -0
  31. package/src/utils/use-sync-external-store-shim-plugin.d.ts +5 -0
  32. package/src/utils/use-sync-external-store-shim-plugin.js +41 -0
  33. package/src/react-hmr-strategy.ts +0 -444
  34. package/src/react-renderer.ts +0 -403
  35. package/src/react.plugin.ts +0 -241
  36. package/src/router-adapter.ts +0 -95
  37. package/src/services/react-bundle.service.ts +0 -212
  38. package/src/services/react-hmr-page-metadata-cache.ts +0 -24
  39. package/src/services/react-hydration-asset.service.ts +0 -260
  40. package/src/services/react-page-module.service.ts +0 -214
  41. package/src/services/react-runtime-bundle.service.ts +0 -271
  42. package/src/utils/client-graph-boundary-plugin.ts +0 -590
  43. package/src/utils/client-only.ts +0 -27
  44. package/src/utils/declared-modules.ts +0 -99
  45. package/src/utils/dynamic.ts +0 -27
  46. package/src/utils/hmr-scripts.ts +0 -47
  47. package/src/utils/html-boundary.ts +0 -66
  48. package/src/utils/hydration-scripts.ts +0 -338
  49. package/src/utils/reachability-analyzer.ts +0 -440
  50. package/src/utils/react-mdx-loader-plugin.ts +0 -40
@@ -5,7 +5,6 @@
5
5
  import { IntegrationPlugin } from '@ecopages/core/plugins/integration-plugin';
6
6
  import type { EcoBuildPlugin } from '@ecopages/core/build/build-types';
7
7
  import type { HmrStrategy } from '@ecopages/core/hmr/hmr-strategy';
8
- import type { IHmrManager } from '@ecopages/core/internal-types';
9
8
  import type { AssetDefinition } from '@ecopages/core/services/asset-processing-service';
10
9
  import type { CompileOptions } from '@mdx-js/mdx';
11
10
  import type React from 'react';
@@ -106,12 +105,28 @@ export declare class ReactPlugin extends IntegrationPlugin<React.JSX.Element> {
106
105
  private mdxLoaderPlugin;
107
106
  private runtimeBundleService;
108
107
  private readonly hmrPageMetadataCache;
108
+ private runtimeDependenciesInitialized;
109
109
  /**
110
110
  * Indicates whether React explicit graph mode is enabled for renderer/HMR behavior.
111
111
  */
112
112
  private explicitGraphEnabled;
113
113
  constructor(options?: Omit<ReactPluginOptions, 'name'>);
114
+ private ensureRuntimeDependencies;
114
115
  get plugins(): EcoBuildPlugin[];
116
+ /**
117
+ * Ensures the optional React MDX loader exists before either config-time
118
+ * manifest sealing or runtime setup needs it.
119
+ */
120
+ private ensureMdxLoaderPlugin;
121
+ /**
122
+ * Prepares React's build-facing loader contributions before config build seals
123
+ * the app manifest.
124
+ */
125
+ prepareBuildContributions(): Promise<void>;
126
+ /**
127
+ * Performs runtime-only React setup after build contributions are already
128
+ * materialized.
129
+ */
115
130
  setup(): Promise<void>;
116
131
  /**
117
132
  * Provides React-specific HMR strategy with Fast Refresh support.
@@ -123,10 +138,7 @@ export declare class ReactPlugin extends IntegrationPlugin<React.JSX.Element> {
123
138
  * @returns ReactHmrStrategy instance for handling React component updates
124
139
  */
125
140
  getHmrStrategy(): HmrStrategy | undefined;
126
- /**
127
- * Override to register React-specific specifier mappings for HMR.
128
- */
129
- setHmrManager(hmrManager: IHmrManager): void;
141
+ getRuntimeSpecifierMap(): Record<string, string>;
130
142
  /**
131
143
  * Declares React's boundary deferral rule for cross-integration rendering.
132
144
  *
@@ -15,15 +15,21 @@ class ReactPlugin extends IntegrationPlugin {
15
15
  mdxLoaderPlugin;
16
16
  runtimeBundleService;
17
17
  hmrPageMetadataCache = new ReactHmrPageMetadataCache();
18
+ runtimeDependenciesInitialized = false;
18
19
  /**
19
20
  * Indicates whether React explicit graph mode is enabled for renderer/HMR behavior.
20
21
  */
21
22
  explicitGraphEnabled;
22
23
  constructor(options) {
23
- const extensions = [".tsx"];
24
+ const { extensions: _ignoredExtensions, ...restOptions } = options ?? {};
25
+ const extensions = [...options?.extensions ?? [".tsx"]];
24
26
  const mdxExtensions = options?.mdx?.extensions ?? [".mdx"];
25
27
  if (options?.mdx?.enabled) {
26
- extensions.push(...mdxExtensions);
28
+ for (const extension of mdxExtensions) {
29
+ if (!extensions.includes(extension)) {
30
+ extensions.push(extension);
31
+ }
32
+ }
27
33
  } else if (options?.mdx?.extensions?.length) {
28
34
  appLogger.warn(
29
35
  "MDX extensions provided but MDX is disabled. MDX files will not be processed. Set mdx.enabled to true to enable MDX support."
@@ -32,7 +38,8 @@ class ReactPlugin extends IntegrationPlugin {
32
38
  super({
33
39
  name: PLUGIN_NAME,
34
40
  extensions,
35
- ...options
41
+ jsxImportSource: "react",
42
+ ...restOptions
36
43
  });
37
44
  this.mdxEnabled = options?.mdx?.enabled ?? false;
38
45
  this.mdxExtensions = mdxExtensions;
@@ -59,7 +66,13 @@ class ReactPlugin extends IntegrationPlugin {
59
66
  ReactRenderer.mdxExtensions = this.mdxExtensions;
60
67
  ReactRenderer.explicitGraphEnabled = this.explicitGraphEnabled;
61
68
  ReactRenderer.hmrPageMetadataCache = this.hmrPageMetadataCache;
69
+ }
70
+ ensureRuntimeDependencies() {
71
+ if (this.runtimeDependenciesInitialized) {
72
+ return;
73
+ }
62
74
  this.integrationDependencies.unshift(...this.runtimeBundleService.getDependencies());
75
+ this.runtimeDependenciesInitialized = true;
63
76
  }
64
77
  get plugins() {
65
78
  if (this.mdxLoaderPlugin) {
@@ -67,11 +80,32 @@ class ReactPlugin extends IntegrationPlugin {
67
80
  }
68
81
  return [];
69
82
  }
70
- async setup() {
71
- if (this.mdxEnabled && this.mdxCompilerOptions) {
72
- const { createReactMdxLoaderPlugin } = await import("./utils/react-mdx-loader-plugin.js");
73
- this.mdxLoaderPlugin = createReactMdxLoaderPlugin(this.mdxCompilerOptions);
83
+ /**
84
+ * Ensures the optional React MDX loader exists before either config-time
85
+ * manifest sealing or runtime setup needs it.
86
+ */
87
+ async ensureMdxLoaderPlugin() {
88
+ if (!this.mdxEnabled || !this.mdxCompilerOptions || this.mdxLoaderPlugin) {
89
+ return;
74
90
  }
91
+ const { createReactMdxLoaderPlugin } = await import("./utils/react-mdx-loader-plugin.js");
92
+ this.mdxLoaderPlugin = createReactMdxLoaderPlugin(this.mdxCompilerOptions);
93
+ }
94
+ /**
95
+ * Prepares React's build-facing loader contributions before config build seals
96
+ * the app manifest.
97
+ */
98
+ async prepareBuildContributions() {
99
+ this.ensureRuntimeDependencies();
100
+ await this.ensureMdxLoaderPlugin();
101
+ }
102
+ /**
103
+ * Performs runtime-only React setup after build contributions are already
104
+ * materialized.
105
+ */
106
+ async setup() {
107
+ this.ensureRuntimeDependencies();
108
+ await this.ensureMdxLoaderPlugin();
75
109
  await super.setup();
76
110
  }
77
111
  /**
@@ -92,15 +126,13 @@ class ReactPlugin extends IntegrationPlugin {
92
126
  context,
93
127
  this.hmrPageMetadataCache,
94
128
  this.mdxCompilerOptions,
129
+ this.extensions,
130
+ this.appConfig.templatesExt,
95
131
  this.explicitGraphEnabled
96
132
  );
97
133
  }
98
- /**
99
- * Override to register React-specific specifier mappings for HMR.
100
- */
101
- setHmrManager(hmrManager) {
102
- super.setHmrManager(hmrManager);
103
- hmrManager.registerSpecifierMap(this.runtimeBundleService.getSpecifierMap());
134
+ getRuntimeSpecifierMap() {
135
+ return this.runtimeBundleService.getSpecifierMap();
104
136
  }
105
137
  /**
106
138
  * Declares React's boundary deferral rule for cross-integration rendering.
@@ -46,13 +46,13 @@ export interface ReactRouterAdapter {
46
46
  outputName: string;
47
47
  /**
48
48
  * Packages to externalize when bundling.
49
- * These should be available via import map.
49
+ * These should be available through the runtime bare-specifier map.
50
50
  * @example ['react', 'react-dom', 'react/jsx-runtime']
51
51
  */
52
52
  externals: string[];
53
53
  };
54
54
  /**
55
- * Bare specifier for the import map entry.
55
+ * Bare specifier for the runtime mapping entry.
56
56
  * This is what the hydration script will import from.
57
57
  * @example '@ecopages/react-router'
58
58
  */
@@ -16,13 +16,15 @@ export interface ReactBundleServiceConfig {
16
16
  rootDir: string;
17
17
  routerAdapter?: ReactRouterAdapter;
18
18
  mdxCompilerOptions?: CompileOptions;
19
+ nonReactExtensions?: string[];
20
+ jsxImportSource?: string;
19
21
  }
20
22
  /**
21
23
  * Manages esbuild bundle configuration and plugin creation for React page/component builds.
22
24
  */
23
25
  export declare class ReactBundleService {
24
- private readonly config;
25
26
  private readonly runtimeBundleService;
27
+ private readonly config;
26
28
  constructor(config: ReactBundleServiceConfig);
27
29
  /**
28
30
  * Returns resolved runtime import paths for the React runtime.
@@ -41,28 +43,5 @@ export declare class ReactBundleService {
41
43
  * Creates the esbuild plugin that rewrites bare React specifiers
42
44
  * to their runtime asset URLs.
43
45
  */
44
- createRuntimeAliasPlugin(runtimeImports: ReactRuntimeImports): {
45
- name: string;
46
- setup(build: {
47
- onResolve: (options: {
48
- filter: RegExp;
49
- namespace?: string;
50
- }, callback: (args: {
51
- path: string;
52
- importer: string;
53
- namespace: string;
54
- }) => {
55
- path?: string;
56
- namespace?: string;
57
- external?: boolean;
58
- } | undefined) => void;
59
- }): void;
60
- };
61
- /**
62
- * Creates the esbuild plugin that shims `use-sync-external-store/shim`
63
- * to re-export from React's built-in `useSyncExternalStore`.
64
- * This is needed because some packages use `use-sync-external-store/shim`
65
- * but React 18+ has built-in `useSyncExternalStore`.
66
- */
67
- private createSyncExternalStorePlugin;
46
+ createRuntimeAliasPlugin(runtimeSpecifierMap: Record<string, string>): import("@ecopages/core/build/build-types").EcoBuildPlugin | null;
68
47
  }
@@ -1,13 +1,22 @@
1
1
  import { createClientGraphBoundaryPlugin } from "../utils/client-graph-boundary-plugin.js";
2
+ import {
3
+ buildReactRuntimeSpecifierMap,
4
+ getReactClientGraphAllowSpecifiers,
5
+ getReactRuntimeExternalSpecifiers
6
+ } from "../utils/react-runtime-specifier-map.js";
7
+ import { createForeignJsxOverridePlugin } from "../utils/foreign-jsx-override-plugin.js";
8
+ import { createUseSyncExternalStoreShimPlugin } from "../utils/use-sync-external-store-shim-plugin.js";
9
+ import { createRuntimeSpecifierAliasPlugin } from "@ecopages/core/build/runtime-specifier-alias-plugin";
2
10
  import { ReactRuntimeBundleService } from "./react-runtime-bundle.service.js";
3
11
  class ReactBundleService {
12
+ runtimeBundleService;
13
+ config;
4
14
  constructor(config) {
5
15
  this.config = config;
6
16
  this.runtimeBundleService = new ReactRuntimeBundleService({
7
17
  routerAdapter: config.routerAdapter
8
18
  });
9
19
  }
10
- runtimeBundleService;
11
20
  /**
12
21
  * Returns resolved runtime import paths for the React runtime.
13
22
  */
@@ -24,8 +33,9 @@ class ReactBundleService {
24
33
  */
25
34
  async createBundleOptions(componentName, isMdx, declaredModules) {
26
35
  const runtimeImports = this.getRuntimeImports();
36
+ const runtimeSpecifierMap = buildReactRuntimeSpecifierMap(runtimeImports, this.config.routerAdapter);
27
37
  const options = {
28
- external: ["react", "react-dom", "react/jsx-runtime", "react/jsx-dev-runtime", "react-dom/client"],
38
+ external: getReactRuntimeExternalSpecifiers(),
29
39
  mainFields: ["module", "browser", "main"],
30
40
  naming: `${componentName}.[ext]`,
31
41
  ...import.meta.env?.NODE_ENV === "production" && {
@@ -37,24 +47,34 @@ class ReactBundleService {
37
47
  const graphBoundaryPlugin = createClientGraphBoundaryPlugin({
38
48
  absWorkingDir: this.config.rootDir,
39
49
  declaredModules,
40
- alwaysAllowSpecifiers: [
41
- "@ecopages/core",
42
- "react",
43
- "react-dom",
44
- "react/jsx-runtime",
45
- "react/jsx-dev-runtime",
46
- "react-dom/client",
47
- ...this.config.routerAdapter ? [this.config.routerAdapter.importMapKey] : []
48
- ]
50
+ alwaysAllowSpecifiers: getReactClientGraphAllowSpecifiers([], this.config.routerAdapter)
51
+ });
52
+ const foreignJsxOverridePlugin = createForeignJsxOverridePlugin(this.config.nonReactExtensions ?? [], {
53
+ name: "react-renderer-foreign-jsx-override",
54
+ jsxImportSource: this.config.jsxImportSource ?? "react"
55
+ });
56
+ const runtimeAliasPlugin = this.createRuntimeAliasPlugin(runtimeSpecifierMap);
57
+ const useSyncExternalStoreShimPlugin = createUseSyncExternalStoreShimPlugin({
58
+ name: "react-renderer-use-sync-external-store-shim",
59
+ namespace: "ecopages-react-renderer-shim"
49
60
  });
50
- const runtimeAliasPlugin = this.createRuntimeAliasPlugin(runtimeImports);
51
- const useSyncExternalStoreShimPlugin = this.createSyncExternalStorePlugin();
52
61
  if (isMdx && this.config.mdxCompilerOptions) {
53
62
  const { createReactMdxLoaderPlugin } = await import("../utils/react-mdx-loader-plugin.js");
54
63
  const mdxPlugin = createReactMdxLoaderPlugin(this.config.mdxCompilerOptions);
55
- options.plugins = [runtimeAliasPlugin, mdxPlugin, useSyncExternalStoreShimPlugin, graphBoundaryPlugin];
64
+ options.plugins = [
65
+ foreignJsxOverridePlugin,
66
+ graphBoundaryPlugin,
67
+ runtimeAliasPlugin,
68
+ mdxPlugin,
69
+ useSyncExternalStoreShimPlugin
70
+ ];
56
71
  } else {
57
- options.plugins = [runtimeAliasPlugin, useSyncExternalStoreShimPlugin, graphBoundaryPlugin];
72
+ options.plugins = [
73
+ foreignJsxOverridePlugin,
74
+ graphBoundaryPlugin,
75
+ runtimeAliasPlugin,
76
+ useSyncExternalStoreShimPlugin
77
+ ];
58
78
  }
59
79
  return options;
60
80
  }
@@ -62,82 +82,8 @@ class ReactBundleService {
62
82
  * Creates the esbuild plugin that rewrites bare React specifiers
63
83
  * to their runtime asset URLs.
64
84
  */
65
- createRuntimeAliasPlugin(runtimeImports) {
66
- const aliases = /* @__PURE__ */ new Map([
67
- ["react", runtimeImports.react],
68
- ["react-dom/client", runtimeImports.reactDomClient],
69
- ["react/jsx-runtime", runtimeImports.reactJsxRuntime],
70
- ["react/jsx-dev-runtime", runtimeImports.reactJsxDevRuntime],
71
- ["react-dom", runtimeImports.reactDom]
72
- ]);
73
- if (this.config.routerAdapter && runtimeImports.router) {
74
- aliases.set(this.config.routerAdapter.importMapKey, runtimeImports.router);
75
- }
76
- const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
77
- const pattern = new RegExp(
78
- `^(${Array.from(aliases.keys()).map((key) => escapeRegExp(key)).join("|")})$`
79
- );
80
- return {
81
- name: "react-runtime-import-alias",
82
- setup(build) {
83
- build.onResolve({ filter: pattern }, (args) => {
84
- const mappedPath = aliases.get(args.path);
85
- if (!mappedPath) {
86
- return void 0;
87
- }
88
- return {
89
- path: mappedPath,
90
- external: true
91
- };
92
- });
93
- }
94
- };
95
- }
96
- /**
97
- * Creates the esbuild plugin that shims `use-sync-external-store/shim`
98
- * to re-export from React's built-in `useSyncExternalStore`.
99
- * This is needed because some packages use `use-sync-external-store/shim`
100
- * but React 18+ has built-in `useSyncExternalStore`.
101
- */
102
- createSyncExternalStorePlugin() {
103
- return {
104
- name: "react-renderer-use-sync-external-store-shim",
105
- setup(build) {
106
- build.onResolve({ filter: /^use-sync-external-store\/shim(?:\/index\.js)?$/ }, () => ({
107
- path: "use-sync-external-store/shim",
108
- namespace: "ecopages-react-renderer-shim"
109
- }));
110
- build.onLoad(
111
- { filter: /^use-sync-external-store\/shim$/, namespace: "ecopages-react-renderer-shim" },
112
- () => ({
113
- contents: "export { useSyncExternalStore } from 'react';",
114
- loader: "js"
115
- })
116
- );
117
- build.onLoad({ filter: /[\\/]use-sync-external-store[\\/]shim[\\/]index\.js$/ }, () => ({
118
- contents: "export { useSyncExternalStore } from 'react';",
119
- loader: "js"
120
- }));
121
- build.onLoad(
122
- {
123
- filter: /[\\/]use-sync-external-store[\\/]cjs[\\/]use-sync-external-store-shim\.development\.js$/
124
- },
125
- () => ({
126
- contents: "export { useSyncExternalStore } from 'react';",
127
- loader: "js"
128
- })
129
- );
130
- build.onLoad(
131
- {
132
- filter: /[\\/]use-sync-external-store[\\/]cjs[\\/]use-sync-external-store-shim\.production\.js$/
133
- },
134
- () => ({
135
- contents: "export { useSyncExternalStore } from 'react';",
136
- loader: "js"
137
- })
138
- );
139
- }
140
- };
85
+ createRuntimeAliasPlugin(runtimeSpecifierMap) {
86
+ return createRuntimeSpecifierAliasPlugin(runtimeSpecifierMap, { name: "react-runtime-import-alias" });
141
87
  }
142
88
  }
143
89
  export {
@@ -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.__ECO_PAGE__={module:"${importPath}",props:${JSON.stringify(props)}};`,
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: {
@@ -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 { defaultBuildAdapter } from "@ecopages/core/build/build-adapter";
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.distDir, ".server-modules-react-mdx");
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 defaultBuildAdapter.build({
40
- entrypoints: [filePath],
41
- root: this.config.rootDir,
42
- outdir,
43
- target: "node",
44
- format: "esm",
45
- sourcemap: "none",
46
- splitting: false,
47
- minify: false,
48
- treeshaking: false,
49
- naming: outputFileName,
50
- plugins: [mdxPlugin]
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}`);
@@ -58,7 +62,10 @@ class ReactPageModuleService {
58
62
  if (!compiledOutput) {
59
63
  throw new Error(`No compiled MDX output generated for page: ${filePath}`);
60
64
  }
61
- return await import(pathToFileURL(compiledOutput).href);
65
+ return await import(
66
+ /* @vite-ignore */
67
+ pathToFileURL(compiledOutput).href
68
+ );
62
69
  }
63
70
  /**
64
71
  * Ensures that an EcoComponentConfig has proper `__eco` metadata attached.
@@ -91,7 +98,7 @@ class ReactPageModuleService {
91
98
  if (fileSystem.exists(resolvedDependency)) {
92
99
  return {
93
100
  ...config,
94
- __eco: buildEcoMeta(resolvedDependency)
101
+ __eco: buildEcoMeta(path.join(candidateDir, path.basename(pagePath)))
95
102
  };
96
103
  }
97
104
  }
@@ -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 temporary entry generation, specifier mapping, and React DOM
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
- getRuntimeImports(): ReactRuntimeImports;
28
- getSpecifierMap(): Record<string, string>;
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 {};