@ecopages/core 0.2.0-beta.7 → 0.2.0-beta.9
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/package.json +27 -3
- package/src/adapters/abstract/application-adapter.d.ts +12 -1
- package/src/adapters/abstract/application-adapter.js +13 -0
- package/src/adapters/abstract/server-adapter.d.ts +3 -0
- package/src/adapters/bun/client-bridge.d.ts +1 -0
- package/src/adapters/bun/client-bridge.js +3 -0
- package/src/adapters/bun/create-app.d.ts +2 -0
- package/src/adapters/bun/create-app.js +28 -9
- package/src/adapters/bun/server-adapter.d.ts +13 -0
- package/src/adapters/bun/server-adapter.js +29 -4
- package/src/adapters/create-app.d.ts +13 -0
- package/src/adapters/create-app.js +10 -1
- package/src/adapters/node/create-app.d.ts +1 -0
- package/src/adapters/node/create-app.js +17 -7
- package/src/adapters/node/node-client-bridge.d.ts +1 -0
- package/src/adapters/node/node-client-bridge.js +3 -0
- package/src/adapters/node/server-adapter.d.ts +10 -13
- package/src/adapters/node/server-adapter.js +37 -82
- package/src/adapters/node/static-content-server.d.ts +1 -0
- package/src/adapters/node/static-content-server.js +3 -0
- package/src/adapters/shared/copy-runtime-public-dir.d.ts +6 -0
- package/src/adapters/shared/copy-runtime-public-dir.js +24 -0
- package/src/adapters/shared/runtime-app-bootstrap.d.ts +0 -1
- package/src/adapters/shared/runtime-app-bootstrap.js +1 -6
- package/src/adapters/shared/server-static-builder.d.ts +4 -6
- package/src/adapters/shared/server-static-builder.js +90 -34
- package/src/adapters/shared/shared-hmr-manager.d.ts +1 -0
- package/src/adapters/shared/shared-hmr-manager.js +15 -2
- package/src/build/README.md +44 -4
- package/src/build/build-adapter.d.ts +27 -2
- package/src/build/build-adapter.js +75 -32
- package/src/build/build-input-fingerprint.d.ts +28 -0
- package/src/build/build-input-fingerprint.js +31 -0
- package/src/build/jsx-ownership-plugins.d.ts +10 -0
- package/src/build/jsx-ownership-plugins.js +17 -0
- package/src/build/pages-unified-graph-build.d.ts +31 -0
- package/src/build/pages-unified-graph-build.js +208 -0
- package/src/build/parallel-build-executor.d.ts +21 -0
- package/src/build/parallel-build-executor.js +52 -0
- package/src/build/rolldown-adapter-helpers.js +7 -1
- package/src/build/rolldown-build-adapter.js +2 -0
- package/src/build/rolldown-build-invocation-metrics.d.ts +12 -0
- package/src/build/rolldown-build-invocation-metrics.js +43 -0
- package/src/build/rolldown-dev-build-adapter.d.ts +2 -2
- package/src/build/rolldown-dev-build-adapter.js +30 -14
- package/src/build/rolldown-plugin-bridge.d.ts +10 -1
- package/src/build/rolldown-plugin-bridge.js +17 -5
- package/src/build/rolldown-source-transform-pass.d.ts +15 -0
- package/src/build/rolldown-source-transform-pass.js +58 -0
- package/src/build/runtime-build-executor.d.ts +7 -13
- package/src/build/runtime-build-executor.js +31 -7
- package/src/build/server-entry-build-cache.d.ts +44 -0
- package/src/build/server-entry-build-cache.js +169 -0
- package/src/config/config-builder.d.ts +11 -1
- package/src/config/config-builder.js +11 -1
- package/src/hmr/hmr.test.e2e.js +15 -4
- package/src/plugins/integration-plugin.d.ts +19 -8
- package/src/plugins/integration-plugin.js +7 -2
- package/src/plugins/processor.d.ts +5 -0
- package/src/plugins/processor.js +7 -0
- package/src/plugins/source-transform.d.ts +31 -0
- package/src/plugins/source-transform.js +23 -1
- package/src/route-renderer/GRAPH.md +4 -4
- package/src/route-renderer/README.md +6 -5
- package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +1 -3
- package/src/route-renderer/orchestration/integration-renderer.d.ts +10 -2
- package/src/route-renderer/orchestration/integration-renderer.js +32 -12
- package/src/route-renderer/orchestration/render-output.utils.d.ts +2 -0
- package/src/route-renderer/orchestration/render-output.utils.js +4 -0
- package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +2 -2
- package/src/route-renderer/orchestration/route-render-orchestrator.js +17 -16
- package/src/router/client/navigation-coordinator.js +10 -0
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -0
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +27 -7
- package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
- package/src/services/assets/browser-bundle.service.d.ts +3 -1
- package/src/services/assets/browser-bundle.service.js +14 -5
- package/src/services/html/html-transformer.service.d.ts +1 -1
- package/src/services/html/html-transformer.service.js +4 -4
- package/src/services/invalidation/development-invalidation.service.d.ts +10 -1
- package/src/services/invalidation/development-invalidation.service.js +29 -0
- package/src/services/module-loading/README.md +49 -0
- package/src/services/module-loading/app-server-module-transpiler.service.js +4 -17
- package/src/services/module-loading/page-module-import.service.d.ts +4 -1
- package/src/services/module-loading/page-module-import.service.js +52 -29
- package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
- package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
- package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
- package/src/services/module-loading/route-module-build-cache.js +38 -0
- package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
- package/src/services/module-loading/route-module-build-cache.store.js +203 -0
- package/src/services/module-loading/route-module-build-manifest.d.ts +61 -0
- package/src/services/module-loading/route-module-build-manifest.js +124 -0
- package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
- package/src/services/module-loading/route-module-dependency-hasher.js +121 -0
- package/src/services/module-loading/server-module-transpiler.service.js +1 -1
- package/src/static-site-generator/README.md +33 -0
- package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
- package/src/static-site-generator/static-build-invalidation.js +78 -0
- package/src/static-site-generator/static-export-context.d.ts +22 -0
- package/src/static-site-generator/static-export-context.js +0 -0
- package/src/static-site-generator/static-site-generator.d.ts +17 -8
- package/src/static-site-generator/static-site-generator.js +176 -62
- package/src/types/internal-types.d.ts +8 -0
- package/src/utils/parse-cli-args.d.ts +1 -0
- package/src/utils/parse-cli-args.js +3 -0
- package/src/watchers/project-watcher.d.ts +8 -0
- package/src/watchers/project-watcher.js +32 -12
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { mergeBrowserRuntimeManifests } from "./browser-runtime-manifest.js";
|
|
2
2
|
import { normalizeNodeRuntimeBuildOutputs } from "./runtime-build-output-normalizer.js";
|
|
3
|
-
import { createForeignJsxOverridePlugin } from "../plugins/foreign-jsx-override-plugin.js";
|
|
4
3
|
import {
|
|
5
4
|
createAppBuildManifest,
|
|
6
5
|
getBrowserBuildPlugins,
|
|
7
6
|
getServerBuildPlugins
|
|
8
7
|
} from "./build-manifest.js";
|
|
8
|
+
import { getAppSourceTransforms } from "../plugins/source-transform.js";
|
|
9
|
+
import { getJsxOwnershipPlugins } from "./jsx-ownership-plugins.js";
|
|
9
10
|
import { createRolldownBuildAdapter } from "./rolldown-build-adapter.js";
|
|
10
11
|
import { createRolldownDevBuildAdapter } from "./rolldown-dev-build-adapter.js";
|
|
12
|
+
import { appLogger } from "../global/app-logger.js";
|
|
11
13
|
function mergeBuildExecutorPlugins(existing, appPlugins) {
|
|
12
14
|
if (!existing || existing.length === 0) {
|
|
13
15
|
return appPlugins;
|
|
@@ -96,7 +98,7 @@ function setAppBuildAdapter(appConfig, buildAdapter) {
|
|
|
96
98
|
}
|
|
97
99
|
function getAppBuildManifest(appConfig) {
|
|
98
100
|
return appConfig.runtime?.buildManifest ?? createAppBuildManifest({
|
|
99
|
-
loaderPlugins: Array.from(appConfig.loaders
|
|
101
|
+
loaderPlugins: Array.from(appConfig.loaders?.values() ?? [])
|
|
100
102
|
});
|
|
101
103
|
}
|
|
102
104
|
function setAppBuildManifest(appConfig, buildManifest) {
|
|
@@ -143,27 +145,55 @@ async function collectConfiguredAppBuildManifestContributions(appConfig) {
|
|
|
143
145
|
};
|
|
144
146
|
}
|
|
145
147
|
async function setupAppRuntimePlugins(options) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
if (options.appConfig.runtime?.runtimeAssetsPrepared) {
|
|
149
|
+
appLogger.debug("Skipped setupAppRuntimePlugins: runtime assets already prepared");
|
|
150
|
+
for (const loader of options.appConfig.loaders.values()) {
|
|
151
|
+
options.onRuntimePlugin?.(loader);
|
|
152
|
+
}
|
|
153
|
+
for (const processor of options.appConfig.processors.values()) {
|
|
154
|
+
if (processor.plugins) {
|
|
155
|
+
for (const plugin of processor.plugins) {
|
|
156
|
+
options.onRuntimePlugin?.(plugin);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
for (const integration of options.appConfig.integrations) {
|
|
161
|
+
for (const plugin of integration.plugins) {
|
|
153
162
|
options.onRuntimePlugin?.(plugin);
|
|
154
163
|
}
|
|
155
164
|
}
|
|
165
|
+
return;
|
|
156
166
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
integration.setHmrManager(options.hmrManager);
|
|
167
|
+
appLogger.debugTime("setupAppRuntimePlugins");
|
|
168
|
+
try {
|
|
169
|
+
for (const loader of options.appConfig.loaders.values()) {
|
|
170
|
+
options.onRuntimePlugin?.(loader);
|
|
162
171
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
172
|
+
for (const processor of options.appConfig.processors.values()) {
|
|
173
|
+
await processor.setup();
|
|
174
|
+
if (processor.plugins) {
|
|
175
|
+
for (const plugin of processor.plugins) {
|
|
176
|
+
options.onRuntimePlugin?.(plugin);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
166
179
|
}
|
|
180
|
+
for (const integration of options.appConfig.integrations) {
|
|
181
|
+
integration.setConfig(options.appConfig);
|
|
182
|
+
integration.setRuntimeOrigin(options.runtimeOrigin);
|
|
183
|
+
if (options.hmrManager) {
|
|
184
|
+
integration.setHmrManager(options.hmrManager);
|
|
185
|
+
}
|
|
186
|
+
await integration.setup();
|
|
187
|
+
for (const plugin of integration.plugins) {
|
|
188
|
+
options.onRuntimePlugin?.(plugin);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
options.appConfig.runtime = {
|
|
192
|
+
...options.appConfig.runtime ?? {},
|
|
193
|
+
runtimeAssetsPrepared: true
|
|
194
|
+
};
|
|
195
|
+
} finally {
|
|
196
|
+
appLogger.debugTimeEnd("setupAppRuntimePlugins");
|
|
167
197
|
}
|
|
168
198
|
}
|
|
169
199
|
function getAppServerBuildPlugins(appConfig) {
|
|
@@ -171,24 +201,20 @@ function getAppServerBuildPlugins(appConfig) {
|
|
|
171
201
|
}
|
|
172
202
|
function getAppBrowserBuildPlugins(appConfig) {
|
|
173
203
|
const manifest = getAppBuildManifest(appConfig);
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
function collectJsxOwnershipPlugins(appConfig) {
|
|
178
|
-
const jsxExtensions = (appConfig.integrations ?? []).filter((integration) => integration.jsxImportSource).flatMap(
|
|
179
|
-
(integration) => integration.extensions.filter((extension) => extension.endsWith(".tsx") || extension.endsWith(".jsx")).map((extension) => ({ integration, extension }))
|
|
180
|
-
).sort((left, right) => right.extension.length - left.extension.length);
|
|
181
|
-
return jsxExtensions.map(
|
|
182
|
-
({ integration, extension }) => createForeignJsxOverridePlugin({
|
|
183
|
-
hostJsxImportSource: integration.jsxImportSource,
|
|
184
|
-
foreignExtensions: [extension],
|
|
185
|
-
excludeExtensions: jsxExtensions.filter((candidate) => candidate.extension.length > extension.length).filter((candidate) => candidate.extension.endsWith(extension)).map((candidate) => candidate.extension),
|
|
186
|
-
name: `ecopages-jsx-ownership-${integration.name}-${extension.replace(/[^a-zA-Z0-9]+/g, "-")}`
|
|
187
|
-
})
|
|
204
|
+
const sourceTransformNames = new Set(getAppSourceTransforms(appConfig).map((transform) => transform.name));
|
|
205
|
+
const browserPlugins = getBrowserBuildPlugins(manifest).filter(
|
|
206
|
+
(plugin) => !sourceTransformNames.has(plugin.name)
|
|
188
207
|
);
|
|
208
|
+
return [...browserPlugins, ...getJsxOwnershipPlugins(appConfig)];
|
|
189
209
|
}
|
|
190
210
|
function getAppBuildExecutor(appConfig) {
|
|
191
|
-
return appConfig.runtime?.buildExecutor ?? getAppBuildAdapter(appConfig);
|
|
211
|
+
return appConfig.runtime?.routeModuleBuildExecutor ?? appConfig.runtime?.buildExecutor ?? getAppBuildAdapter(appConfig);
|
|
212
|
+
}
|
|
213
|
+
function getAppHmrBuildExecutor(appConfig) {
|
|
214
|
+
return appConfig.runtime?.hmrBuildExecutor ?? getAppBuildExecutor(appConfig);
|
|
215
|
+
}
|
|
216
|
+
function getAppRouteModuleBuildExecutor(appConfig) {
|
|
217
|
+
return appConfig.runtime?.routeModuleBuildExecutor ?? getAppBuildExecutor(appConfig);
|
|
192
218
|
}
|
|
193
219
|
function setAppBuildExecutor(appConfig, buildExecutor) {
|
|
194
220
|
appConfig.runtime = {
|
|
@@ -196,6 +222,19 @@ function setAppBuildExecutor(appConfig, buildExecutor) {
|
|
|
196
222
|
buildExecutor
|
|
197
223
|
};
|
|
198
224
|
}
|
|
225
|
+
function setAppHmrBuildExecutor(appConfig, buildExecutor) {
|
|
226
|
+
appConfig.runtime = {
|
|
227
|
+
...appConfig.runtime ?? {},
|
|
228
|
+
hmrBuildExecutor: buildExecutor
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function setAppRouteModuleBuildExecutor(appConfig, buildExecutor) {
|
|
232
|
+
appConfig.runtime = {
|
|
233
|
+
...appConfig.runtime ?? {},
|
|
234
|
+
routeModuleBuildExecutor: buildExecutor,
|
|
235
|
+
buildExecutor
|
|
236
|
+
};
|
|
237
|
+
}
|
|
199
238
|
function build(options, executor = defaultRolldownBuildAdapter) {
|
|
200
239
|
return executor.build(options).then((result) => {
|
|
201
240
|
if (result.success) {
|
|
@@ -228,6 +267,8 @@ export {
|
|
|
228
267
|
getAppBuildExecutor,
|
|
229
268
|
getAppBuildManifest,
|
|
230
269
|
getAppBuildOwnership,
|
|
270
|
+
getAppHmrBuildExecutor,
|
|
271
|
+
getAppRouteModuleBuildExecutor,
|
|
231
272
|
getAppServerBuildPlugins,
|
|
232
273
|
getAppTranspileOptions,
|
|
233
274
|
getBuildAdapterOwnership,
|
|
@@ -237,6 +278,8 @@ export {
|
|
|
237
278
|
setAppBuildExecutor,
|
|
238
279
|
setAppBuildManifest,
|
|
239
280
|
setAppBuildOwnership,
|
|
281
|
+
setAppHmrBuildExecutor,
|
|
282
|
+
setAppRouteModuleBuildExecutor,
|
|
240
283
|
setupAppRuntimePlugins,
|
|
241
284
|
updateAppBuildManifest,
|
|
242
285
|
withBuildExecutorPlugins
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { IntegrationPlugin } from '../plugins/integration-plugin.js';
|
|
2
|
+
import type { Processor } from '../plugins/processor.js';
|
|
3
|
+
import type { EcoPagesAppConfig } from '../types/internal-types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Optional contributor surface for build-time cache invalidation.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Processors and integrations may override {@link didChange} to report that
|
|
9
|
+
* their build inputs changed independently of route source files.
|
|
10
|
+
*/
|
|
11
|
+
export interface BuildInputChangeContributor {
|
|
12
|
+
/**
|
|
13
|
+
* Returns `true` when this contributor's build inputs changed since the last
|
|
14
|
+
* persisted incremental build metadata was written.
|
|
15
|
+
*/
|
|
16
|
+
didChange?(): boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Returns whether a processor or integration signals changed build inputs. */
|
|
19
|
+
export declare function didBuildInputContributorChange(contributor: BuildInputChangeContributor): boolean;
|
|
20
|
+
/** Hashes the app's eco.config.ts file when present. */
|
|
21
|
+
export declare function hashAppConfigFile(appConfig: EcoPagesAppConfig): string;
|
|
22
|
+
/** Fingerprints processor/integration build-input state for cache invalidation. */
|
|
23
|
+
export declare function createBuildInputsFingerprint(appConfig: EcoPagesAppConfig): string;
|
|
24
|
+
/** Returns true when any processor or integration reports changed build inputs. */
|
|
25
|
+
export declare function haveBuildInputsChanged(appConfig: EcoPagesAppConfig): boolean;
|
|
26
|
+
/** Collects every processor and integration that can invalidate incremental builds. */
|
|
27
|
+
export declare function collectBuildInputContributors(appConfig: EcoPagesAppConfig): BuildInputChangeContributor[];
|
|
28
|
+
export type { Processor, IntegrationPlugin };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { fileSystem } from "@ecopages/file-system";
|
|
2
|
+
function didBuildInputContributorChange(contributor) {
|
|
3
|
+
return contributor.didChange?.() === true;
|
|
4
|
+
}
|
|
5
|
+
function hashAppConfigFile(appConfig) {
|
|
6
|
+
const configPath = appConfig.absolutePaths?.config;
|
|
7
|
+
if (!configPath || !fileSystem.exists(configPath)) {
|
|
8
|
+
return "missing";
|
|
9
|
+
}
|
|
10
|
+
return fileSystem.hash(configPath);
|
|
11
|
+
}
|
|
12
|
+
function createBuildInputsFingerprint(appConfig) {
|
|
13
|
+
const changedContributors = [
|
|
14
|
+
...Array.from(appConfig.processors?.values() ?? []).filter((processor) => didBuildInputContributorChange(processor)).map((processor) => `processor:${processor.getName()}`),
|
|
15
|
+
...(appConfig.integrations ?? []).filter((integration) => didBuildInputContributorChange(integration)).map((integration) => `integration:${integration.name}`)
|
|
16
|
+
];
|
|
17
|
+
return changedContributors.length > 0 ? changedContributors.sort().join("|") : "stable";
|
|
18
|
+
}
|
|
19
|
+
function haveBuildInputsChanged(appConfig) {
|
|
20
|
+
return createBuildInputsFingerprint(appConfig) !== "stable";
|
|
21
|
+
}
|
|
22
|
+
function collectBuildInputContributors(appConfig) {
|
|
23
|
+
return [...Array.from(appConfig.processors?.values() ?? []), ...appConfig.integrations ?? []];
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
collectBuildInputContributors,
|
|
27
|
+
createBuildInputsFingerprint,
|
|
28
|
+
didBuildInputContributorChange,
|
|
29
|
+
hashAppConfigFile,
|
|
30
|
+
haveBuildInputsChanged
|
|
31
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { EcoBuildPlugin } from './build-types.js';
|
|
2
|
+
import type { EcoPagesAppConfig } from '../types/internal-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Foreign JSX override plugins for mixed-integration apps (Kita + React, etc.).
|
|
5
|
+
*
|
|
6
|
+
* Each plugin rewrites files for one `(integration, extension)` pair with a
|
|
7
|
+
* `@jsxImportSource` pragma so the bundler compiles against the owning runtime.
|
|
8
|
+
* Extensions are sorted longest-first so `.page.react.tsx` wins over `.tsx`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getJsxOwnershipPlugins(appConfig: EcoPagesAppConfig): EcoBuildPlugin[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createForeignJsxOverridePlugin } from "../plugins/foreign-jsx-override-plugin.js";
|
|
2
|
+
function getJsxOwnershipPlugins(appConfig) {
|
|
3
|
+
const jsxExtensions = (appConfig.integrations ?? []).filter((integration) => integration.jsxImportSource).flatMap(
|
|
4
|
+
(integration) => integration.extensions.filter((extension) => extension.endsWith(".tsx") || extension.endsWith(".jsx")).map((extension) => ({ integration, extension }))
|
|
5
|
+
).sort((left, right) => right.extension.length - left.extension.length);
|
|
6
|
+
return jsxExtensions.map(
|
|
7
|
+
({ integration, extension }) => createForeignJsxOverridePlugin({
|
|
8
|
+
hostJsxImportSource: integration.jsxImportSource,
|
|
9
|
+
foreignExtensions: [extension],
|
|
10
|
+
excludeExtensions: jsxExtensions.filter((candidate) => candidate.extension.length > extension.length).filter((candidate) => candidate.extension.endsWith(extension)).map((candidate) => candidate.extension),
|
|
11
|
+
name: `ecopages-jsx-ownership-${integration.name}-${extension.replace(/[^a-zA-Z0-9]+/g, "-")}`
|
|
12
|
+
})
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
getJsxOwnershipPlugins
|
|
17
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified pages Rolldown graph (Phase A build + Phase C import).
|
|
3
|
+
*
|
|
4
|
+
* Enabled by default in production builds. Opt out with
|
|
5
|
+
* `ECOPAGES_UNIFIED_PAGES_GRAPH=0`. Covers all static page template extensions
|
|
6
|
+
* registered on the app config.
|
|
7
|
+
*/
|
|
8
|
+
import type { EcoPagesAppConfig } from '../types/internal-types.js';
|
|
9
|
+
export declare const PAGES_UNIFIED_GRAPH_CACHE_DIR = ".server-pages-graph";
|
|
10
|
+
export declare const PAGES_UNIFIED_GRAPH_CACHE_FILENAME = ".build-cache.json";
|
|
11
|
+
export interface PagesUnifiedGraphCacheManifest {
|
|
12
|
+
invalidationVersion: string;
|
|
13
|
+
buildInputsFingerprint: string;
|
|
14
|
+
buildKey: string;
|
|
15
|
+
builtAt: number;
|
|
16
|
+
outputs: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
export declare function isPagesUnifiedGraphEnabled(): boolean;
|
|
19
|
+
/** True when the unified graph should build or serve prebuilt page modules. */
|
|
20
|
+
export declare function shouldBuildPagesUnifiedGraph(): boolean;
|
|
21
|
+
export declare function isPagesUnifiedGraphPage(filePath: string, appConfig: EcoPagesAppConfig): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Builds eligible static pages in one Rolldown invocation and seeds route-module disk cache.
|
|
24
|
+
*/
|
|
25
|
+
export declare function ensurePagesUnifiedGraphBuilt(options: {
|
|
26
|
+
appConfig: EcoPagesAppConfig;
|
|
27
|
+
entryPaths: readonly string[];
|
|
28
|
+
outdir: string;
|
|
29
|
+
force?: boolean;
|
|
30
|
+
}): Promise<PagesUnifiedGraphCacheManifest | undefined>;
|
|
31
|
+
export declare function importPagesUnifiedGraphModule<T>(appConfig: EcoPagesAppConfig, filePath: string): Promise<T | undefined>;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import { fileSystem } from "@ecopages/file-system";
|
|
4
|
+
import { appLogger } from "../global/app-logger.js";
|
|
5
|
+
import { build, getAppRouteModuleBuildExecutor, getAppServerBuildPlugins } from "./build-adapter.js";
|
|
6
|
+
import { createBuildInputsFingerprint, hashAppConfigFile } from "./build-input-fingerprint.js";
|
|
7
|
+
import { getCorePackageVersion } from "../services/module-loading/route-module-build-manifest.js";
|
|
8
|
+
import { resolveInternalExecutionDir } from "../utils/resolve-work-dir.js";
|
|
9
|
+
import { getSharedRouteModuleBuildCache } from "../services/module-loading/route-module-build-cache-registry.js";
|
|
10
|
+
import { normalizeNodeRuntimeBuildOutputFile } from "./runtime-build-output-normalizer.js";
|
|
11
|
+
import { resolveRouteModuleDependencyPaths } from "../services/module-loading/route-module-dependency-hasher.js";
|
|
12
|
+
import { getJsxOwnershipPlugins } from "./jsx-ownership-plugins.js";
|
|
13
|
+
const PAGES_UNIFIED_GRAPH_CACHE_DIR = ".server-pages-graph";
|
|
14
|
+
const PAGES_UNIFIED_GRAPH_CACHE_FILENAME = ".build-cache.json";
|
|
15
|
+
function isPagesUnifiedGraphEnabled() {
|
|
16
|
+
if (process.env.ECOPAGES_UNIFIED_PAGES_GRAPH === "0") {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if (process.env.ECOPAGES_UNIFIED_PAGES_GRAPH === "1") {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return process.env.NODE_ENV === "production";
|
|
23
|
+
}
|
|
24
|
+
function shouldBuildPagesUnifiedGraph() {
|
|
25
|
+
return isPagesUnifiedGraphEnabled() && process.env.NODE_ENV === "production";
|
|
26
|
+
}
|
|
27
|
+
function isPagesUnifiedGraphPage(filePath, appConfig) {
|
|
28
|
+
const normalizedPath = path.normalize(filePath);
|
|
29
|
+
return appConfig.templatesExt.some((extension) => normalizedPath.endsWith(extension));
|
|
30
|
+
}
|
|
31
|
+
function getPagesUnifiedGraphCachePath(appConfig) {
|
|
32
|
+
return path.join(
|
|
33
|
+
resolveInternalExecutionDir(appConfig),
|
|
34
|
+
PAGES_UNIFIED_GRAPH_CACHE_DIR,
|
|
35
|
+
PAGES_UNIFIED_GRAPH_CACHE_FILENAME
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
function createPagesUnifiedGraphBuildKey(appConfig, outdir) {
|
|
39
|
+
const plugins = appConfig.runtime?.buildManifest ? getAppServerBuildPlugins(appConfig) : [];
|
|
40
|
+
const pluginNames = [...plugins, ...getJsxOwnershipPlugins(appConfig)].map((plugin) => plugin.name).sort().join("|");
|
|
41
|
+
const templateExtensions = [...appConfig.templatesExt].sort().join("|");
|
|
42
|
+
return [
|
|
43
|
+
path.resolve(outdir),
|
|
44
|
+
hashAppConfigFile(appConfig),
|
|
45
|
+
templateExtensions,
|
|
46
|
+
pluginNames,
|
|
47
|
+
"es2022",
|
|
48
|
+
"esm",
|
|
49
|
+
"external-packages"
|
|
50
|
+
].join("::");
|
|
51
|
+
}
|
|
52
|
+
function readPagesUnifiedGraphManifest(appConfig) {
|
|
53
|
+
const manifestPath = getPagesUnifiedGraphCachePath(appConfig);
|
|
54
|
+
if (!fileSystem.exists(manifestPath)) {
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(fileSystem.readFileSync(manifestPath));
|
|
59
|
+
if (!parsed?.outputs) {
|
|
60
|
+
return void 0;
|
|
61
|
+
}
|
|
62
|
+
return parsed;
|
|
63
|
+
} catch {
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function writePagesUnifiedGraphManifest(appConfig, manifest) {
|
|
68
|
+
const manifestPath = getPagesUnifiedGraphCachePath(appConfig);
|
|
69
|
+
fileSystem.ensureDir(path.dirname(manifestPath));
|
|
70
|
+
fileSystem.write(manifestPath, `${JSON.stringify(manifest, null, " ")}
|
|
71
|
+
`);
|
|
72
|
+
}
|
|
73
|
+
function createSafeGraphEntryKey(entryPath, rootDir) {
|
|
74
|
+
const relativePath = path.relative(rootDir, entryPath).replace(/\.[^.]+$/u, "");
|
|
75
|
+
const safeKey = relativePath.replace(/[^a-zA-Z0-9]+/gu, "-").replace(/^-+|-+$/gu, "");
|
|
76
|
+
return safeKey.length > 0 ? safeKey : "page";
|
|
77
|
+
}
|
|
78
|
+
function resolveOutputForEntrypoint(entryKey, buildResult) {
|
|
79
|
+
const outputs = buildResult.outputs.map((output) => output.path);
|
|
80
|
+
for (const outputPath of outputs) {
|
|
81
|
+
const outputBaseName = path.basename(outputPath);
|
|
82
|
+
if (outputBaseName.startsWith(`${entryKey}-`) && /\.(?:m?js)$/u.test(outputBaseName)) {
|
|
83
|
+
return outputPath;
|
|
84
|
+
}
|
|
85
|
+
if (outputBaseName === `${entryKey}.js` || outputBaseName === `${entryKey}.mjs`) {
|
|
86
|
+
return outputPath;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return void 0;
|
|
90
|
+
}
|
|
91
|
+
function isManifestValidForEntries(manifest, appConfig, outdir, entryPaths) {
|
|
92
|
+
if (manifest.invalidationVersion !== getCorePackageVersion()) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
if (manifest.buildInputsFingerprint !== createBuildInputsFingerprint(appConfig)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
if (manifest.buildKey !== createPagesUnifiedGraphBuildKey(appConfig, outdir)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return entryPaths.every((entryPath) => {
|
|
102
|
+
const resolvedEntryPath = path.resolve(entryPath);
|
|
103
|
+
const outputPath = manifest.outputs[resolvedEntryPath];
|
|
104
|
+
return outputPath ? fileSystem.exists(outputPath) : false;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async function ensurePagesUnifiedGraphBuilt(options) {
|
|
108
|
+
if (!shouldBuildPagesUnifiedGraph()) {
|
|
109
|
+
return void 0;
|
|
110
|
+
}
|
|
111
|
+
const eligibleEntryPaths = options.entryPaths.map((entryPath) => path.resolve(entryPath)).filter((entryPath) => isPagesUnifiedGraphPage(entryPath, options.appConfig));
|
|
112
|
+
if (eligibleEntryPaths.length === 0) {
|
|
113
|
+
return void 0;
|
|
114
|
+
}
|
|
115
|
+
const outdir = path.resolve(options.outdir);
|
|
116
|
+
const existingManifest = options.force ? void 0 : readPagesUnifiedGraphManifest(options.appConfig);
|
|
117
|
+
if (existingManifest && isManifestValidForEntries(existingManifest, options.appConfig, outdir, eligibleEntryPaths)) {
|
|
118
|
+
appLogger.debug("Reusing pages unified graph cache");
|
|
119
|
+
return existingManifest;
|
|
120
|
+
}
|
|
121
|
+
const plugins = options.appConfig.runtime?.buildManifest ? getAppServerBuildPlugins(options.appConfig) : [];
|
|
122
|
+
const mergedPlugins = [...plugins, ...getJsxOwnershipPlugins(options.appConfig)];
|
|
123
|
+
const routeModuleBuildCache = getSharedRouteModuleBuildCache(outdir, options.appConfig);
|
|
124
|
+
const entryRecord = {};
|
|
125
|
+
const entryKeysByPath = /* @__PURE__ */ new Map();
|
|
126
|
+
for (const entryPath of eligibleEntryPaths) {
|
|
127
|
+
const entryKey = createSafeGraphEntryKey(entryPath, options.appConfig.rootDir);
|
|
128
|
+
entryRecord[entryKey] = entryPath;
|
|
129
|
+
entryKeysByPath.set(entryPath, entryKey);
|
|
130
|
+
}
|
|
131
|
+
appLogger.debugTime("pagesUnifiedGraphBuild");
|
|
132
|
+
const buildResult = await build(
|
|
133
|
+
{
|
|
134
|
+
entrypoints: entryRecord,
|
|
135
|
+
root: options.appConfig.rootDir,
|
|
136
|
+
outdir,
|
|
137
|
+
target: "es2022",
|
|
138
|
+
format: "esm",
|
|
139
|
+
sourcemap: "none",
|
|
140
|
+
splitting: true,
|
|
141
|
+
minify: false,
|
|
142
|
+
naming: "[name]-[hash].[ext]",
|
|
143
|
+
externalPackages: true,
|
|
144
|
+
plugins: mergedPlugins.length > 0 ? mergedPlugins : void 0
|
|
145
|
+
},
|
|
146
|
+
getAppRouteModuleBuildExecutor(options.appConfig)
|
|
147
|
+
);
|
|
148
|
+
appLogger.debugTimeEnd("pagesUnifiedGraphBuild");
|
|
149
|
+
if (!buildResult.success) {
|
|
150
|
+
const details = buildResult.logs.map((log) => log.message).join(" | ");
|
|
151
|
+
throw new Error(`Pages unified graph build failed: ${details}`);
|
|
152
|
+
}
|
|
153
|
+
const outputs = {};
|
|
154
|
+
for (const entryPath of eligibleEntryPaths) {
|
|
155
|
+
const fileHash = fileSystem.hash(entryPath);
|
|
156
|
+
const entryKey = entryKeysByPath.get(entryPath);
|
|
157
|
+
const compiledOutput = entryKey ? resolveOutputForEntrypoint(entryKey, buildResult) : void 0;
|
|
158
|
+
if (!compiledOutput) {
|
|
159
|
+
throw new Error(`Pages unified graph build produced no output for ${entryPath}`);
|
|
160
|
+
}
|
|
161
|
+
normalizeNodeRuntimeBuildOutputFile(compiledOutput, options.appConfig.rootDir);
|
|
162
|
+
outputs[entryPath] = compiledOutput;
|
|
163
|
+
routeModuleBuildCache.recordBuild({
|
|
164
|
+
filePath: entryPath,
|
|
165
|
+
rootDir: options.appConfig.rootDir,
|
|
166
|
+
outdir,
|
|
167
|
+
fileHash,
|
|
168
|
+
outputPath: compiledOutput,
|
|
169
|
+
dependencyModulePaths: resolveRouteModuleDependencyPaths(buildResult, entryPath, options.appConfig.rootDir),
|
|
170
|
+
externalPackages: true,
|
|
171
|
+
plugins: mergedPlugins
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
const manifest = {
|
|
175
|
+
invalidationVersion: getCorePackageVersion(),
|
|
176
|
+
buildInputsFingerprint: createBuildInputsFingerprint(options.appConfig),
|
|
177
|
+
buildKey: createPagesUnifiedGraphBuildKey(options.appConfig, outdir),
|
|
178
|
+
builtAt: Date.now(),
|
|
179
|
+
outputs
|
|
180
|
+
};
|
|
181
|
+
writePagesUnifiedGraphManifest(options.appConfig, manifest);
|
|
182
|
+
appLogger.debug(`Built pages unified graph for ${eligibleEntryPaths.length} entries`);
|
|
183
|
+
return manifest;
|
|
184
|
+
}
|
|
185
|
+
async function importPagesUnifiedGraphModule(appConfig, filePath) {
|
|
186
|
+
const manifest = readPagesUnifiedGraphManifest(appConfig);
|
|
187
|
+
if (!manifest) {
|
|
188
|
+
return void 0;
|
|
189
|
+
}
|
|
190
|
+
const resolvedFilePath = path.resolve(filePath);
|
|
191
|
+
const outputPath = manifest.outputs[resolvedFilePath];
|
|
192
|
+
if (!outputPath || !fileSystem.exists(outputPath)) {
|
|
193
|
+
return void 0;
|
|
194
|
+
}
|
|
195
|
+
return await import(
|
|
196
|
+
/* @vite-ignore */
|
|
197
|
+
pathToFileURL(outputPath).href
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
export {
|
|
201
|
+
PAGES_UNIFIED_GRAPH_CACHE_DIR,
|
|
202
|
+
PAGES_UNIFIED_GRAPH_CACHE_FILENAME,
|
|
203
|
+
ensurePagesUnifiedGraphBuilt,
|
|
204
|
+
importPagesUnifiedGraphModule,
|
|
205
|
+
isPagesUnifiedGraphEnabled,
|
|
206
|
+
isPagesUnifiedGraphPage,
|
|
207
|
+
shouldBuildPagesUnifiedGraph
|
|
208
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BuildExecutor, BuildOptions, BuildResult } from './build-adapter.js';
|
|
2
|
+
/**
|
|
3
|
+
* Concurrency-limited build executor wrapper.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Runs up to `limit` builds concurrently. Use for independent route-module
|
|
7
|
+
* and HMR browser builds where FIFO serialization is unnecessary.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ParallelBuildExecutor implements BuildExecutor {
|
|
10
|
+
private readonly inner;
|
|
11
|
+
private readonly limit;
|
|
12
|
+
private activeCount;
|
|
13
|
+
private queue;
|
|
14
|
+
constructor(inner: BuildExecutor, limit: number);
|
|
15
|
+
build(options: BuildOptions): Promise<BuildResult>;
|
|
16
|
+
private drainQueue;
|
|
17
|
+
unwrap(): BuildExecutor;
|
|
18
|
+
getConcurrencyLimitForTests(): number;
|
|
19
|
+
getActiveCountForTests(): number;
|
|
20
|
+
getQueuedCountForTests(): number;
|
|
21
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
class ParallelBuildExecutor {
|
|
2
|
+
inner;
|
|
3
|
+
limit;
|
|
4
|
+
activeCount = 0;
|
|
5
|
+
queue = [];
|
|
6
|
+
constructor(inner, limit) {
|
|
7
|
+
this.inner = inner;
|
|
8
|
+
this.limit = Math.max(1, limit);
|
|
9
|
+
}
|
|
10
|
+
build(options) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
this.queue.push({
|
|
13
|
+
operation: () => this.inner.build(options),
|
|
14
|
+
resolve,
|
|
15
|
+
reject
|
|
16
|
+
});
|
|
17
|
+
this.drainQueue();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
drainQueue() {
|
|
21
|
+
while (this.activeCount < this.limit && this.queue.length > 0) {
|
|
22
|
+
const next = this.queue.shift();
|
|
23
|
+
if (!next) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.activeCount += 1;
|
|
27
|
+
void next.operation().then((result) => {
|
|
28
|
+
next.resolve(result);
|
|
29
|
+
}).catch((error) => {
|
|
30
|
+
next.reject(error);
|
|
31
|
+
}).finally(() => {
|
|
32
|
+
this.activeCount -= 1;
|
|
33
|
+
this.drainQueue();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
unwrap() {
|
|
38
|
+
return this.inner;
|
|
39
|
+
}
|
|
40
|
+
getConcurrencyLimitForTests() {
|
|
41
|
+
return this.limit;
|
|
42
|
+
}
|
|
43
|
+
getActiveCountForTests() {
|
|
44
|
+
return this.activeCount;
|
|
45
|
+
}
|
|
46
|
+
getQueuedCountForTests() {
|
|
47
|
+
return this.queue.length;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
ParallelBuildExecutor
|
|
52
|
+
};
|
|
@@ -201,7 +201,8 @@ function resolveRolldownOptions(options, contextRoot, outdir, appRootRequireCach
|
|
|
201
201
|
transformOptions.target = options.target;
|
|
202
202
|
}
|
|
203
203
|
const bundlePlugins = options.plugins ?? [];
|
|
204
|
-
const
|
|
204
|
+
const sourceTransforms = options.target === "browser" ? options.sourceTransforms ?? [] : [];
|
|
205
|
+
const appPlugins = createRolldownPluginBridge(bundlePlugins, contextRoot, sourceTransforms);
|
|
205
206
|
const allPlugins = [...options.target !== "browser" ? [createServerSideCssShimPlugin()] : [], ...appPlugins];
|
|
206
207
|
const inputOptions = {
|
|
207
208
|
input: options.entrypoints,
|
|
@@ -211,6 +212,11 @@ function resolveRolldownOptions(options, contextRoot, outdir, appRootRequireCach
|
|
|
211
212
|
transform: Object.keys(transformOptions).length > 0 ? transformOptions : void 0,
|
|
212
213
|
resolve: options.conditions ? { conditionNames: options.conditions } : void 0,
|
|
213
214
|
treeshake: typeof options.treeshaking === "boolean" ? options.treeshaking : true,
|
|
215
|
+
...process.env.ECOPAGES_PROFILE_BUILD === "1" ? {} : {
|
|
216
|
+
checks: {
|
|
217
|
+
pluginTimings: false
|
|
218
|
+
}
|
|
219
|
+
},
|
|
214
220
|
experimental: {
|
|
215
221
|
nativeMagicString: true
|
|
216
222
|
},
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
toBuildLogs,
|
|
10
10
|
transpileProfileToOptions
|
|
11
11
|
} from "./rolldown-adapter-helpers.js";
|
|
12
|
+
import { recordRolldownBuildInvocation } from "./rolldown-build-invocation-metrics.js";
|
|
12
13
|
const moduleRequire = createRequire(import.meta.url);
|
|
13
14
|
class RolldownBuildAdapter {
|
|
14
15
|
ownership = "rolldown";
|
|
@@ -20,6 +21,7 @@ class RolldownBuildAdapter {
|
|
|
20
21
|
* entrypoints, use {@link RolldownDevBuildAdapter}.
|
|
21
22
|
*/
|
|
22
23
|
async buildOrThrow(options) {
|
|
24
|
+
recordRolldownBuildInvocation("rolldown");
|
|
23
25
|
const contextRoot = options.root ? path.resolve(options.root) : process.cwd();
|
|
24
26
|
const outdir = path.resolve(options.outdir ?? "dist/assets");
|
|
25
27
|
const plugins = options.plugins ?? [];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide Rolldown build invocation counters for benchmarks and spikes.
|
|
3
|
+
*
|
|
4
|
+
* Gated behind {@link isRolldownBuildMetricsEnabled} so production paths stay quiet.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isRolldownBuildMetricsEnabled(): boolean;
|
|
7
|
+
export declare function recordRolldownBuildInvocation(adapter?: 'rolldown' | 'rolldown-dev'): void;
|
|
8
|
+
export declare function getRolldownBuildInvocationCounts(): Readonly<Record<string, number>>;
|
|
9
|
+
export declare function resetRolldownBuildInvocationCounts(): void;
|
|
10
|
+
export declare function recordPageModuleBuildInvocation(): void;
|
|
11
|
+
export declare function getPageModuleRolldownBuildInvocations(): number;
|
|
12
|
+
export declare function getTotalRolldownBuildInvocations(): number;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const invocationCounts = /* @__PURE__ */ new Map();
|
|
2
|
+
let pageModuleBuildInvocations = 0;
|
|
3
|
+
function isRolldownBuildMetricsEnabled() {
|
|
4
|
+
return process.env.ECOPAGES_ROLLDOWN_BUILD_METRICS === "1" || process.env.ECOPAGES_LOGGER_DEBUG === "true";
|
|
5
|
+
}
|
|
6
|
+
function recordRolldownBuildInvocation(adapter = "rolldown") {
|
|
7
|
+
if (!isRolldownBuildMetricsEnabled()) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
invocationCounts.set(adapter, (invocationCounts.get(adapter) ?? 0) + 1);
|
|
11
|
+
}
|
|
12
|
+
function getRolldownBuildInvocationCounts() {
|
|
13
|
+
return Object.fromEntries(invocationCounts);
|
|
14
|
+
}
|
|
15
|
+
function resetRolldownBuildInvocationCounts() {
|
|
16
|
+
invocationCounts.clear();
|
|
17
|
+
pageModuleBuildInvocations = 0;
|
|
18
|
+
}
|
|
19
|
+
function recordPageModuleBuildInvocation() {
|
|
20
|
+
if (!isRolldownBuildMetricsEnabled()) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
pageModuleBuildInvocations += 1;
|
|
24
|
+
}
|
|
25
|
+
function getPageModuleRolldownBuildInvocations() {
|
|
26
|
+
return pageModuleBuildInvocations;
|
|
27
|
+
}
|
|
28
|
+
function getTotalRolldownBuildInvocations() {
|
|
29
|
+
let total = 0;
|
|
30
|
+
for (const count of invocationCounts.values()) {
|
|
31
|
+
total += count;
|
|
32
|
+
}
|
|
33
|
+
return total;
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
getPageModuleRolldownBuildInvocations,
|
|
37
|
+
getRolldownBuildInvocationCounts,
|
|
38
|
+
getTotalRolldownBuildInvocations,
|
|
39
|
+
isRolldownBuildMetricsEnabled,
|
|
40
|
+
recordPageModuleBuildInvocation,
|
|
41
|
+
recordRolldownBuildInvocation,
|
|
42
|
+
resetRolldownBuildInvocationCounts
|
|
43
|
+
};
|