@ecopages/core 0.2.0-beta.16 → 0.2.0-beta.18
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 +10 -2
- package/src/adapters/bun/server-adapter.js +2 -0
- package/src/adapters/node/server-adapter-dependencies.js +2 -0
- package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +0 -2
- package/src/adapters/shared/hmr-entrypoint-registrar.js +3 -26
- package/src/adapters/shared/runtime-server-lifecycle.js +4 -0
- package/src/adapters/shared/shared-hmr-manager.d.ts +5 -3
- package/src/adapters/shared/shared-hmr-manager.js +15 -8
- package/src/dev/hmr-manager-registry.d.ts +8 -0
- package/src/dev/hmr-manager-registry.js +15 -0
- package/src/hmr/hmr-entrypoint-output.d.ts +14 -0
- package/src/hmr/hmr-entrypoint-output.js +35 -0
- package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -0
- package/src/hmr/strategies/js-hmr-strategy.js +44 -11
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.18",
|
|
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.18",
|
|
21
21
|
"@ecopages/logger": "^0.2.3",
|
|
22
22
|
"@ecopages/scripts-injector": "^0.1.5",
|
|
23
23
|
"@oxc-project/runtime": "0.134.0",
|
|
@@ -133,6 +133,10 @@
|
|
|
133
133
|
"types": "./src/dev/client-bridge-registry.d.ts",
|
|
134
134
|
"default": "./src/dev/client-bridge-registry.js"
|
|
135
135
|
},
|
|
136
|
+
"./dev/hmr-manager-registry": {
|
|
137
|
+
"types": "./src/dev/hmr-manager-registry.d.ts",
|
|
138
|
+
"default": "./src/dev/hmr-manager-registry.js"
|
|
139
|
+
},
|
|
136
140
|
"./dev/dev-client-ownership": {
|
|
137
141
|
"types": "./src/dev/dev-client-ownership.d.ts",
|
|
138
142
|
"default": "./src/dev/dev-client-ownership.js"
|
|
@@ -338,6 +342,10 @@
|
|
|
338
342
|
"types": "./src/dev/client-bridge-registry.d.ts",
|
|
339
343
|
"default": "./src/dev/client-bridge-registry.js"
|
|
340
344
|
},
|
|
345
|
+
"./dev/hmr-manager-registry.ts": {
|
|
346
|
+
"types": "./src/dev/hmr-manager-registry.d.ts",
|
|
347
|
+
"default": "./src/dev/hmr-manager-registry.js"
|
|
348
|
+
},
|
|
341
349
|
"./dev/dev-client-ownership.ts": {
|
|
342
350
|
"types": "./src/dev/dev-client-ownership.d.ts",
|
|
343
351
|
"default": "./src/dev/dev-client-ownership.js"
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from "../shared/runtime-server-lifecycle.js";
|
|
25
25
|
import { ClientBridge } from "./client-bridge.js";
|
|
26
26
|
import { setAppDevClientBridge } from "../../dev/client-bridge-registry.js";
|
|
27
|
+
import { setAppHmrManager } from "../../dev/hmr-manager-registry.js";
|
|
27
28
|
import { HmrManager } from "./hmr-manager.js";
|
|
28
29
|
import { BunStaticPreviewHost } from "./static-preview-host.js";
|
|
29
30
|
class BunServerAdapter extends SharedServerAdapter {
|
|
@@ -600,6 +601,7 @@ async function createBunServerAdapter(params) {
|
|
|
600
601
|
const bridge = params.bridge ?? new ClientBridge();
|
|
601
602
|
const hmrManager = params.hmrManager ?? new HmrManager({ appConfig: params.appConfig, bridge });
|
|
602
603
|
setAppDevClientBridge(params.appConfig, bridge);
|
|
604
|
+
setAppHmrManager(params.appConfig, hmrManager);
|
|
603
605
|
const previewHost = params.previewHost ?? new BunStaticPreviewHost();
|
|
604
606
|
const adapter = new BunServerAdapter({
|
|
605
607
|
...params,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { WebSocketServer } from "ws";
|
|
2
2
|
import { setAppDevClientBridge } from "../../dev/client-bridge-registry.js";
|
|
3
|
+
import { setAppHmrManager } from "../../dev/hmr-manager-registry.js";
|
|
3
4
|
import { NodeClientBridge } from "./node-client-bridge.js";
|
|
4
5
|
import { NodeHmrManager } from "./node-hmr-manager.js";
|
|
5
6
|
class DefaultNodeServerDevRuntimeFactory {
|
|
@@ -8,6 +9,7 @@ class DefaultNodeServerDevRuntimeFactory {
|
|
|
8
9
|
const bridge = new NodeClientBridge();
|
|
9
10
|
const hmrManager = new NodeHmrManager({ appConfig: options.appConfig, bridge });
|
|
10
11
|
setAppDevClientBridge(options.appConfig, bridge);
|
|
12
|
+
setAppHmrManager(options.appConfig, hmrManager);
|
|
11
13
|
return {
|
|
12
14
|
websocketServer,
|
|
13
15
|
bridge,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileSystem } from "@ecopages/file-system";
|
|
3
|
-
import {
|
|
4
|
-
import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
|
|
3
|
+
import { removeStaleHmrEntrypointOutput, resolveHmrEntrypointOutputPaths } from "../../hmr/hmr-entrypoint-output.js";
|
|
5
4
|
class HmrEntrypointRegistrar {
|
|
6
5
|
options;
|
|
7
6
|
constructor(options) {
|
|
@@ -36,7 +35,7 @@ class HmrEntrypointRegistrar {
|
|
|
36
35
|
}
|
|
37
36
|
const { outputPath, outputUrl } = this.getEntrypointOutput(entrypointPath);
|
|
38
37
|
this.options.watchedFiles.set(entrypointPath, outputUrl);
|
|
39
|
-
|
|
38
|
+
removeStaleHmrEntrypointOutput(outputPath, "HMR");
|
|
40
39
|
await registrationOptions.emit(entrypointPath, outputPath);
|
|
41
40
|
if (!fileSystem.exists(outputPath)) {
|
|
42
41
|
throw registrationOptions.getMissingOutputError(entrypointPath, outputPath);
|
|
@@ -57,29 +56,7 @@ class HmrEntrypointRegistrar {
|
|
|
57
56
|
]);
|
|
58
57
|
}
|
|
59
58
|
getEntrypointOutput(entrypointPath) {
|
|
60
|
-
|
|
61
|
-
const relativePathJs = relativePath.replace(/\.(tsx?|jsx?|mdx?)$/, ".js");
|
|
62
|
-
const encodedPathJs = this.encodeDynamicSegments(relativePathJs);
|
|
63
|
-
const urlPath = encodedPathJs.split(path.sep).join("/");
|
|
64
|
-
return {
|
|
65
|
-
outputUrl: `/${path.join(RESOLVED_ASSETS_DIR, "_hmr", urlPath)}`,
|
|
66
|
-
outputPath: path.join(this.options.distDir, urlPath)
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
removeStaleEntrypointOutput(outputPath) {
|
|
70
|
-
if (!fileSystem.exists(outputPath)) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
try {
|
|
74
|
-
fileSystem.remove(outputPath);
|
|
75
|
-
} catch (error) {
|
|
76
|
-
appLogger.warn(
|
|
77
|
-
`[HMR] Failed to remove stale entrypoint output ${outputPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
encodeDynamicSegments(filepath) {
|
|
82
|
-
return filepath.replace(/\[([^\]]+)\]/g, "_$1_");
|
|
59
|
+
return resolveHmrEntrypointOutputPaths(this.options.srcDir, this.options.distDir, entrypointPath);
|
|
83
60
|
}
|
|
84
61
|
}
|
|
85
62
|
export {
|
|
@@ -4,6 +4,8 @@ import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
|
|
|
4
4
|
import { disposeAppBuildRuntime } from "../../build/build-runtime.js";
|
|
5
5
|
import { getAppBrowserBuildPlugins } from "../../build/build-adapter.js";
|
|
6
6
|
import { copyRuntimePublicDirIfChanged } from "./copy-runtime-public-dir.js";
|
|
7
|
+
import { clearAppDevClientBridge } from "../../dev/client-bridge-registry.js";
|
|
8
|
+
import { clearAppHmrManager } from "../../dev/hmr-manager-registry.js";
|
|
7
9
|
import { injectHmrRuntimeIntoHtmlResponse, isHtmlResponse, shouldInjectHmrHtmlResponse } from "./hmr-html-response.js";
|
|
8
10
|
function prepareRuntimePublicDir(appConfig) {
|
|
9
11
|
const srcPublicDir = path.join(appConfig.rootDir, appConfig.srcDir, appConfig.publicDir);
|
|
@@ -29,6 +31,8 @@ async function disposeDevResources(options) {
|
|
|
29
31
|
await disposeAppBuildRuntime(options.appConfig);
|
|
30
32
|
options.hmrManager?.stop();
|
|
31
33
|
options.bridge?.destroy();
|
|
34
|
+
clearAppDevClientBridge(options.appConfig);
|
|
35
|
+
clearAppHmrManager(options.appConfig);
|
|
32
36
|
await options.previewHost.stop();
|
|
33
37
|
}
|
|
34
38
|
export {
|
|
@@ -47,10 +47,12 @@ export declare abstract class SharedHmrManager implements IHmrManager {
|
|
|
47
47
|
handleFileChange(filePath: string, options?: HandleFileChangeOptions): Promise<void>;
|
|
48
48
|
getOutputUrl(entrypointPath: string): string | undefined;
|
|
49
49
|
/**
|
|
50
|
-
* Returns the emitted HMR script output when the
|
|
50
|
+
* Returns the emitted HMR script output when the entrypoint is already registered
|
|
51
|
+
* and its browser bundle exists on disk.
|
|
51
52
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
53
|
+
* @remarks
|
|
54
|
+
* Disk artifacts alone are not enough: a fresh dev session must still register
|
|
55
|
+
* the entrypoint so file watchers can rebuild it on change.
|
|
54
56
|
*/
|
|
55
57
|
getResolvedScriptOutput(entrypointPath: string): {
|
|
56
58
|
outputUrl: string;
|
|
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { RESOLVED_ASSETS_DIR } from "../../config/constants.js";
|
|
5
|
+
import { resolveHmrEntrypointOutputPaths } from "../../hmr/hmr-entrypoint-output.js";
|
|
5
6
|
import { requireBuildRuntime } from "../../build/build-runtime.js";
|
|
6
7
|
import { fileSystem } from "@ecopages/file-system";
|
|
7
8
|
import { HmrStrategyType } from "../../hmr/hmr-strategy.js";
|
|
@@ -184,21 +185,27 @@ class SharedHmrManager {
|
|
|
184
185
|
return this.watchedFiles.get(entrypointPath);
|
|
185
186
|
}
|
|
186
187
|
/**
|
|
187
|
-
* Returns the emitted HMR script output when the
|
|
188
|
+
* Returns the emitted HMR script output when the entrypoint is already registered
|
|
189
|
+
* and its browser bundle exists on disk.
|
|
188
190
|
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
+
* @remarks
|
|
192
|
+
* Disk artifacts alone are not enough: a fresh dev session must still register
|
|
193
|
+
* the entrypoint so file watchers can rebuild it on change.
|
|
191
194
|
*/
|
|
192
195
|
getResolvedScriptOutput(entrypointPath) {
|
|
193
196
|
const normalizedEntrypoint = path.resolve(entrypointPath);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const outputPath =
|
|
197
|
+
if (!this.watchedFiles.has(normalizedEntrypoint)) {
|
|
198
|
+
return void 0;
|
|
199
|
+
}
|
|
200
|
+
const { outputPath, outputUrl: derivedOutputUrl } = resolveHmrEntrypointOutputPaths(
|
|
201
|
+
this.appConfig.absolutePaths.srcDir,
|
|
202
|
+
this.distDir,
|
|
203
|
+
normalizedEntrypoint
|
|
204
|
+
);
|
|
198
205
|
if (!fileSystem.exists(outputPath)) {
|
|
199
206
|
return void 0;
|
|
200
207
|
}
|
|
201
|
-
const outputUrl = this.watchedFiles.get(normalizedEntrypoint) ??
|
|
208
|
+
const outputUrl = this.watchedFiles.get(normalizedEntrypoint) ?? derivedOutputUrl;
|
|
202
209
|
return { outputUrl, outputPath };
|
|
203
210
|
}
|
|
204
211
|
getWatchedFiles() {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-app registry for the shared HMR manager used by host-owned dev clients.
|
|
3
|
+
*/
|
|
4
|
+
import type { EcoPagesAppConfig } from '../types/public-types.js';
|
|
5
|
+
import type { IHmrManager } from '../types/public-types.js';
|
|
6
|
+
export declare function setAppHmrManager(appConfig: EcoPagesAppConfig, hmrManager: IHmrManager): void;
|
|
7
|
+
export declare function getAppHmrManager(appConfig: EcoPagesAppConfig): IHmrManager | undefined;
|
|
8
|
+
export declare function clearAppHmrManager(appConfig: EcoPagesAppConfig): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const appHmrManagers = /* @__PURE__ */ new WeakMap();
|
|
2
|
+
function setAppHmrManager(appConfig, hmrManager) {
|
|
3
|
+
appHmrManagers.set(appConfig, hmrManager);
|
|
4
|
+
}
|
|
5
|
+
function getAppHmrManager(appConfig) {
|
|
6
|
+
return appHmrManagers.get(appConfig);
|
|
7
|
+
}
|
|
8
|
+
function clearAppHmrManager(appConfig) {
|
|
9
|
+
appHmrManagers.delete(appConfig);
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
clearAppHmrManager,
|
|
13
|
+
getAppHmrManager,
|
|
14
|
+
setAppHmrManager
|
|
15
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function encodeHmrDynamicSegments(filepath: string): string;
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the on-disk and browser URL targets for one HMR script entrypoint.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resolveHmrEntrypointOutputPaths(srcDir: string, distDir: string, entrypointPath: string): {
|
|
6
|
+
outputPath: string;
|
|
7
|
+
outputUrl: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* @remarks
|
|
11
|
+
* Rebuilds must delete the previous artifact so browser-hmr does not reuse a
|
|
12
|
+
* stale bundle when the source file changed.
|
|
13
|
+
*/
|
|
14
|
+
export declare function removeStaleHmrEntrypointOutput(outputPath: string, scope: string): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileSystem } from "@ecopages/file-system";
|
|
3
|
+
import { RESOLVED_ASSETS_DIR } from "../config/constants.js";
|
|
4
|
+
import { appLogger } from "../global/app-logger.js";
|
|
5
|
+
function encodeHmrDynamicSegments(filepath) {
|
|
6
|
+
return filepath.replace(/\[([^\]]+)\]/g, "_$1_");
|
|
7
|
+
}
|
|
8
|
+
function resolveHmrEntrypointOutputPaths(srcDir, distDir, entrypointPath) {
|
|
9
|
+
const normalizedEntrypoint = path.resolve(entrypointPath);
|
|
10
|
+
const relativePath = path.relative(srcDir, normalizedEntrypoint);
|
|
11
|
+
const relativePathJs = relativePath.replace(/\.(tsx?|jsx?|mdx?)$/, ".js");
|
|
12
|
+
const encodedPathJs = encodeHmrDynamicSegments(relativePathJs);
|
|
13
|
+
const urlPath = encodedPathJs.split(path.sep).join("/");
|
|
14
|
+
return {
|
|
15
|
+
outputUrl: `/${path.join(RESOLVED_ASSETS_DIR, "_hmr", urlPath).split(path.sep).join("/")}`,
|
|
16
|
+
outputPath: path.join(distDir, urlPath)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function removeStaleHmrEntrypointOutput(outputPath, scope) {
|
|
20
|
+
if (!fileSystem.exists(outputPath)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
fileSystem.remove(outputPath);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
appLogger.warn(
|
|
27
|
+
`[${scope}] Failed to remove stale entrypoint output ${outputPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
encodeHmrDynamicSegments,
|
|
33
|
+
removeStaleHmrEntrypointOutput,
|
|
34
|
+
resolveHmrEntrypointOutputPaths
|
|
35
|
+
};
|
|
@@ -98,6 +98,7 @@ export declare class JsHmrStrategy extends HmrStrategy {
|
|
|
98
98
|
* Matches if:
|
|
99
99
|
* 1. There are registered entrypoints to rebuild
|
|
100
100
|
* 2. The changed file is a JS/TS file in the src directory
|
|
101
|
+
* 3. Registered entrypoints always match, even when they share an integration template extension
|
|
101
102
|
*
|
|
102
103
|
* @param filePath - Absolute path to the changed file
|
|
103
104
|
* @returns True if this file should trigger entrypoint rebuilds
|
|
@@ -116,6 +117,8 @@ export declare class JsHmrStrategy extends HmrStrategy {
|
|
|
116
117
|
* @returns Action to broadcast update events
|
|
117
118
|
*/
|
|
118
119
|
process(filePath: string): Promise<HmrAction>;
|
|
120
|
+
private resolveEntrypointOutputPath;
|
|
121
|
+
private removeStaleEntrypointOutput;
|
|
119
122
|
/**
|
|
120
123
|
* Bundles one or more entrypoints in a single build invocation.
|
|
121
124
|
* Uses the source directory as the output base so that the directory structure
|
|
@@ -2,6 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { fileSystem } from "@ecopages/file-system";
|
|
3
3
|
import { HmrStrategy, HmrStrategyType } from "../hmr-strategy.js";
|
|
4
4
|
import { appLogger } from "../../global/app-logger.js";
|
|
5
|
+
import { removeStaleHmrEntrypointOutput, resolveHmrEntrypointOutputPaths } from "../hmr-entrypoint-output.js";
|
|
5
6
|
class JsHmrStrategy extends HmrStrategy {
|
|
6
7
|
type = HmrStrategyType.SCRIPT;
|
|
7
8
|
context;
|
|
@@ -15,27 +16,29 @@ class JsHmrStrategy extends HmrStrategy {
|
|
|
15
16
|
* Matches if:
|
|
16
17
|
* 1. There are registered entrypoints to rebuild
|
|
17
18
|
* 2. The changed file is a JS/TS file in the src directory
|
|
19
|
+
* 3. Registered entrypoints always match, even when they share an integration template extension
|
|
18
20
|
*
|
|
19
21
|
* @param filePath - Absolute path to the changed file
|
|
20
22
|
* @returns True if this file should trigger entrypoint rebuilds
|
|
21
23
|
*/
|
|
22
24
|
matches(filePath) {
|
|
23
25
|
const watchedFiles = this.context.getWatchedFiles();
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
26
|
+
const resolvedPath = path.resolve(filePath);
|
|
27
|
+
const isJsTs = /\.(ts|tsx|js|jsx)$/.test(resolvedPath);
|
|
28
|
+
const isInSrc = resolvedPath.startsWith(this.context.getSrcDir());
|
|
29
|
+
const isIntegrationTemplate = this.context.getTemplateExtensions().some((extension) => resolvedPath.endsWith(extension));
|
|
27
30
|
if (watchedFiles.size === 0) {
|
|
28
31
|
return false;
|
|
29
32
|
}
|
|
30
33
|
if (!isJsTs || !isInSrc) {
|
|
31
34
|
return false;
|
|
32
35
|
}
|
|
36
|
+
if (watchedFiles.has(resolvedPath)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
33
39
|
if (isIntegrationTemplate) {
|
|
34
40
|
return false;
|
|
35
41
|
}
|
|
36
|
-
if (watchedFiles.has(filePath)) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
42
|
return true;
|
|
40
43
|
}
|
|
41
44
|
/**
|
|
@@ -59,7 +62,7 @@ class JsHmrStrategy extends HmrStrategy {
|
|
|
59
62
|
}
|
|
60
63
|
const dependencyHits = this.context.getEntrypointDependencyGraph().getDependencyEntrypoints(filePath);
|
|
61
64
|
const hasDependencyHit = dependencyHits.size > 0;
|
|
62
|
-
const impactedEntrypoints = hasDependencyHit ? Array.from(dependencyHits).filter((entrypoint) => watchedFiles.has(entrypoint)) : Array.from(watchedFiles.keys());
|
|
65
|
+
const impactedEntrypoints = hasDependencyHit ? Array.from(dependencyHits).filter((entrypoint) => watchedFiles.has(path.resolve(entrypoint))) : Array.from(watchedFiles.keys());
|
|
63
66
|
const buildableEntrypoints = impactedEntrypoints.filter(
|
|
64
67
|
(entrypoint) => this.context.shouldProcessEntrypoint?.(entrypoint) ?? true
|
|
65
68
|
);
|
|
@@ -69,6 +72,9 @@ class JsHmrStrategy extends HmrStrategy {
|
|
|
69
72
|
if (buildableEntrypoints.length === 0) {
|
|
70
73
|
return { type: "none" };
|
|
71
74
|
}
|
|
75
|
+
for (const entrypoint of buildableEntrypoints) {
|
|
76
|
+
this.removeStaleEntrypointOutput(this.resolveEntrypointOutputPath(entrypoint));
|
|
77
|
+
}
|
|
72
78
|
const buildResult = await this.bundleEntrypoints(buildableEntrypoints);
|
|
73
79
|
if (!buildResult.success) {
|
|
74
80
|
return { type: "none" };
|
|
@@ -82,10 +88,7 @@ class JsHmrStrategy extends HmrStrategy {
|
|
|
82
88
|
const entrypointDeps = buildResult.dependencies.get(path.resolve(entrypoint)) ?? [];
|
|
83
89
|
this.context.getEntrypointDependencyGraph().setEntrypointDependencies(entrypoint, entrypointDeps);
|
|
84
90
|
}
|
|
85
|
-
const
|
|
86
|
-
const relativePath = path.relative(srcDir, entrypoint);
|
|
87
|
-
const relativePathJs = relativePath.replace(/\.(tsx?|jsx?|mdx?)$/, ".js");
|
|
88
|
-
const outputPath = path.join(this.context.getDistDir(), relativePathJs);
|
|
91
|
+
const outputPath = this.resolveEntrypointOutputPath(entrypoint);
|
|
89
92
|
const result = await this.processOutput(outputPath, outputUrl);
|
|
90
93
|
if (result.success) {
|
|
91
94
|
updates.push(outputUrl);
|
|
@@ -113,6 +116,12 @@ class JsHmrStrategy extends HmrStrategy {
|
|
|
113
116
|
}
|
|
114
117
|
return { type: "none" };
|
|
115
118
|
}
|
|
119
|
+
resolveEntrypointOutputPath(entrypointPath) {
|
|
120
|
+
return resolveHmrEntrypointOutputPaths(this.context.getSrcDir(), this.context.getDistDir(), entrypointPath).outputPath;
|
|
121
|
+
}
|
|
122
|
+
removeStaleEntrypointOutput(outputPath) {
|
|
123
|
+
removeStaleHmrEntrypointOutput(outputPath, "JsHmrStrategy");
|
|
124
|
+
}
|
|
116
125
|
/**
|
|
117
126
|
* Bundles one or more entrypoints in a single build invocation.
|
|
118
127
|
* Uses the source directory as the output base so that the directory structure
|
|
@@ -120,6 +129,30 @@ class JsHmrStrategy extends HmrStrategy {
|
|
|
120
129
|
*/
|
|
121
130
|
async bundleEntrypoints(entrypoints) {
|
|
122
131
|
try {
|
|
132
|
+
if (entrypoints.length === 1) {
|
|
133
|
+
const entrypoint = entrypoints[0];
|
|
134
|
+
const outputPath = this.resolveEntrypointOutputPath(entrypoint);
|
|
135
|
+
const naming = path.relative(this.context.getDistDir(), outputPath).split(path.sep).join("/");
|
|
136
|
+
const result2 = await this.context.getBrowserBundleService().bundle({
|
|
137
|
+
profile: "hmr-entrypoint",
|
|
138
|
+
entrypoints: [entrypoint],
|
|
139
|
+
outdir: this.context.getDistDir(),
|
|
140
|
+
naming,
|
|
141
|
+
plugins: this.context.getPlugins(),
|
|
142
|
+
minify: false
|
|
143
|
+
});
|
|
144
|
+
if (!result2.success) {
|
|
145
|
+
appLogger.error("[JsHmrStrategy] Entrypoint build failed:", result2.logs);
|
|
146
|
+
return { success: false };
|
|
147
|
+
}
|
|
148
|
+
const dependencies2 = /* @__PURE__ */ new Map();
|
|
149
|
+
if (result2.dependencyGraph?.entrypoints) {
|
|
150
|
+
for (const [resolvedEntrypoint, deps] of Object.entries(result2.dependencyGraph.entrypoints)) {
|
|
151
|
+
dependencies2.set(path.resolve(resolvedEntrypoint), deps);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return { success: true, dependencies: dependencies2 };
|
|
155
|
+
}
|
|
123
156
|
const result = await this.context.getBrowserBundleService().bundle({
|
|
124
157
|
profile: "hmr-entrypoint",
|
|
125
158
|
entrypoints,
|