@ecopages/core 0.2.0-beta.41 → 0.2.0-beta.42
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 +3 -3
- package/src/services/invalidation/development-invalidation.service.js +3 -1
- package/src/services/module-loading/README.md +2 -2
- package/src/services/module-loading/page-module-import.service.js +15 -4
- package/src/services/module-loading/route-module-build-cache-registry.d.ts +2 -0
- package/src/services/module-loading/route-module-build-cache-registry.js +12 -0
- package/src/services/module-loading/route-module-build-cache.store.d.ts +10 -0
- package/src/services/module-loading/route-module-build-cache.store.js +18 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecopages/core",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.42",
|
|
4
4
|
"description": "Core package for Ecopages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ecopages",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"directory": "packages/core"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@ecopages/file-system": "0.2.0-beta.
|
|
20
|
+
"@ecopages/file-system": "0.2.0-beta.42",
|
|
21
21
|
"@ecopages/logger": "^0.2.3",
|
|
22
22
|
"@ecopages/scripts-injector": "^0.1.5",
|
|
23
23
|
"@oxc-project/runtime": "0.141.0",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@standard-schema/utils": "^0.3.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@ecopages/dev-toolbar": "0.2.0-beta.
|
|
35
|
+
"@ecopages/dev-toolbar": "0.2.0-beta.42"
|
|
36
36
|
},
|
|
37
37
|
"peerDependenciesMeta": {
|
|
38
38
|
"@ecopages/dev-toolbar": {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { getAppServerInvalidationState } from '../runtime-state/server-invalidation-state.service.js';
|
|
3
3
|
import { appLogger } from '../../global/app-logger.js';
|
|
4
|
+
import { clearAppDevelopmentRouteModuleBuildCaches } from '../module-loading/route-module-build-cache-registry.js';
|
|
4
5
|
/**
|
|
5
6
|
* Framework-owned development invalidation service.
|
|
6
7
|
*
|
|
@@ -29,6 +30,7 @@ export class DevelopmentInvalidationService {
|
|
|
29
30
|
invalidateServerModules(changedFiles) {
|
|
30
31
|
getAppServerInvalidationState(this.appConfig).invalidateServerModules(changedFiles);
|
|
31
32
|
this.appConfig.runtime?.appModuleLoader?.invalidateDevelopmentGraph();
|
|
33
|
+
clearAppDevelopmentRouteModuleBuildCaches(this.appConfig);
|
|
32
34
|
}
|
|
33
35
|
/**
|
|
34
36
|
* Registers an integration-owned handler for registered script entrypoint edits.
|
|
@@ -57,8 +59,8 @@ export class DevelopmentInvalidationService {
|
|
|
57
59
|
* Resets runtime-owned graph state and invalidates server modules.
|
|
58
60
|
*/
|
|
59
61
|
resetRuntimeState(changedFiles) {
|
|
62
|
+
this.invalidateServerModules(changedFiles);
|
|
60
63
|
const serverInvalidationState = getAppServerInvalidationState(this.appConfig);
|
|
61
|
-
serverInvalidationState.invalidateServerModules(changedFiles);
|
|
62
64
|
serverInvalidationState.reset();
|
|
63
65
|
}
|
|
64
66
|
/**
|
|
@@ -33,7 +33,7 @@ Call site (route scan, renderer, SSG, API)
|
|
|
33
33
|
2. **Disk transpile cache** (`.eco/.server-modules/.build-cache.json`) — production and stable development graphs when dependency hashes match. Manifest field `corePackageVersion` invalidates entries when the framework package changes.
|
|
34
34
|
3. **Unified graph manifest** — production static export fast path only; see build layer docs.
|
|
35
35
|
|
|
36
|
-
Development
|
|
36
|
+
Development import URLs use `sourceHash` plus a per-service import generation counter. Node uses that value in its `?update=` query. Bun also receives a generation-specific compiled output filename because it retains a previously imported file when only its query changes. Both paths advance after `invalidateDevelopmentGraph()` without a process-wide invalidation version in reuse keys.
|
|
37
37
|
|
|
38
38
|
## Files
|
|
39
39
|
|
|
@@ -49,4 +49,4 @@ Development `?update=` query params use `sourceHash` plus a per-service import g
|
|
|
49
49
|
|
|
50
50
|
## Development invalidation
|
|
51
51
|
|
|
52
|
-
`DevelopmentInvalidationService.invalidateServerModules()` calls `appModuleLoader.invalidateDevelopmentGraph()`, which clears the in-memory import cache, bumps the per-service dev import generation used
|
|
52
|
+
`DevelopmentInvalidationService.invalidateServerModules()` calls `appModuleLoader.invalidateDevelopmentGraph()`, which clears the in-memory import cache, bumps the per-service dev import generation used for runtime URLs and Bun output filenames, and clears dependency-hash memoization. It also clears persisted route-module entries: externalized generated modules can change without appearing in a route bundle's dependency graph, so retaining those entries could reload stale server HTML.
|
|
@@ -127,10 +127,7 @@ export class PageModuleImportService {
|
|
|
127
127
|
async loadModule(options) {
|
|
128
128
|
const { filePath, fileHash, importCacheKey } = options;
|
|
129
129
|
const { rootDir, outdir, splitting, externalPackages, transpileErrorMessage = (details) => `Error transpiling page module: ${details}`, noOutputMessage = (targetFilePath) => `No transpiled output generated for page module: ${targetFilePath}`, } = options;
|
|
130
|
-
const outputFileName = resolvePageModuleOutputFileName({
|
|
131
|
-
filePath,
|
|
132
|
-
fileHash,
|
|
133
|
-
});
|
|
130
|
+
const outputFileName = createRuntimeBuildOutputFileName(resolvePageModuleOutputFileName({ filePath, fileHash }), this.developmentImportGeneration);
|
|
134
131
|
const outputNamingTemplate = outputFileName.replace(/\.mjs$/u, '.[ext]');
|
|
135
132
|
const preferredOutputPath = path.join(outdir, outputFileName);
|
|
136
133
|
const buildOptions = this.appConfig
|
|
@@ -229,3 +226,17 @@ function createRuntimeModuleUrl(filePath, fileHash, developmentImportGeneration)
|
|
|
229
226
|
function shouldAddRuntimeUpdateQuery() {
|
|
230
227
|
return process.env.NODE_ENV === 'development';
|
|
231
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Gives Bun a distinct compiled module path after development invalidation.
|
|
231
|
+
*
|
|
232
|
+
* @remarks
|
|
233
|
+
* Bun does not reload an already-imported module when only its URL query changes.
|
|
234
|
+
* A dependency edit can leave the entrypoint source hash unchanged, so the output
|
|
235
|
+
* filename must include the import generation as well as the runtime query.
|
|
236
|
+
*/
|
|
237
|
+
function createRuntimeBuildOutputFileName(outputFileName, developmentImportGeneration) {
|
|
238
|
+
if (typeof Bun === 'undefined' || !shouldAddRuntimeUpdateQuery()) {
|
|
239
|
+
return outputFileName;
|
|
240
|
+
}
|
|
241
|
+
return outputFileName.replace(/\.mjs$/u, `-${developmentImportGeneration}.mjs`);
|
|
242
|
+
}
|
|
@@ -22,3 +22,5 @@ export declare const getRouteModuleBuildCacheOutdir: typeof getServerModuleBuild
|
|
|
22
22
|
* generation during the same build process.
|
|
23
23
|
*/
|
|
24
24
|
export declare function getSharedRouteModuleBuildCache(outdir: string, appConfig?: EcoPagesAppConfig): RouteModuleBuildCache;
|
|
25
|
+
/** Clears route-module cache entries that can retain stale external server modules during development. */
|
|
26
|
+
export declare function clearAppDevelopmentRouteModuleBuildCaches(appConfig: EcoPagesAppConfig): void;
|
|
@@ -49,3 +49,15 @@ export function getSharedRouteModuleBuildCache(outdir, appConfig) {
|
|
|
49
49
|
caches.set(outdir, routeModuleBuildCache);
|
|
50
50
|
return routeModuleBuildCache;
|
|
51
51
|
}
|
|
52
|
+
/** Clears route-module cache entries that can retain stale external server modules during development. */
|
|
53
|
+
export function clearAppDevelopmentRouteModuleBuildCaches(appConfig) {
|
|
54
|
+
const serverModuleCacheOutdir = getServerModuleBuildCacheOutdir(appConfig);
|
|
55
|
+
const caches = appConfig.runtime?.routeModuleBuildCaches;
|
|
56
|
+
const serverModuleCache = caches?.get(serverModuleCacheOutdir) ?? new RouteModuleBuildCache(serverModuleCacheOutdir);
|
|
57
|
+
serverModuleCache.clearDevelopmentEntries();
|
|
58
|
+
for (const cache of caches?.values() ?? []) {
|
|
59
|
+
if (cache !== serverModuleCache) {
|
|
60
|
+
cache.clearDevelopmentEntries();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -51,6 +51,16 @@ export declare class RouteModuleBuildCache {
|
|
|
51
51
|
context: RouteModuleStaticRenderCacheContext;
|
|
52
52
|
}): void;
|
|
53
53
|
resetMemory(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Removes every persisted route-module entry after development invalidation.
|
|
56
|
+
*
|
|
57
|
+
* @remarks
|
|
58
|
+
* Server bundles may externalize generated modules whose source dependencies
|
|
59
|
+
* are not present in the route bundle's dependency graph. Keeping an entry
|
|
60
|
+
* after its server graph changes can therefore reload a route that still
|
|
61
|
+
* imports an obsolete external bundle.
|
|
62
|
+
*/
|
|
63
|
+
clearDevelopmentEntries(): void;
|
|
54
64
|
pruneStaleRenderedOutputs(activePathnames: ReadonlySet<string>): string[];
|
|
55
65
|
private loadManifest;
|
|
56
66
|
private persistManifest;
|
|
@@ -164,6 +164,24 @@ export class RouteModuleBuildCache {
|
|
|
164
164
|
this.manifest = undefined;
|
|
165
165
|
this.manifestLoaded = false;
|
|
166
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Removes every persisted route-module entry after development invalidation.
|
|
169
|
+
*
|
|
170
|
+
* @remarks
|
|
171
|
+
* Server bundles may externalize generated modules whose source dependencies
|
|
172
|
+
* are not present in the route bundle's dependency graph. Keeping an entry
|
|
173
|
+
* after its server graph changes can therefore reload a route that still
|
|
174
|
+
* imports an obsolete external bundle.
|
|
175
|
+
*/
|
|
176
|
+
clearDevelopmentEntries() {
|
|
177
|
+
if (!this.manifestLoaded && !this.dependencies.exists(this.manifestPath)) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const manifest = createEmptyRouteModuleBuildCacheManifest();
|
|
181
|
+
this.manifest = manifest;
|
|
182
|
+
this.manifestLoaded = true;
|
|
183
|
+
this.persistManifest(manifest);
|
|
184
|
+
}
|
|
167
185
|
pruneStaleRenderedOutputs(activePathnames) {
|
|
168
186
|
if (process.env.NODE_ENV !== 'production') {
|
|
169
187
|
return [];
|