@ecopages/core 0.2.0-rc.3 → 0.2.0-rc.5
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 +5 -2
- package/package.json +7 -4
- package/src/build/contracts/content-virtual-modules.d.ts +3 -1
- package/src/build/contracts/content-virtual-modules.js +8 -0
- package/src/css-imports.d.ts +4 -0
- package/src/declarations.d.ts +2 -5
- package/src/dev/README.md +2 -0
- package/src/dev/transform-server/dev-transform-server.d.ts +6 -0
- package/src/dev/transform-server/dev-transform-server.js +16 -5
- package/src/eco/README.md +71 -5
- package/src/eco/component-identity.d.ts +3 -2
- package/src/eco/component-identity.js +5 -2
- package/src/eco/discovered-dependencies.d.ts +45 -0
- package/src/eco/discovered-dependencies.js +87 -0
- package/src/eco/eco.js +2 -0
- package/src/eco/eco.types.d.ts +18 -2
- package/src/eco/page-dependency-contributions.d.ts +19 -0
- package/src/eco/page-dependency-contributions.js +52 -0
- package/src/index.browser.d.ts +3 -0
- package/src/index.browser.js +3 -0
- package/src/index.d.ts +4 -1
- package/src/index.js +4 -1
- package/src/plugins/README.md +7 -1
- package/src/plugins/component-import-discovery.d.ts +19 -0
- package/src/plugins/component-import-discovery.js +203 -0
- package/src/plugins/eco-component-meta-plugin.d.ts +3 -1
- package/src/plugins/eco-component-meta-plugin.js +101 -16
- package/src/plugins/tsconfig-import-resolver.d.ts +3 -1
- package/src/plugins/tsconfig-import-resolver.js +4 -2
- package/src/route-renderer/GRAPH.md +1 -1
- package/src/route-renderer/README.md +8 -0
- package/src/route-renderer/orchestration/foreign-child/foreign-subtree-execution.service.d.ts +8 -0
- package/src/route-renderer/orchestration/foreign-child/foreign-subtree-execution.service.js +9 -1
- package/src/route-renderer/orchestration/integration-renderer.d.ts +2 -2
- package/src/route-renderer/orchestration/integration-renderer.js +8 -9
- package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.d.ts +1 -4
- package/src/route-renderer/orchestration/ownership-graph/component-graph-collectors.js +0 -66
- package/src/route-renderer/orchestration/route-pipeline/route-render-orchestrator.js +5 -8
- package/src/route-renderer/page-loading/component-dependency-collection.d.ts +6 -2
- package/src/route-renderer/page-loading/component-dependency-collection.js +29 -5
- package/src/route-renderer/page-loading/file-scoped-dependency-components.d.ts +11 -1
- package/src/route-renderer/page-loading/file-scoped-dependency-components.js +40 -6
- package/src/route-renderer/page-loading/resolved-page-dependencies.d.ts +1 -2
- package/src/route-renderer/page-loading/resolved-page-dependencies.js +8 -7
- package/src/services/module-loading/page-module-import.service.d.ts +2 -0
- package/src/services/module-loading/page-module-import.service.js +2 -1
- package/src/static-site-generator/README.md +3 -1
- package/src/types/public-types.d.ts +1 -1
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { EcoPagesAppConfig } from '../../../types/internal-types.js';
|
|
2
2
|
import type { EcoComponent, ResolvedLazyTrigger } from '../../../types/public-types.js';
|
|
3
|
-
import type {
|
|
4
|
-
import type { AssetProcessingService, ProcessedAsset } from '../../../services/assets/asset-processing-service/index.js';
|
|
3
|
+
import type { ProcessedAsset } from '../../../services/assets/asset-processing-service/index.js';
|
|
5
4
|
export declare function collectIntegrationNamesFromGraph(components: (EcoComponent | Partial<EcoComponent>)[], currentIntegrationName: string): Set<string>;
|
|
6
5
|
export declare function collectResolvedLazyTriggersFromGraph(components: (EcoComponent | Partial<EcoComponent>)[], currentIntegrationName: string): ResolvedLazyTrigger[];
|
|
7
6
|
export declare function hasForeignChildDescendantsInGraph(component: EcoComponent, currentIntegrationName: string): boolean;
|
|
8
|
-
export declare function collectEagerSsrLazyScriptDefinitions(components: (EcoComponent | Partial<EcoComponent>)[]): AssetDefinition[];
|
|
9
7
|
export declare function collectUsedIntegrationDependenciesFromGraph(appConfig: EcoPagesAppConfig, components: (EcoComponent | Partial<EcoComponent>)[], currentIntegrationName: string): ProcessedAsset[];
|
|
10
|
-
export declare function buildEagerSsrLazyAssetsFromGraph(assetProcessingService: AssetProcessingService, components: (EcoComponent | Partial<EcoComponent>)[], currentIntegrationName: string): Promise<ProcessedAsset[]>;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { AssetFactory } from '../../../services/assets/asset-processing-service/index.js';
|
|
3
1
|
import { walkComponentGraph } from './component-graph.js';
|
|
4
2
|
import { getComponentIdentity } from '../../../eco/component-identity.js';
|
|
5
3
|
function toGraphRoots(components) {
|
|
@@ -51,63 +49,6 @@ export function hasForeignChildDescendantsInGraph(component, currentIntegrationN
|
|
|
51
49
|
});
|
|
52
50
|
return foundForeign;
|
|
53
51
|
}
|
|
54
|
-
export function collectEagerSsrLazyScriptDefinitions(components) {
|
|
55
|
-
const dependencies = [];
|
|
56
|
-
const seenKeys = new Set();
|
|
57
|
-
const normalizeAttributes = (attributes) => ({
|
|
58
|
-
type: 'module',
|
|
59
|
-
defer: '',
|
|
60
|
-
...(attributes ?? {}),
|
|
61
|
-
});
|
|
62
|
-
walkComponentGraph({
|
|
63
|
-
roots: toGraphRoots(components),
|
|
64
|
-
currentIntegrationName: '',
|
|
65
|
-
visitLayout: true,
|
|
66
|
-
onConfig: (config) => {
|
|
67
|
-
const componentFile = getComponentIdentity(config)?.file;
|
|
68
|
-
if (!componentFile || !config) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
const componentDir = path.dirname(componentFile);
|
|
72
|
-
for (const script of config.dependencies?.scripts ?? []) {
|
|
73
|
-
if (typeof script === 'string' || !script.lazy || script.ssr !== true) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
const attributes = normalizeAttributes(script.attributes);
|
|
77
|
-
if (script.content) {
|
|
78
|
-
const key = `content:${script.content}:${JSON.stringify(attributes)}`;
|
|
79
|
-
if (seenKeys.has(key)) {
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
seenKeys.add(key);
|
|
83
|
-
dependencies.push(AssetFactory.createContentScript({
|
|
84
|
-
position: 'head',
|
|
85
|
-
content: script.content,
|
|
86
|
-
attributes,
|
|
87
|
-
packageRole: 'dynamic-chunk',
|
|
88
|
-
}));
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
if (!script.src) {
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
const resolvedPath = path.resolve(componentDir, script.src);
|
|
95
|
-
const key = `file:${resolvedPath}:${JSON.stringify(attributes)}`;
|
|
96
|
-
if (seenKeys.has(key)) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
seenKeys.add(key);
|
|
100
|
-
dependencies.push(AssetFactory.createFileScript({
|
|
101
|
-
filepath: resolvedPath,
|
|
102
|
-
position: 'head',
|
|
103
|
-
attributes,
|
|
104
|
-
packageRole: 'dynamic-chunk',
|
|
105
|
-
}));
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
return dependencies;
|
|
110
|
-
}
|
|
111
52
|
export function collectUsedIntegrationDependenciesFromGraph(appConfig, components, currentIntegrationName) {
|
|
112
53
|
const integrationNames = collectIntegrationNamesFromGraph(components, currentIntegrationName);
|
|
113
54
|
const dependencies = [];
|
|
@@ -123,10 +64,3 @@ export function collectUsedIntegrationDependenciesFromGraph(appConfig, component
|
|
|
123
64
|
}
|
|
124
65
|
return dependencies;
|
|
125
66
|
}
|
|
126
|
-
export async function buildEagerSsrLazyAssetsFromGraph(assetProcessingService, components, currentIntegrationName) {
|
|
127
|
-
const dependencies = collectEagerSsrLazyScriptDefinitions(components);
|
|
128
|
-
if (dependencies.length === 0) {
|
|
129
|
-
return [];
|
|
130
|
-
}
|
|
131
|
-
return assetProcessingService.processDependencies(dependencies, `${currentIntegrationName}:ssr-lazy`);
|
|
132
|
-
}
|
|
@@ -2,7 +2,7 @@ import { collectHtmlCacheSourceDependencyPaths } from '../../../services/cache/h
|
|
|
2
2
|
import { getComponentIdentity } from '../../../eco/component-identity.js';
|
|
3
3
|
import { inspectUnresolvedMarkerArtifactHtml } from './marker-artifact.utils.js';
|
|
4
4
|
import { OwnershipValidationService, throwIfOwnershipInvalid, } from '../ownership-graph/ownership-validation.service.js';
|
|
5
|
-
import {
|
|
5
|
+
import { collectResolvedLazyTriggersFromGraph, collectUsedIntegrationDependenciesFromGraph, } from '../ownership-graph/component-graph-collectors.js';
|
|
6
6
|
import { buildGlobalInjectorAssets } from '../page-browser-graph/global-injector-assets.service.js';
|
|
7
7
|
import { mergePageBrowserGraphContributions } from '../page-browser-graph/page-browser-graph-contribution.merge.js';
|
|
8
8
|
import { PageBrowserGraphService } from '../page-browser-graph/page-browser-graph.service.js';
|
|
@@ -93,13 +93,10 @@ export class RouteRenderOrchestrator {
|
|
|
93
93
|
...collectUsedIntegrationDependenciesFromGraph(this.appConfig, componentsToResolve, adapter.name),
|
|
94
94
|
];
|
|
95
95
|
const triggers = collectResolvedLazyTriggersFromGraph(componentsToResolve, adapter.name);
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
buildEagerSsrLazyAssetsFromGraph(this.assetProcessingService, componentsToResolve, adapter.name),
|
|
101
|
-
]);
|
|
102
|
-
allDependencies.push(...globalAssets, ...eagerSsrLazyAssets);
|
|
96
|
+
const globalAssets = triggers.length > 0
|
|
97
|
+
? await buildGlobalInjectorAssets(this.appConfig, this.assetProcessingService, triggers, adapter.name)
|
|
98
|
+
: [];
|
|
99
|
+
allDependencies.push(...globalAssets);
|
|
103
100
|
const sourceDependencyPaths = collectHtmlCacheSourceDependencyPaths({
|
|
104
101
|
routeFile: routeOptions.file,
|
|
105
102
|
processedAssets: allDependencies,
|
|
@@ -30,8 +30,12 @@ type CollectComponentDependenciesOptions = {
|
|
|
30
30
|
* Walks component dependency trees and collects declared assets, module declarations,
|
|
31
31
|
* and lazy-script group metadata in one pass.
|
|
32
32
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* Explicit stylesheet declarations are collected first across the graph. Inferred
|
|
35
|
+
* stylesheets are read from component identity afterward and skipped when the same
|
|
36
|
+
* resolved path already has an explicit entry. The returned structures preserve both
|
|
37
|
+
* the flat asset list used by asset processing and the grouped lazy-trigger data used
|
|
38
|
+
* later during render output.
|
|
35
39
|
*/
|
|
36
40
|
export declare function collectComponentDependencies(options: CollectComponentDependenciesOptions): CollectedComponentDependencies;
|
|
37
41
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { assertEcoDeclaredComponent } from '../../eco/eco-declared-component.js';
|
|
3
3
|
import { getComponentIdentity } from '../../eco/component-identity.js';
|
|
4
|
+
import { getInferredStylesheets } from '../../eco/discovered-dependencies.js';
|
|
4
5
|
import { AssetFactory } from '../../services/assets/asset-processing-service/index.js';
|
|
5
6
|
import { extractEcopagesVirtualImports } from './ecopages-virtual-imports.js';
|
|
6
7
|
import { collectDeclaredAssetEntries } from './declared-asset-collection.js';
|
|
@@ -27,20 +28,27 @@ function pushUniqueDependency(keys, key, dependencies, dependency) {
|
|
|
27
28
|
return true;
|
|
28
29
|
}
|
|
29
30
|
function resolveDependencyPath(componentDir, pathUrl) {
|
|
30
|
-
return path.join(componentDir, pathUrl);
|
|
31
|
+
return path.isAbsolute(pathUrl) ? pathUrl : path.join(componentDir, pathUrl);
|
|
31
32
|
}
|
|
32
33
|
/**
|
|
33
34
|
* Walks component dependency trees and collects declared assets, module declarations,
|
|
34
35
|
* and lazy-script group metadata in one pass.
|
|
35
36
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* Explicit stylesheet declarations are collected first across the graph. Inferred
|
|
39
|
+
* stylesheets are read from component identity afterward and skipped when the same
|
|
40
|
+
* resolved path already has an explicit entry. The returned structures preserve both
|
|
41
|
+
* the flat asset list used by asset processing and the grouped lazy-trigger data used
|
|
42
|
+
* later during render output.
|
|
38
43
|
*/
|
|
39
44
|
export function collectComponentDependencies(options) {
|
|
40
45
|
const { components, integrationName, resolveLazyScripts, createEcopagesJsxLazyEntryName, isEcopagesJsxIntegration, errors, } = options;
|
|
41
46
|
const dependencies = [];
|
|
42
47
|
const lazyScriptsByConfig = new Map();
|
|
43
48
|
const lazyDependencyKeys = new Set();
|
|
49
|
+
const visited = new Set();
|
|
50
|
+
const inferredStyles = [];
|
|
51
|
+
const explicitStylePaths = new Set();
|
|
44
52
|
for (const component of components) {
|
|
45
53
|
if (!component)
|
|
46
54
|
continue;
|
|
@@ -54,13 +62,22 @@ export function collectComponentDependencies(options) {
|
|
|
54
62
|
* Recursively visits one component config and its declared child dependencies.
|
|
55
63
|
*/
|
|
56
64
|
const collect = (config) => {
|
|
57
|
-
if (!config)
|
|
65
|
+
if (!config || visited.has(config))
|
|
58
66
|
return;
|
|
67
|
+
visited.add(config);
|
|
59
68
|
const file = getComponentIdentity(config)?.file;
|
|
60
69
|
if (!file)
|
|
61
70
|
return;
|
|
62
71
|
const dir = path.dirname(file);
|
|
63
72
|
const dependenciesConfig = config.dependencies;
|
|
73
|
+
const explicitStyles = dependenciesConfig?.stylesheets ?? [];
|
|
74
|
+
for (const style of explicitStyles) {
|
|
75
|
+
const src = typeof style === 'string' ? style : style.src;
|
|
76
|
+
if (src)
|
|
77
|
+
explicitStylePaths.add(resolveDependencyPath(dir, src));
|
|
78
|
+
}
|
|
79
|
+
for (const src of getInferredStylesheets(config))
|
|
80
|
+
inferredStyles.push({ dir, src });
|
|
64
81
|
const registerLazyScript = ({ lazy, lazyKey, fallbackUrl, }) => {
|
|
65
82
|
let grouped = lazyScriptsByConfig.get(config);
|
|
66
83
|
if (!grouped) {
|
|
@@ -73,7 +90,7 @@ export function collectComponentDependencies(options) {
|
|
|
73
90
|
grouped.set(triggerKey, existing);
|
|
74
91
|
};
|
|
75
92
|
collectDeclaredAssetEntries({
|
|
76
|
-
stylesheetEntries:
|
|
93
|
+
stylesheetEntries: explicitStyles,
|
|
77
94
|
scriptEntries: dependenciesConfig?.scripts ?? [],
|
|
78
95
|
componentDir: dir,
|
|
79
96
|
dependencies,
|
|
@@ -125,6 +142,13 @@ export function collectComponentDependencies(options) {
|
|
|
125
142
|
});
|
|
126
143
|
}));
|
|
127
144
|
}
|
|
145
|
+
for (const { dir, src } of inferredStyles) {
|
|
146
|
+
const filepath = resolveDependencyPath(dir, src);
|
|
147
|
+
if (explicitStylePaths.has(filepath))
|
|
148
|
+
continue;
|
|
149
|
+
explicitStylePaths.add(filepath);
|
|
150
|
+
dependencies.push(AssetFactory.createFileStylesheet({ filepath, position: 'head', attributes: { rel: 'stylesheet' } }));
|
|
151
|
+
}
|
|
128
152
|
return {
|
|
129
153
|
dependencies,
|
|
130
154
|
lazyScriptsByConfig,
|
|
@@ -21,12 +21,21 @@ export declare function collectFileScopedDependencyComponents(options: {
|
|
|
21
21
|
integrationName: string;
|
|
22
22
|
dependencies: EcoComponentDependencies;
|
|
23
23
|
}): Array<EcoComponent | Partial<EcoComponent>>;
|
|
24
|
+
/**
|
|
25
|
+
* Expands a page dependency result into collector roots, retaining each contribution's owner.
|
|
26
|
+
*/
|
|
27
|
+
export declare function collectPageDependencyComponents(options: {
|
|
28
|
+
result: PageDependenciesResult;
|
|
29
|
+
fallbackOwnerFile: string;
|
|
30
|
+
integrationName: string;
|
|
31
|
+
}): Array<EcoComponent | Partial<EcoComponent>>;
|
|
24
32
|
export type CollectComponentConfigFilePathsOptions = {
|
|
25
33
|
additionalPaths?: ReadonlyArray<string>;
|
|
26
34
|
includeLayouts?: boolean;
|
|
35
|
+
includeStylesheets?: boolean;
|
|
27
36
|
};
|
|
28
37
|
/**
|
|
29
|
-
* Walks component configs and collects
|
|
38
|
+
* Walks component configs and collects identity files, stylesheets, and discovered barrel hops.
|
|
30
39
|
*/
|
|
31
40
|
export declare function collectComponentConfigFilePaths(components: ReadonlyArray<EcoComponent | Partial<EcoComponent> | undefined>, options?: CollectComponentConfigFilePathsOptions): Set<string>;
|
|
32
41
|
/**
|
|
@@ -39,4 +48,5 @@ export declare function collectDependencyWatchPaths(ownerFile: string, component
|
|
|
39
48
|
export declare function splitPageDependenciesResult(result: PageDependenciesResult): {
|
|
40
49
|
dependencies: EcoComponentDependencies;
|
|
41
50
|
ownerFile?: string;
|
|
51
|
+
contributions?: PageDependenciesResult['contributions'];
|
|
42
52
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { rapidhash } from '../../utils/hash.js';
|
|
3
3
|
import { bindComponentIdentity, getComponentIdentity } from '../../eco/component-identity.js';
|
|
4
|
+
import { getDiscoveredWatchFiles, getInferredStylesheets } from '../../eco/discovered-dependencies.js';
|
|
5
|
+
import { listFileOwnedDependencyContributions } from '../../eco/page-dependency-contributions.js';
|
|
4
6
|
/**
|
|
5
7
|
* Attaches canonical file-backed identity to one component config.
|
|
6
8
|
*/
|
|
@@ -43,7 +45,22 @@ export function collectFileScopedDependencyComponents(options) {
|
|
|
43
45
|
return components;
|
|
44
46
|
}
|
|
45
47
|
/**
|
|
46
|
-
*
|
|
48
|
+
* Expands a page dependency result into collector roots, retaining each contribution's owner.
|
|
49
|
+
*/
|
|
50
|
+
export function collectPageDependencyComponents(options) {
|
|
51
|
+
const components = [];
|
|
52
|
+
for (const contribution of listFileOwnedDependencyContributions(options.result)) {
|
|
53
|
+
const { ownerFile, ...dependencies } = contribution;
|
|
54
|
+
components.push(...collectFileScopedDependencyComponents({
|
|
55
|
+
ownerFile: ownerFile ?? options.fallbackOwnerFile,
|
|
56
|
+
integrationName: options.integrationName,
|
|
57
|
+
dependencies,
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
return components;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Walks component configs and collects identity files, stylesheets, and discovered barrel hops.
|
|
47
64
|
*/
|
|
48
65
|
export function collectComponentConfigFilePaths(components, options) {
|
|
49
66
|
const files = new Set();
|
|
@@ -60,11 +77,24 @@ export function collectComponentConfigFilePaths(components, options) {
|
|
|
60
77
|
return;
|
|
61
78
|
}
|
|
62
79
|
const resolved = path.resolve(file);
|
|
63
|
-
if (visited.has(
|
|
80
|
+
if (visited.has(config)) {
|
|
64
81
|
return;
|
|
65
82
|
}
|
|
66
|
-
visited.add(
|
|
83
|
+
visited.add(config);
|
|
67
84
|
files.add(resolved);
|
|
85
|
+
for (const style of options?.includeStylesheets ? (config.dependencies?.stylesheets ?? []) : []) {
|
|
86
|
+
const src = typeof style === 'string' ? style : style.src;
|
|
87
|
+
if (src)
|
|
88
|
+
files.add(path.resolve(path.dirname(resolved), src));
|
|
89
|
+
}
|
|
90
|
+
if (options?.includeStylesheets) {
|
|
91
|
+
for (const src of getInferredStylesheets(config)) {
|
|
92
|
+
files.add(path.resolve(path.dirname(resolved), src));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const watchFile of getDiscoveredWatchFiles(config)) {
|
|
96
|
+
files.add(path.resolve(watchFile));
|
|
97
|
+
}
|
|
68
98
|
for (const dependency of config.dependencies?.components ?? []) {
|
|
69
99
|
visit(dependency?.config);
|
|
70
100
|
}
|
|
@@ -83,12 +113,16 @@ export function collectComponentConfigFilePaths(components, options) {
|
|
|
83
113
|
* Collects source files that should invalidate a per-instance browser graph entry.
|
|
84
114
|
*/
|
|
85
115
|
export function collectDependencyWatchPaths(ownerFile, components) {
|
|
86
|
-
return Array.from(collectComponentConfigFilePaths(components, { additionalPaths: [ownerFile] }));
|
|
116
|
+
return Array.from(collectComponentConfigFilePaths(components, { additionalPaths: [ownerFile], includeStylesheets: true }));
|
|
87
117
|
}
|
|
88
118
|
/**
|
|
89
119
|
* Separates optional owner metadata from a resolved page dependency bag.
|
|
90
120
|
*/
|
|
91
121
|
export function splitPageDependenciesResult(result) {
|
|
92
|
-
const { ownerFile, ...dependencies } = result;
|
|
93
|
-
return {
|
|
122
|
+
const { ownerFile, contributions, ...dependencies } = result;
|
|
123
|
+
return {
|
|
124
|
+
dependencies,
|
|
125
|
+
ownerFile,
|
|
126
|
+
...(contributions ? { contributions } : {}),
|
|
127
|
+
};
|
|
94
128
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { EcoComponent, PageBrowserGraphContribution, PageBrowserGraphContributionContext } from '../../types/public-types.js';
|
|
2
|
-
import { collectFileScopedDependencyComponents } from './file-scoped-dependency-components.js';
|
|
3
2
|
export type ResolvedPageDependencies = {
|
|
4
3
|
ownerFile: string;
|
|
5
4
|
components: ReadonlyArray<EcoComponent | Partial<EcoComponent>>;
|
|
6
5
|
contribution?: PageBrowserGraphContribution;
|
|
7
6
|
};
|
|
8
|
-
export type ResolvePageDependenciesContribution = (
|
|
7
|
+
export type ResolvePageDependenciesContribution = (components: ReadonlyArray<EcoComponent | Partial<EcoComponent>>, ownerFile: string) => Promise<PageBrowserGraphContribution | undefined>;
|
|
9
8
|
/**
|
|
10
9
|
* Resolves `eco.page().dependencies()` once for one graph contribution context.
|
|
11
10
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { listFileOwnedDependencyContributions } from '../../eco/page-dependency-contributions.js';
|
|
2
|
+
import { collectPageDependencyComponents } from './file-scoped-dependency-components.js';
|
|
2
3
|
/**
|
|
3
4
|
* Resolves `eco.page().dependencies()` once for one graph contribution context.
|
|
4
5
|
*/
|
|
@@ -16,12 +17,12 @@ export async function resolvePageDependenciesFromContext(context, integrationNam
|
|
|
16
17
|
if (!dependenciesResult) {
|
|
17
18
|
return undefined;
|
|
18
19
|
}
|
|
19
|
-
const
|
|
20
|
-
const resolvedOwnerFile = ownerFile ?? context.file;
|
|
21
|
-
const components =
|
|
22
|
-
|
|
20
|
+
const contributions = listFileOwnedDependencyContributions(dependenciesResult);
|
|
21
|
+
const resolvedOwnerFile = contributions.length === 1 ? (contributions[0]?.ownerFile ?? context.file) : context.file;
|
|
22
|
+
const components = collectPageDependencyComponents({
|
|
23
|
+
result: dependenciesResult,
|
|
24
|
+
fallbackOwnerFile: context.file,
|
|
23
25
|
integrationName,
|
|
24
|
-
dependencies,
|
|
25
26
|
});
|
|
26
27
|
if (components.length === 0) {
|
|
27
28
|
return {
|
|
@@ -29,7 +30,7 @@ export async function resolvePageDependenciesFromContext(context, integrationNam
|
|
|
29
30
|
components,
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
|
-
const contribution = await materializeContribution(
|
|
33
|
+
const contribution = await materializeContribution(components, resolvedOwnerFile);
|
|
33
34
|
return {
|
|
34
35
|
ownerFile: resolvedOwnerFile,
|
|
35
36
|
components,
|
|
@@ -16,6 +16,8 @@ interface PageModuleImportBaseOptions {
|
|
|
16
16
|
export interface PageModuleBuildImportOptions extends PageModuleImportBaseOptions {
|
|
17
17
|
rootDir: string;
|
|
18
18
|
outdir: string;
|
|
19
|
+
/** Use the server build pipeline even when a development host can load source modules. */
|
|
20
|
+
forceBuild?: boolean;
|
|
19
21
|
buildExecutor?: BuildExecutor;
|
|
20
22
|
splitting?: boolean;
|
|
21
23
|
externalPackages?: boolean;
|
|
@@ -72,7 +72,8 @@ export class PageModuleImportService {
|
|
|
72
72
|
async importModule(options) {
|
|
73
73
|
const { filePath } = options;
|
|
74
74
|
const fileHash = this.dependencies.hashFile(filePath);
|
|
75
|
-
const hostModuleLoader =
|
|
75
|
+
const hostModuleLoader = !options.forceBuild &&
|
|
76
|
+
typeof Bun === 'undefined' &&
|
|
76
77
|
process.env.NODE_ENV === 'development' &&
|
|
77
78
|
this.dependencies.canLoadSourceModuleFromHost(filePath)
|
|
78
79
|
? this.dependencies.getHostModuleLoader()
|
|
@@ -58,10 +58,12 @@ Integrations may implement:
|
|
|
58
58
|
- `beforeStaticExport(context)` — runs after unified-graph prebuild, before page rendering
|
|
59
59
|
- `afterStaticExport(context)` — runs in a `finally` block after generation completes
|
|
60
60
|
|
|
61
|
-
When `appConfig.sitemap.enabled` is true, `sitemap.xml` is written **after** `afterStaticExport` so integration-generated URLs can be listed via `extraUrls`.
|
|
61
|
+
When `appConfig.sitemap.enabled` is true, `sitemap.xml` is written **after** `afterStaticExport` so integration-generated URLs can be listed via `extraUrls`. Development (`ecopages dev`) does not emit this file.
|
|
62
62
|
|
|
63
63
|
Sitemap eligibility is decided during successful page export (`activeStaticPathnames` plus `robots.index !== false`, fail-closed on metadata errors). `resolveSitemapLocations` then applies `exclude` and appends `extraUrls`.
|
|
64
64
|
|
|
65
65
|
`StaticExportContext.routes` is the unfiltered static-generation route list. Sitemap filtering is applied separately.
|
|
66
66
|
|
|
67
67
|
See `StaticExportContext` in `static-export-context.ts`.
|
|
68
|
+
|
|
69
|
+
User-facing guide: [Sitemap](https://github.com/ecopages/ecopages/blob/main/apps/docs/src/content/docs/core/sitemap.mdx) in the docs app.
|
|
@@ -11,7 +11,7 @@ import type { InteractionEventsString as ScriptsInjectorInteractionEventsString
|
|
|
11
11
|
import type { EntrypointDependencyGraph } from '../services/runtime-state/entrypoint-dependency-graph.service.js';
|
|
12
12
|
import type { DevTransformBundleContributor } from '../dev/transform-server/types.js';
|
|
13
13
|
export type { EcoPagesAppConfig } from './internal-types.js';
|
|
14
|
-
export type { EcoPageComponent, GetPageDependencies, GetPageDependenciesContext, PageDependenciesResult, } from '../eco/eco.types.js';
|
|
14
|
+
export type { EcoPageComponent, FileOwnedDependencyContribution, GetPageDependencies, GetPageDependenciesContext, PageDependenciesResult, } from '../eco/eco.types.js';
|
|
15
15
|
export type { ProcessedAsset } from '../services/assets/asset-processing-service/assets.types.js';
|
|
16
16
|
/**
|
|
17
17
|
* Runtime-agnostic incoming WebSocket frame.
|