@ecopages/react 0.2.0-alpha.9 → 0.2.0-beta.1
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 +30 -13
- package/package.json +23 -12
- package/src/eco-embed.d.ts +11 -0
- package/src/eco-embed.js +11 -0
- package/src/react-hmr-strategy.d.ts +102 -18
- package/src/react-hmr-strategy.js +427 -50
- package/src/react-renderer.d.ts +100 -92
- package/src/react-renderer.js +356 -340
- package/src/react.constants.d.ts +1 -0
- package/src/react.constants.js +4 -0
- package/src/react.plugin.d.ts +25 -107
- package/src/react.plugin.js +109 -61
- package/src/react.types.d.ts +88 -0
- package/src/react.types.js +0 -0
- package/src/router-adapter.d.ts +7 -14
- package/src/runtime/use-sync-external-store-with-selector.d.ts +3 -0
- package/src/runtime/use-sync-external-store-with-selector.js +56 -0
- package/src/services/pages-index.d.ts +64 -0
- package/src/services/pages-index.js +73 -0
- package/src/services/react-bundle.service.d.ts +24 -9
- package/src/services/react-bundle.service.js +35 -24
- package/src/services/react-hmr-page-metadata-cache.d.ts +10 -1
- package/src/services/react-hmr-page-metadata-cache.js +18 -2
- package/src/services/react-hydration-asset.service.d.ts +28 -19
- package/src/services/react-hydration-asset.service.js +83 -64
- package/src/services/react-mdx-config-dependency.service.d.ts +36 -0
- package/src/services/react-mdx-config-dependency.service.js +122 -0
- package/src/services/react-page-module.service.d.ts +8 -3
- package/src/services/react-page-module.service.js +33 -26
- package/src/services/react-page-payload.service.d.ts +46 -0
- package/src/services/react-page-payload.service.js +67 -0
- package/src/services/react-runtime-bundle.service.d.ts +9 -2
- package/src/services/react-runtime-bundle.service.js +77 -16
- package/src/utils/client-graph-boundary-cache.d.ts +108 -0
- package/src/utils/client-graph-boundary-cache.js +116 -0
- package/src/utils/client-graph-boundary-plugin.d.ts +13 -5
- package/src/utils/client-graph-boundary-plugin.js +63 -5
- package/src/utils/component-config-traversal.d.ts +36 -0
- package/src/utils/component-config-traversal.js +54 -0
- package/src/utils/declared-modules.d.ts +1 -1
- package/src/utils/declared-modules.js +7 -16
- package/src/utils/dynamic.test.browser.d.ts +1 -0
- package/src/utils/dynamic.test.browser.js +33 -0
- package/src/utils/hydration-scripts.d.ts +9 -5
- package/src/utils/hydration-scripts.js +119 -34
- package/src/utils/hydration-scripts.test.browser.d.ts +1 -0
- package/src/utils/hydration-scripts.test.browser.js +198 -0
- package/src/utils/react-dom-runtime-interop-plugin.d.ts +1 -1
- package/src/utils/react-dom-runtime-interop-plugin.js +9 -0
- package/src/utils/react-mdx-loader-plugin.d.ts +1 -1
- package/src/utils/{react-runtime-specifier-map.d.ts → react-runtime-alias-map.d.ts} +3 -1
- package/src/utils/react-runtime-alias-map.js +90 -0
- package/CHANGELOG.md +0 -27
- package/src/react-hmr-strategy.ts +0 -386
- package/src/react-renderer.ts +0 -803
- package/src/react.plugin.ts +0 -276
- package/src/router-adapter.ts +0 -95
- package/src/services/react-bundle.service.ts +0 -108
- package/src/services/react-hmr-page-metadata-cache.ts +0 -24
- package/src/services/react-hydration-asset.service.ts +0 -263
- package/src/services/react-page-module.service.ts +0 -224
- package/src/services/react-runtime-bundle.service.ts +0 -172
- package/src/utils/client-graph-boundary-plugin.ts +0 -831
- package/src/utils/client-only.ts +0 -27
- package/src/utils/declared-modules.ts +0 -99
- package/src/utils/dynamic.ts +0 -27
- package/src/utils/hmr-scripts.ts +0 -47
- package/src/utils/html-boundary.ts +0 -66
- package/src/utils/hydration-scripts.ts +0 -459
- package/src/utils/reachability-analyzer.ts +0 -593
- package/src/utils/react-dom-runtime-interop-plugin.ts +0 -33
- package/src/utils/react-mdx-loader-plugin.ts +0 -63
- package/src/utils/react-runtime-specifier-map.js +0 -37
- package/src/utils/react-runtime-specifier-map.ts +0 -45
- package/src/utils/use-sync-external-store-shim-plugin.d.ts +0 -5
- package/src/utils/use-sync-external-store-shim-plugin.js +0 -41
- package/src/utils/use-sync-external-store-shim-plugin.ts +0 -45
package/src/react.plugin.ts
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This module contains the react plugin for Ecopages
|
|
3
|
-
* @module
|
|
4
|
-
*/
|
|
5
|
-
import { IntegrationPlugin } from '@ecopages/core/plugins/integration-plugin';
|
|
6
|
-
import type { EcoBuildPlugin } from '@ecopages/core/build/build-types';
|
|
7
|
-
import type { HmrStrategy } from '@ecopages/core/hmr/hmr-strategy';
|
|
8
|
-
import type { AssetDefinition } from '@ecopages/core/services/asset-processing-service';
|
|
9
|
-
import { Logger } from '@ecopages/logger';
|
|
10
|
-
import type { CompileOptions } from '@mdx-js/mdx';
|
|
11
|
-
import type React from 'react';
|
|
12
|
-
import { ReactRenderer } from './react-renderer.ts';
|
|
13
|
-
import { ReactHmrStrategy } from './react-hmr-strategy.ts';
|
|
14
|
-
import type { ReactRouterAdapter } from './router-adapter.ts';
|
|
15
|
-
import type { ComponentBoundaryPolicyInput } from '@ecopages/core/plugins/integration-plugin';
|
|
16
|
-
import { ReactRuntimeBundleService } from './services/react-runtime-bundle.service.ts';
|
|
17
|
-
import { ReactHmrPageMetadataCache } from './services/react-hmr-page-metadata-cache.ts';
|
|
18
|
-
|
|
19
|
-
const appLogger = new Logger('[ReactPlugin]');
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* MDX configuration options for the React plugin
|
|
23
|
-
*/
|
|
24
|
-
export type ReactMdxOptions = {
|
|
25
|
-
/**
|
|
26
|
-
* Whether to enable MDX support.
|
|
27
|
-
* @default false
|
|
28
|
-
*/
|
|
29
|
-
enabled: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Compiler options for MDX.
|
|
32
|
-
* @default undefined
|
|
33
|
-
*/
|
|
34
|
-
compilerOptions?: Omit<CompileOptions, 'jsxImportSource' | 'jsxRuntime'>;
|
|
35
|
-
/**
|
|
36
|
-
* Remark plugins.
|
|
37
|
-
* @default undefined
|
|
38
|
-
*/
|
|
39
|
-
remarkPlugins?: CompileOptions['remarkPlugins'];
|
|
40
|
-
/**
|
|
41
|
-
* Rehype plugins.
|
|
42
|
-
* @default undefined
|
|
43
|
-
*/
|
|
44
|
-
rehypePlugins?: CompileOptions['rehypePlugins'];
|
|
45
|
-
/**
|
|
46
|
-
* Recma plugins.
|
|
47
|
-
* @default undefined
|
|
48
|
-
*/
|
|
49
|
-
recmaPlugins?: CompileOptions['recmaPlugins'];
|
|
50
|
-
/**
|
|
51
|
-
* Custom extensions to be treated as MDX files.
|
|
52
|
-
* @default ['.mdx']
|
|
53
|
-
*/
|
|
54
|
-
extensions?: string[];
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Options for the React plugin
|
|
59
|
-
*/
|
|
60
|
-
export type ReactPluginOptions = {
|
|
61
|
-
extensions?: string[];
|
|
62
|
-
dependencies?: AssetDefinition[];
|
|
63
|
-
/**
|
|
64
|
-
* Enables explicit client graph mode for React page entries.
|
|
65
|
-
*
|
|
66
|
-
* When enabled, React page-entry bundling relies on explicit dependency declarations
|
|
67
|
-
* and skips AST-based `middleware`/`requires` stripping in the React path.
|
|
68
|
-
* @default false
|
|
69
|
-
*/
|
|
70
|
-
explicitGraph?: boolean;
|
|
71
|
-
/**
|
|
72
|
-
* Router adapter for SPA navigation.
|
|
73
|
-
* When provided, pages with layouts will be wrapped in the router for client-side navigation.
|
|
74
|
-
* @example
|
|
75
|
-
* ```ts
|
|
76
|
-
* import { ecoRouter } from '@ecopages/react-router';
|
|
77
|
-
* reactPlugin({ router: ecoRouter() })
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
|
-
router?: ReactRouterAdapter;
|
|
81
|
-
/**
|
|
82
|
-
* MDX configuration for handling .mdx files within the React plugin.
|
|
83
|
-
* When enabled, MDX files are treated as React pages with full router support.
|
|
84
|
-
* @example
|
|
85
|
-
* ```ts
|
|
86
|
-
* reactPlugin({
|
|
87
|
-
* router: ecoRouter(),
|
|
88
|
-
* mdx: {
|
|
89
|
-
* enabled: true,
|
|
90
|
-
* extensions: ['.mdx', '.md'],
|
|
91
|
-
* remarkPlugins: [remarkGfm],
|
|
92
|
-
* rehypePlugins: [[rehypePrettyCode, { theme: '...' }]],
|
|
93
|
-
* }
|
|
94
|
-
* })
|
|
95
|
-
* ```
|
|
96
|
-
*/
|
|
97
|
-
mdx?: ReactMdxOptions;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* The name of the React plugin
|
|
102
|
-
*/
|
|
103
|
-
export const PLUGIN_NAME = 'react';
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* The React plugin class
|
|
107
|
-
* This plugin provides support for React components in Ecopages
|
|
108
|
-
*/
|
|
109
|
-
export class ReactPlugin extends IntegrationPlugin<React.JSX.Element> {
|
|
110
|
-
renderer = ReactRenderer;
|
|
111
|
-
routerAdapter: ReactRouterAdapter | undefined;
|
|
112
|
-
private mdxEnabled: boolean;
|
|
113
|
-
private mdxCompilerOptions?: CompileOptions;
|
|
114
|
-
private mdxExtensions: string[];
|
|
115
|
-
private mdxLoaderPlugin: EcoBuildPlugin | undefined;
|
|
116
|
-
private runtimeBundleService: ReactRuntimeBundleService;
|
|
117
|
-
private readonly hmrPageMetadataCache = new ReactHmrPageMetadataCache();
|
|
118
|
-
private runtimeDependenciesInitialized = false;
|
|
119
|
-
/**
|
|
120
|
-
* Indicates whether React explicit graph mode is enabled for renderer/HMR behavior.
|
|
121
|
-
*/
|
|
122
|
-
private explicitGraphEnabled: boolean;
|
|
123
|
-
|
|
124
|
-
constructor(options?: Omit<ReactPluginOptions, 'name'>) {
|
|
125
|
-
const { extensions: _ignoredExtensions, ...restOptions } = options ?? {};
|
|
126
|
-
const extensions = [...(options?.extensions ?? ['.tsx'])];
|
|
127
|
-
const mdxExtensions = options?.mdx?.extensions ?? ['.mdx'];
|
|
128
|
-
|
|
129
|
-
if (options?.mdx?.enabled) {
|
|
130
|
-
for (const extension of mdxExtensions) {
|
|
131
|
-
if (!extensions.includes(extension)) {
|
|
132
|
-
extensions.push(extension);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
} else if (options?.mdx?.extensions?.length) {
|
|
136
|
-
appLogger.warn(
|
|
137
|
-
'MDX extensions provided but MDX is disabled. MDX files will not be processed. Set mdx.enabled to true to enable MDX support.',
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
super({
|
|
142
|
-
name: PLUGIN_NAME,
|
|
143
|
-
extensions,
|
|
144
|
-
...restOptions,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
this.mdxEnabled = options?.mdx?.enabled ?? false;
|
|
148
|
-
this.mdxExtensions = mdxExtensions;
|
|
149
|
-
|
|
150
|
-
if (this.mdxEnabled) {
|
|
151
|
-
const { compilerOptions, remarkPlugins, rehypePlugins, recmaPlugins } = options?.mdx || {};
|
|
152
|
-
this.mdxCompilerOptions = {
|
|
153
|
-
...compilerOptions,
|
|
154
|
-
remarkPlugins: [...(compilerOptions?.remarkPlugins || []), ...(remarkPlugins || [])],
|
|
155
|
-
rehypePlugins: [...(compilerOptions?.rehypePlugins || []), ...(rehypePlugins || [])],
|
|
156
|
-
recmaPlugins: [...(compilerOptions?.recmaPlugins || []), ...(recmaPlugins || [])],
|
|
157
|
-
jsxImportSource: 'react',
|
|
158
|
-
jsxRuntime: 'automatic',
|
|
159
|
-
development: process.env.NODE_ENV === 'development',
|
|
160
|
-
};
|
|
161
|
-
appLogger.debug('MDX mode enabled with React jsx runtime');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
this.routerAdapter = options?.router;
|
|
165
|
-
this.runtimeBundleService = new ReactRuntimeBundleService({
|
|
166
|
-
routerAdapter: this.routerAdapter,
|
|
167
|
-
});
|
|
168
|
-
this.explicitGraphEnabled = options?.explicitGraph ?? false;
|
|
169
|
-
ReactRenderer.routerAdapter = this.routerAdapter;
|
|
170
|
-
ReactRenderer.mdxCompilerOptions = this.mdxCompilerOptions;
|
|
171
|
-
ReactRenderer.mdxExtensions = this.mdxExtensions;
|
|
172
|
-
ReactRenderer.explicitGraphEnabled = this.explicitGraphEnabled;
|
|
173
|
-
ReactRenderer.hmrPageMetadataCache = this.hmrPageMetadataCache;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private ensureRuntimeDependencies(): void {
|
|
177
|
-
if (this.runtimeDependenciesInitialized) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
this.integrationDependencies.unshift(...this.runtimeBundleService.getDependencies());
|
|
182
|
-
this.runtimeDependenciesInitialized = true;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
override get plugins(): EcoBuildPlugin[] {
|
|
186
|
-
if (this.mdxLoaderPlugin) {
|
|
187
|
-
return [this.mdxLoaderPlugin];
|
|
188
|
-
}
|
|
189
|
-
return [];
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Ensures the optional React MDX loader exists before either config-time
|
|
194
|
-
* manifest sealing or runtime setup needs it.
|
|
195
|
-
*/
|
|
196
|
-
private async ensureMdxLoaderPlugin(): Promise<void> {
|
|
197
|
-
if (!this.mdxEnabled || !this.mdxCompilerOptions || this.mdxLoaderPlugin) {
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const { createReactMdxLoaderPlugin } = await import('./utils/react-mdx-loader-plugin.ts');
|
|
202
|
-
this.mdxLoaderPlugin = createReactMdxLoaderPlugin(this.mdxCompilerOptions);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Prepares React's build-facing loader contributions before config build seals
|
|
207
|
-
* the app manifest.
|
|
208
|
-
*/
|
|
209
|
-
override async prepareBuildContributions(): Promise<void> {
|
|
210
|
-
this.ensureRuntimeDependencies();
|
|
211
|
-
await this.ensureMdxLoaderPlugin();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Performs runtime-only React setup after build contributions are already
|
|
216
|
-
* materialized.
|
|
217
|
-
*/
|
|
218
|
-
override async setup(): Promise<void> {
|
|
219
|
-
this.ensureRuntimeDependencies();
|
|
220
|
-
await this.ensureMdxLoaderPlugin();
|
|
221
|
-
await super.setup();
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Provides React-specific HMR strategy with Fast Refresh support.
|
|
226
|
-
*
|
|
227
|
-
* The strategy shares a React-only page metadata cache with the renderer so
|
|
228
|
-
* save-time rebuilds can reuse declared-module analysis without expanding the
|
|
229
|
-
* core HMR interfaces.
|
|
230
|
-
*
|
|
231
|
-
* @returns ReactHmrStrategy instance for handling React component updates
|
|
232
|
-
*/
|
|
233
|
-
override getHmrStrategy(): HmrStrategy | undefined {
|
|
234
|
-
if (!this.hmrManager || !this.appConfig) {
|
|
235
|
-
return undefined;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const context = this.hmrManager.getDefaultContext();
|
|
239
|
-
|
|
240
|
-
return new ReactHmrStrategy(
|
|
241
|
-
context,
|
|
242
|
-
this.hmrPageMetadataCache,
|
|
243
|
-
this.mdxCompilerOptions,
|
|
244
|
-
this.extensions,
|
|
245
|
-
this.appConfig.templatesExt,
|
|
246
|
-
this.explicitGraphEnabled,
|
|
247
|
-
);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
override getRuntimeSpecifierMap(): Record<string, string> {
|
|
251
|
-
return this.runtimeBundleService.getSpecifierMap();
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Declares React's boundary deferral rule for cross-integration rendering.
|
|
256
|
-
*
|
|
257
|
-
* React defers when a render pass owned by another integration enters a React
|
|
258
|
-
* component boundary. That boundary is then resolved later through the marker
|
|
259
|
-
* graph stage using the React renderer.
|
|
260
|
-
*
|
|
261
|
-
* @param input Boundary metadata for the active render pass.
|
|
262
|
-
* @returns `true` when the boundary should be deferred into the marker pass.
|
|
263
|
-
*/
|
|
264
|
-
override shouldDeferComponentBoundary(input: ComponentBoundaryPolicyInput): boolean {
|
|
265
|
-
return input.targetIntegration === this.name && input.currentIntegration !== this.name;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Factory function to create a React plugin instance
|
|
271
|
-
* @param options Configuration options for the React plugin
|
|
272
|
-
* @returns A new ReactPlugin instance
|
|
273
|
-
*/
|
|
274
|
-
export function reactPlugin(options?: ReactPluginOptions): ReactPlugin {
|
|
275
|
-
return new ReactPlugin(options);
|
|
276
|
-
}
|
package/src/router-adapter.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Router adapter interface for React integration.
|
|
3
|
-
* Allows pluggable SPA routers to be used with the React plugin.
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Configuration for a React router adapter.
|
|
9
|
-
* Implement this interface to create custom router integrations.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* const myRouter: ReactRouterAdapter = {
|
|
14
|
-
* name: 'my-router',
|
|
15
|
-
* bundle: {
|
|
16
|
-
* importPath: '@my/router/browser.ts',
|
|
17
|
-
* outputName: 'my-router',
|
|
18
|
-
* externals: ['react', 'react-dom'],
|
|
19
|
-
* },
|
|
20
|
-
* importMapKey: '@my/router',
|
|
21
|
-
* components: {
|
|
22
|
-
* router: 'MyRouter',
|
|
23
|
-
* pageContent: 'PageOutlet',
|
|
24
|
-
* },
|
|
25
|
-
* getRouterProps: (page, props) => `{ page: ${page}, pageProps: ${props} }`,
|
|
26
|
-
* };
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
export interface ReactRouterAdapter {
|
|
30
|
-
/**
|
|
31
|
-
* Unique identifier for caching and debugging.
|
|
32
|
-
*/
|
|
33
|
-
name: string;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Runtime bundle configuration.
|
|
37
|
-
*/
|
|
38
|
-
bundle: {
|
|
39
|
-
/**
|
|
40
|
-
* Node module import path for the browser-compatible entry.
|
|
41
|
-
* @example '@ecopages/react-router/browser.ts'
|
|
42
|
-
*/
|
|
43
|
-
importPath: string;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Output filename (without extension).
|
|
47
|
-
* @example 'react-router-esm'
|
|
48
|
-
*/
|
|
49
|
-
outputName: string;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Packages to externalize when bundling.
|
|
53
|
-
* These should be available through the runtime bare-specifier map.
|
|
54
|
-
* @example ['react', 'react-dom', 'react/jsx-runtime']
|
|
55
|
-
*/
|
|
56
|
-
externals: string[];
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Bare specifier for the runtime mapping entry.
|
|
61
|
-
* This is what the hydration script will import from.
|
|
62
|
-
* @example '@ecopages/react-router'
|
|
63
|
-
*/
|
|
64
|
-
importMapKey: string;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Component names to import from the router package.
|
|
68
|
-
*/
|
|
69
|
-
components: {
|
|
70
|
-
/**
|
|
71
|
-
* The router component that wraps the layout.
|
|
72
|
-
* @example 'EcoRouter'
|
|
73
|
-
*/
|
|
74
|
-
router: string;
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* The component that renders the current page content.
|
|
78
|
-
* @example 'PageContent'
|
|
79
|
-
*/
|
|
80
|
-
pageContent: string;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Generate the props object for the router component.
|
|
85
|
-
* @param page - Variable name holding the page component
|
|
86
|
-
* @param props - Variable name holding the page props
|
|
87
|
-
* @returns Code string for the router props
|
|
88
|
-
* @example
|
|
89
|
-
* ```ts
|
|
90
|
-
* getRouterProps: (page, props) => `{ page: ${page}, pageProps: ${props} }`
|
|
91
|
-
* // Results in: { page: Component, pageProps: props }
|
|
92
|
-
* ```
|
|
93
|
-
*/
|
|
94
|
-
getRouterProps(page: string, props: string): string;
|
|
95
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bundle configuration service for React integration.
|
|
3
|
-
*
|
|
4
|
-
* Encapsulates all esbuild plugin creation and bundle options
|
|
5
|
-
* for client-side React component builds.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { createClientGraphBoundaryPlugin } from '../utils/client-graph-boundary-plugin.ts';
|
|
11
|
-
import {
|
|
12
|
-
buildReactRuntimeSpecifierMap,
|
|
13
|
-
getReactClientGraphAllowSpecifiers,
|
|
14
|
-
getReactRuntimeExternalSpecifiers,
|
|
15
|
-
} from '../utils/react-runtime-specifier-map.ts';
|
|
16
|
-
import { createUseSyncExternalStoreShimPlugin } from '../utils/use-sync-external-store-shim-plugin.ts';
|
|
17
|
-
import { createRuntimeSpecifierAliasPlugin } from '@ecopages/core/build/runtime-specifier-alias-plugin';
|
|
18
|
-
import type { ReactRouterAdapter } from '../router-adapter.ts';
|
|
19
|
-
import type { CompileOptions } from '@mdx-js/mdx';
|
|
20
|
-
import { ReactRuntimeBundleService, type ReactRuntimeImports } from './react-runtime-bundle.service.ts';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Configuration for the ReactBundleService.
|
|
24
|
-
*/
|
|
25
|
-
export interface ReactBundleServiceConfig {
|
|
26
|
-
rootDir: string;
|
|
27
|
-
routerAdapter?: ReactRouterAdapter;
|
|
28
|
-
mdxCompilerOptions?: CompileOptions;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Manages esbuild bundle configuration and plugin creation for React page/component builds.
|
|
33
|
-
*/
|
|
34
|
-
export class ReactBundleService {
|
|
35
|
-
private readonly runtimeBundleService: ReactRuntimeBundleService;
|
|
36
|
-
private readonly config: ReactBundleServiceConfig;
|
|
37
|
-
|
|
38
|
-
constructor(config: ReactBundleServiceConfig) {
|
|
39
|
-
this.config = config;
|
|
40
|
-
this.runtimeBundleService = new ReactRuntimeBundleService({
|
|
41
|
-
routerAdapter: config.routerAdapter,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Returns resolved runtime import paths for the React runtime.
|
|
47
|
-
*/
|
|
48
|
-
getRuntimeImports(): ReactRuntimeImports {
|
|
49
|
-
return this.runtimeBundleService.getRuntimeImports();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Creates esbuild bundle options for a page or component entry.
|
|
54
|
-
*
|
|
55
|
-
* @param componentName - Generated unique component name for output naming
|
|
56
|
-
* @param isMdx - Whether the source file is an MDX file
|
|
57
|
-
* @param declaredModules - Explicitly declared browser module specifiers
|
|
58
|
-
* @returns Bundle options object for the build adapter
|
|
59
|
-
*/
|
|
60
|
-
async createBundleOptions(
|
|
61
|
-
componentName: string,
|
|
62
|
-
isMdx: boolean,
|
|
63
|
-
declaredModules: string[],
|
|
64
|
-
): Promise<Record<string, unknown>> {
|
|
65
|
-
const runtimeImports = this.getRuntimeImports();
|
|
66
|
-
const runtimeSpecifierMap = buildReactRuntimeSpecifierMap(runtimeImports, this.config.routerAdapter);
|
|
67
|
-
const options: Record<string, unknown> = {
|
|
68
|
-
external: getReactRuntimeExternalSpecifiers(),
|
|
69
|
-
mainFields: ['module', 'browser', 'main'],
|
|
70
|
-
naming: `${componentName}.[ext]`,
|
|
71
|
-
...(import.meta.env?.NODE_ENV === 'production' && {
|
|
72
|
-
minify: true,
|
|
73
|
-
splitting: false,
|
|
74
|
-
treeshaking: true,
|
|
75
|
-
}),
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const graphBoundaryPlugin = createClientGraphBoundaryPlugin({
|
|
79
|
-
absWorkingDir: this.config.rootDir,
|
|
80
|
-
declaredModules,
|
|
81
|
-
alwaysAllowSpecifiers: getReactClientGraphAllowSpecifiers([], this.config.routerAdapter),
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const runtimeAliasPlugin = this.createRuntimeAliasPlugin(runtimeSpecifierMap);
|
|
85
|
-
const useSyncExternalStoreShimPlugin = createUseSyncExternalStoreShimPlugin({
|
|
86
|
-
name: 'react-renderer-use-sync-external-store-shim',
|
|
87
|
-
namespace: 'ecopages-react-renderer-shim',
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
if (isMdx && this.config.mdxCompilerOptions) {
|
|
91
|
-
const { createReactMdxLoaderPlugin } = await import('../utils/react-mdx-loader-plugin.ts');
|
|
92
|
-
const mdxPlugin = createReactMdxLoaderPlugin(this.config.mdxCompilerOptions);
|
|
93
|
-
options.plugins = [graphBoundaryPlugin, runtimeAliasPlugin, mdxPlugin, useSyncExternalStoreShimPlugin];
|
|
94
|
-
} else {
|
|
95
|
-
options.plugins = [graphBoundaryPlugin, runtimeAliasPlugin, useSyncExternalStoreShimPlugin];
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return options;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Creates the esbuild plugin that rewrites bare React specifiers
|
|
103
|
-
* to their runtime asset URLs.
|
|
104
|
-
*/
|
|
105
|
-
createRuntimeAliasPlugin(runtimeSpecifierMap: Record<string, string>) {
|
|
106
|
-
return createRuntimeSpecifierAliasPlugin(runtimeSpecifierMap, { name: 'react-runtime-import-alias' });
|
|
107
|
-
}
|
|
108
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React-only cache for page metadata that HMR rebuilds need during development.
|
|
3
|
-
*
|
|
4
|
-
* This keeps React Fast Refresh optimizations local to the React integration so
|
|
5
|
-
* core HMR interfaces do not need React-specific metadata hooks.
|
|
6
|
-
*/
|
|
7
|
-
export class ReactHmrPageMetadataCache {
|
|
8
|
-
private readonly declaredModulesByEntrypoint = new Map<string, string[]>();
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Stores the declared browser modules for a page entrypoint.
|
|
12
|
-
*/
|
|
13
|
-
setDeclaredModules(entrypointPath: string, declaredModules: string[]): void {
|
|
14
|
-
this.declaredModulesByEntrypoint.set(entrypointPath, [...declaredModules]);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Returns the last known declared browser modules for a page entrypoint.
|
|
19
|
-
*/
|
|
20
|
-
getDeclaredModules(entrypointPath: string): string[] | undefined {
|
|
21
|
-
const declaredModules = this.declaredModulesByEntrypoint.get(entrypointPath);
|
|
22
|
-
return declaredModules ? [...declaredModules] : undefined;
|
|
23
|
-
}
|
|
24
|
-
}
|