@absolutejs/absolute 0.19.0-beta.999 → 0.20.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -13
- package/README.md +48 -2
- package/dist/angular/browser.js +82 -77
- package/dist/angular/browser.js.map +11 -11
- package/dist/angular/components/constants.js +43 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/angular/hmrPreserveCore.ts +132 -134
- package/dist/angular/index.js +1719 -844
- package/dist/angular/index.js.map +34 -26
- package/dist/angular/server.js +1620 -768
- package/dist/angular/server.js.map +28 -20
- package/dist/build.js +4935 -2593
- package/dist/build.js.map +72 -57
- package/dist/cli/config/client.js +578 -0
- package/dist/cli/config/server.js +39587 -0
- package/dist/cli/htmx/htmx.min.js +1 -0
- package/dist/cli/index.js +16828 -3511
- package/dist/client/index.js +49 -46
- package/dist/client/index.js.map +12 -12
- package/dist/core/streamingSlotRegistrar.js +1 -19
- package/dist/core/streamingSlotRegistrar.js.map +2 -2
- package/dist/core/streamingSlotRegistry.js +1 -19
- package/dist/core/streamingSlotRegistry.js.map +2 -2
- package/dist/dev/client/cssUtils.ts +98 -41
- package/dist/dev/client/domState.ts +2 -0
- package/dist/dev/client/errorOverlay.ts +14 -13
- package/dist/dev/client/handlers/angularHmrShim.ts +20 -20
- package/dist/dev/client/handlers/angularRemount.ts +74 -55
- package/dist/dev/client/handlers/angularRemountWiring.ts +1 -2
- package/dist/dev/client/handlers/html.ts +144 -41
- package/dist/dev/client/handlers/htmx.ts +43 -8
- package/dist/dev/client/handlers/react.ts +114 -32
- package/dist/dev/client/handlers/rebuild.ts +28 -8
- package/dist/dev/client/handlers/svelte.ts +92 -51
- package/dist/dev/client/handlers/vue.ts +36 -45
- package/dist/dev/client/hmrClient.ts +101 -26
- package/dist/dev/client/hmrTiming.ts +141 -0
- package/dist/dev/client/hmrToast.ts +22 -24
- package/dist/dev/client/reactRefreshSetup.ts +4 -0
- package/dist/dev/client/vendor/reactRefreshRuntime.d.ts +12 -0
- package/dist/dev/client/vendor/reactRefreshRuntime.js +313 -0
- package/dist/dev/serverBootstrap.js +45 -0
- package/dist/index.js +7153 -3224
- package/dist/index.js.map +118 -86
- package/dist/islands/browser.js +1 -19
- package/dist/islands/browser.js.map +3 -3
- package/dist/islands/index.js +709 -120
- package/dist/islands/index.js.map +18 -13
- package/dist/mobile/browser.js +428 -0
- package/dist/mobile/browser.js.map +12 -0
- package/dist/mobile/index.js +3058 -0
- package/dist/mobile/index.js.map +35 -0
- package/dist/react/browser.js +13 -62
- package/dist/react/browser.js.map +5 -6
- package/dist/react/components/browser/index.js +23 -13
- package/dist/react/components/index.js +30 -34
- package/dist/react/components/index.js.map +8 -7
- package/dist/react/hooks/index.js +1 -19
- package/dist/react/hooks/index.js.map +3 -3
- package/dist/react/index.js +1643 -679
- package/dist/react/index.js.map +29 -20
- package/dist/react/jsxDevRuntimeCompat.js +22 -20
- package/dist/react/jsxDevRuntimeCompat.js.map +5 -4
- package/dist/react/jsxRuntimeCompat.js +90 -0
- package/dist/react/jsxRuntimeCompat.js.map +10 -0
- package/dist/react/router/browser.js +77 -0
- package/dist/react/router/browser.js.map +10 -0
- package/dist/react/router/index.js +77 -0
- package/dist/react/router/index.js.map +10 -0
- package/dist/react/server.js +950 -565
- package/dist/react/server.js.map +16 -11
- package/dist/src/angular/components/constants.d.ts +21 -0
- package/dist/src/angular/hmrPreserveCore.d.ts +7 -20
- package/dist/src/angular/islands.d.ts +1 -1
- package/dist/src/angular/pageHandler.d.ts +2 -0
- package/dist/src/angular/ssrRender.d.ts +4 -1
- package/dist/src/build/bunStringRawUnicodePlugin.d.ts +12 -0
- package/dist/src/build/chainInlineSourcemaps.d.ts +1 -0
- package/dist/src/build/compileAngular.d.ts +5 -7
- package/dist/src/build/compileSvelte.d.ts +3 -0
- package/dist/src/build/compileVue.d.ts +3 -1
- package/dist/src/build/generateReactIndexes.d.ts +1 -0
- package/dist/src/build/islandRegistryTransform.d.ts +17 -0
- package/dist/src/build/maskLiterals.d.ts +28 -0
- package/dist/src/build/parseVueSpaRoutes.d.ts +5 -0
- package/dist/src/build/resolveBuildMode.d.ts +7 -0
- package/dist/src/build/serverExternals.d.ts +14 -0
- package/dist/src/build/spaSideManifests.d.ts +16 -0
- package/dist/src/build/tailwindCompiler.d.ts +0 -1
- package/dist/src/cli/add/dependencies.d.ts +13 -0
- package/dist/src/cli/config/absolute/AbsoluteConfigPanel.d.ts +6 -0
- package/dist/src/cli/config/absolute/editAbsoluteConfig.d.ts +5 -0
- package/dist/src/cli/config/absolute/resolveAbsoluteConfig.d.ts +19 -0
- package/dist/src/cli/config/auth/AuthPanel.d.ts +6 -0
- package/dist/src/cli/config/auth/authCatalog.d.ts +10 -0
- package/dist/src/cli/config/auth/authScaffolds.d.ts +16 -0
- package/dist/src/cli/config/auth/editAuthConfig.d.ts +5 -0
- package/dist/src/cli/config/auth/resolveAuthSettings.d.ts +14 -0
- package/dist/src/cli/config/auth/resolveAuthState.d.ts +2 -0
- package/dist/src/cli/config/auth/scaffoldAuthFeature.d.ts +6 -0
- package/dist/src/cli/config/client.d.ts +1 -0
- package/dist/src/cli/config/configCert.d.ts +12 -0
- package/dist/src/cli/config/eslint/EslintPanel.d.ts +6 -0
- package/dist/src/cli/config/eslint/configAst.d.ts +18 -0
- package/dist/src/cli/config/eslint/editConfigRule.d.ts +6 -0
- package/dist/src/cli/config/eslint/eslintStyles.d.ts +1 -0
- package/dist/src/cli/config/eslint/resolveConfig.d.ts +3 -0
- package/dist/src/cli/config/eslint/serializeValue.d.ts +9 -0
- package/dist/src/cli/config/guards.d.ts +4 -0
- package/dist/src/cli/config/integrations/IntegrationsPanel.d.ts +6 -0
- package/dist/src/cli/config/packageJson/PackageJsonPanel.d.ts +6 -0
- package/dist/src/cli/config/packageJson/editPackageJson.d.ts +9 -0
- package/dist/src/cli/config/packageJson/resolvePackageJson.d.ts +8 -0
- package/dist/src/cli/config/page/ConfigShell.d.ts +6 -0
- package/dist/src/cli/config/page/FieldEditor.d.ts +9 -0
- package/dist/src/cli/config/page/PanelHost.d.ts +6 -0
- package/dist/src/cli/config/page/configStyles.d.ts +1 -0
- package/dist/src/cli/config/panels.d.ts +7 -0
- package/dist/src/cli/config/prettier/PrettierPanel.d.ts +6 -0
- package/dist/src/cli/config/prettier/editPrettier.d.ts +5 -0
- package/dist/src/cli/config/prettier/resolvePrettier.d.ts +11 -0
- package/dist/src/cli/config/schema/fromJsonSchema.d.ts +3 -0
- package/dist/src/cli/config/schema/fromType.d.ts +1 -0
- package/dist/src/cli/config/schema/serialize.d.ts +1 -0
- package/dist/src/cli/config/server.d.ts +527 -0
- package/dist/src/cli/config/tsconfig/TsconfigPanel.d.ts +6 -0
- package/dist/src/cli/config/tsconfig/editTsconfig.d.ts +5 -0
- package/dist/src/cli/config/tsconfig/resolveTsconfig.d.ts +8 -0
- package/dist/src/cli/config/tsconfig/tsconfigStyles.d.ts +1 -0
- package/dist/src/cli/discoverInstances.d.ts +5 -0
- package/dist/src/cli/elysiaOpenApiTypeboxPlugin.d.ts +8 -0
- package/dist/src/cli/generate/componentTemplates.d.ts +7 -0
- package/dist/src/cli/generate/context.d.ts +30 -0
- package/dist/src/cli/generate/cssStrategy.d.ts +20 -0
- package/dist/src/cli/generate/frameworkKey.d.ts +3 -0
- package/dist/src/cli/generate/frameworks.d.ts +40 -0
- package/dist/src/cli/generate/generateApi.d.ts +3 -0
- package/dist/src/cli/generate/generateComponent.d.ts +4 -0
- package/dist/src/cli/generate/generatePage.d.ts +4 -0
- package/dist/src/cli/generate/naming.d.ts +5 -0
- package/dist/src/cli/generate/navData.d.ts +10 -0
- package/dist/src/cli/generate/outcome.d.ts +17 -0
- package/dist/src/cli/generate/pageTemplates.d.ts +11 -0
- package/dist/src/cli/generate/routeWiring.d.ts +40 -0
- package/dist/src/cli/generate/staticNav.d.ts +5 -0
- package/dist/src/cli/heapDiff.d.ts +1 -0
- package/dist/src/cli/htmx/install.d.ts +6 -0
- package/dist/src/cli/inspectData.d.ts +12 -0
- package/dist/src/cli/inspectTui.d.ts +1 -0
- package/dist/src/cli/instanceStatus.d.ts +22 -0
- package/dist/src/cli/integrations/addPlugin.d.ts +8 -0
- package/dist/src/cli/integrations/catalog.d.ts +20 -0
- package/dist/src/cli/psTui.d.ts +1 -0
- package/dist/src/cli/scripts/add.d.ts +1 -0
- package/dist/src/cli/scripts/analyze.d.ts +1 -0
- package/dist/src/cli/scripts/api.d.ts +1 -0
- package/dist/src/cli/scripts/build.d.ts +1 -1
- package/dist/src/cli/scripts/db.d.ts +20 -0
- package/dist/src/cli/scripts/dev.d.ts +5 -1
- package/dist/src/cli/scripts/doctor.d.ts +1 -0
- package/dist/src/cli/scripts/env.d.ts +7 -0
- package/dist/src/cli/scripts/eslint.d.ts +37 -2
- package/dist/src/cli/scripts/eslintChunked.d.ts +37 -0
- package/dist/src/cli/scripts/generate.d.ts +1 -0
- package/dist/src/cli/scripts/htmx.d.ts +1 -0
- package/dist/src/cli/scripts/inspect.d.ts +1 -0
- package/dist/src/cli/scripts/islands.d.ts +1 -0
- package/dist/src/cli/scripts/lintProof.d.ts +42 -0
- package/dist/src/cli/scripts/logs.d.ts +1 -0
- package/dist/src/cli/scripts/ls.d.ts +1 -0
- package/dist/src/cli/scripts/mem.d.ts +1 -0
- package/dist/src/cli/scripts/mobile.d.ts +1 -0
- package/dist/src/cli/scripts/prettier.d.ts +2 -0
- package/dist/src/cli/scripts/ps.d.ts +1 -0
- package/dist/src/cli/scripts/remove.d.ts +1 -0
- package/dist/src/cli/scripts/routes.d.ts +1 -0
- package/dist/src/cli/scripts/start.d.ts +6 -1
- package/dist/src/cli/scripts/tunnelRelay.d.ts +9 -0
- package/dist/src/cli/scripts/workspace.d.ts +3 -1
- package/dist/src/cli/serverBundleExternals.d.ts +2 -0
- package/dist/src/cli/tuiPrimitives.d.ts +14 -0
- package/dist/src/cli/typeGraphCoherence.d.ts +32 -0
- package/dist/src/cli/utils.d.ts +3 -1
- package/dist/src/cli/workspaceTui.d.ts +2 -1
- package/dist/src/client/hydrators/react.d.ts +1 -1
- package/dist/src/client/hydrators/svelte.d.ts +1 -1
- package/dist/src/client/hydrators/vue.d.ts +1 -1
- package/dist/src/client/islandStore.d.ts +3 -3
- package/dist/src/client/preserveIslandMarkup.d.ts +4 -1
- package/dist/src/constants.d.ts +21 -0
- package/dist/src/core/angularServerModule.d.ts +1 -0
- package/dist/src/core/build.d.ts +11 -3
- package/dist/src/core/devRouteRegistrationCallsite.d.ts +1 -5
- package/dist/src/core/index.d.ts +1 -0
- package/dist/src/core/pageResponseCache.d.ts +23 -0
- package/dist/src/core/prepare.d.ts +192 -154
- package/dist/src/core/requestContext.d.ts +18 -0
- package/dist/src/dev/angular/fastHmrCompiler.d.ts +5 -3
- package/dist/src/dev/angular/hmrCompiler.d.ts +1 -1
- package/dist/src/dev/angular/resolveOwningComponents.d.ts +1 -1
- package/dist/src/dev/clientManager.d.ts +10 -1
- package/dist/src/dev/configResolver.d.ts +2 -0
- package/dist/src/dev/moduleMapper.d.ts +1 -1
- package/dist/src/dev/moduleServer.d.ts +2 -1
- package/dist/src/dev/pathUtils.d.ts +1 -1
- package/dist/src/dev/reactComponentClassifier.d.ts +1 -1
- package/dist/src/dev/rebuildTrigger.d.ts +4 -0
- package/dist/src/dev/requestInspector.d.ts +31 -0
- package/dist/src/dev/serverBootstrap.d.ts +1 -0
- package/dist/src/dev/serverEntryWatcher.d.ts +3 -3
- package/dist/src/dev/tunnel/client.d.ts +20 -0
- package/dist/src/dev/tunnel/protocol.d.ts +85 -0
- package/dist/src/dev/tunnel/relay.d.ts +28 -0
- package/dist/src/dev/webSocket.d.ts +1 -1
- package/dist/src/mobile/androidConformance.d.ts +42 -0
- package/dist/src/mobile/androidEmulatorController.d.ts +99 -0
- package/dist/src/mobile/androidNativeWatcher.d.ts +19 -0
- package/dist/src/mobile/androidRelease.d.ts +47 -0
- package/dist/src/mobile/androidWebView.d.ts +46 -0
- package/dist/src/mobile/artifactStore.d.ts +47 -0
- package/dist/src/mobile/associationFiles.d.ts +49 -0
- package/dist/src/mobile/browser.d.ts +2 -0
- package/dist/src/mobile/buildMetadata.d.ts +10 -0
- package/dist/src/mobile/buildPipeline.d.ts +8 -0
- package/dist/src/mobile/buildRelease.d.ts +24 -0
- package/dist/src/mobile/capacitorBundle.d.ts +28 -0
- package/dist/src/mobile/capacitorProject.d.ts +9 -0
- package/dist/src/mobile/client.d.ts +35 -0
- package/dist/src/mobile/compatibilityDispatcher.d.ts +26 -0
- package/dist/src/mobile/config.d.ts +16 -0
- package/dist/src/mobile/emulatorDoctor.d.ts +25 -0
- package/dist/src/mobile/emulatorInstaller.d.ts +41 -0
- package/dist/src/mobile/index.d.ts +19 -0
- package/dist/src/mobile/materializedBundle.d.ts +36 -0
- package/dist/src/mobile/nativeDeepLinks.d.ts +5 -0
- package/dist/src/mobile/pageProtocol.d.ts +89 -0
- package/dist/src/mobile/producerContext.d.ts +4 -0
- package/dist/src/mobile/producerContextState.d.ts +10 -0
- package/dist/src/mobile/releaseArtifact.d.ts +75 -0
- package/dist/src/mobile/releaseDoctor.d.ts +13 -0
- package/dist/src/mobile/routeMatcher.d.ts +3 -0
- package/dist/src/mobile/routeMetadataTransform.d.ts +13 -0
- package/dist/src/mobile/shellBootstrap.d.ts +1 -0
- package/dist/src/mobile/transport.d.ts +31 -0
- package/dist/src/plugins/devtoolsJson.d.ts +6 -47
- package/dist/src/plugins/hmr.d.ts +22 -96
- package/dist/src/plugins/imageOptimizer.d.ts +150 -62
- package/dist/src/plugins/networking.d.ts +2 -2
- package/dist/src/plugins/openApiPlugin.d.ts +4 -0
- package/dist/src/plugins/telemetryPlugin.d.ts +36 -0
- package/dist/src/react/browser.d.ts +0 -2
- package/dist/src/react/hooks/useMediaQuery.d.ts +1 -1
- package/dist/src/react/index.d.ts +0 -2
- package/dist/src/react/jsxDevRuntimeCompat.d.ts +1 -1
- package/dist/src/react/jsxRuntimeCompat.d.ts +7 -0
- package/dist/src/react/pageHandler.d.ts +8 -0
- package/dist/src/react/router/UniversalRouter.d.ts +43 -0
- package/dist/src/react/router/browser.d.ts +2 -0
- package/dist/src/react/router/index.d.ts +2 -0
- package/dist/src/svelte/pageHandler.d.ts +5 -0
- package/dist/src/svelte/router/hashMode.d.ts +1 -6
- package/dist/src/svelte/router/matchPath.d.ts +4 -24
- package/dist/src/svelte/router/page.svelte.d.ts +1 -10
- package/dist/src/svelte/router/prefetchCache.d.ts +2 -6
- package/dist/src/utils/cleanup.d.ts +1 -0
- package/dist/src/utils/defineConvention.d.ts +2 -2
- package/dist/src/utils/defineEnv.d.ts +4 -4
- package/dist/src/utils/formatBytes.d.ts +2 -0
- package/dist/src/utils/generatedDir.d.ts +1 -1
- package/dist/src/utils/iconVersion.d.ts +5 -0
- package/dist/src/utils/imageProcessing.d.ts +1 -1
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/src/utils/inlinePageCss.d.ts +9 -0
- package/dist/src/utils/instanceRegistry.d.ts +13 -0
- package/dist/src/utils/isTestSourcePath.d.ts +1 -0
- package/dist/src/utils/jsonLd.d.ts +1 -1
- package/dist/src/utils/loadConfig.d.ts +11 -3
- package/dist/src/utils/logger.d.ts +2 -0
- package/dist/src/utils/portScan.d.ts +22 -0
- package/dist/src/utils/projectRoot.d.ts +17 -0
- package/dist/src/utils/resolveConvention.d.ts +1 -1
- package/dist/src/utils/resolveDevPort.d.ts +4 -1
- package/dist/src/utils/runtimeMode.d.ts +1 -1
- package/dist/src/utils/spaRouteCss.d.ts +10 -0
- package/dist/src/utils/spaRouteManifest.d.ts +8 -0
- package/dist/src/utils/stripStringsAndComments.d.ts +18 -0
- package/dist/src/utils/userAgentFunctions.d.ts +1 -1
- package/dist/src/utils/vueCompiler.d.ts +1 -0
- package/dist/src/vue/components/Image.d.ts +2 -2
- package/dist/src/vue/defineVuePage.d.ts +1 -11
- package/dist/src/vue/index.d.ts +3 -0
- package/dist/src/vue/pageHandler.d.ts +5 -0
- package/dist/src/vue/resolveGeneratedVueModulePath.d.ts +1 -0
- package/dist/src/vue/teleports.d.ts +2 -0
- package/dist/src/vue/useResource.d.ts +65 -0
- package/dist/svelte/browser.js +1 -19
- package/dist/svelte/browser.js.map +3 -3
- package/dist/svelte/components/Head.svelte +7 -1
- package/dist/svelte/index.js +1281 -543
- package/dist/svelte/index.js.map +27 -19
- package/dist/svelte/router/Link.svelte.d.ts +3 -3
- package/dist/svelte/router/Route.svelte.d.ts +5 -5
- package/dist/svelte/router/Router.svelte.d.ts +3 -3
- package/dist/svelte/router/hashMode.ts +6 -12
- package/dist/svelte/router/matchPath.ts +44 -61
- package/dist/svelte/router/page.d.ts +1 -10
- package/dist/svelte/router/page.js +6 -6
- package/dist/svelte/router/prefetchCache.ts +21 -23
- package/dist/svelte/router/viewTransitions.ts +22 -12
- package/dist/svelte/server.js +697 -565
- package/dist/svelte/server.js.map +14 -11
- package/dist/types/absoluteConfig.d.ts +22 -0
- package/dist/types/angular.d.ts +4 -1
- package/dist/types/authPanel.d.ts +62 -0
- package/dist/types/build.d.ts +116 -0
- package/dist/types/cli.d.ts +57 -0
- package/dist/types/config.d.ts +52 -0
- package/dist/types/eslintConfig.d.ts +68 -0
- package/dist/types/globals.d.ts +31 -10
- package/dist/types/image.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/integrationsPanel.d.ts +29 -0
- package/dist/types/messages.d.ts +12 -0
- package/dist/types/packageJson.d.ts +74 -0
- package/dist/types/packageJsonPanel.d.ts +29 -0
- package/dist/types/prettier.d.ts +26 -0
- package/dist/types/tsconfig.d.ts +31 -0
- package/dist/types/vue.d.ts +13 -15
- package/dist/vue/browser.js +14 -36
- package/dist/vue/browser.js.map +5 -5
- package/dist/vue/components/Image.js +3 -20
- package/dist/vue/components/Image.js.map +3 -3
- package/dist/vue/components/index.js +3 -20
- package/dist/vue/components/index.js.map +3 -3
- package/dist/vue/index.js +1573 -620
- package/dist/vue/index.js.map +34 -22
- package/dist/vue/server.js +800 -520
- package/dist/vue/server.js.map +17 -11
- package/package.json +145 -68
- package/dist/src/react/UniversalRouter.d.ts +0 -12
|
@@ -17,6 +17,7 @@ import { detectCurrentFramework } from '../frameworkDetect';
|
|
|
17
17
|
import type { ScriptInfo } from '../../../types/client';
|
|
18
18
|
import { restoreDOMChanges, snapshotDOMChanges } from '../domTracker';
|
|
19
19
|
import { hmrState } from '../hmrState';
|
|
20
|
+
import { sendAbsoluteHmrTiming } from '../hmrTiming';
|
|
20
21
|
|
|
21
22
|
const parseHTMLMessage = (
|
|
22
23
|
html: string | { body?: string; head?: string } | null | undefined
|
|
@@ -57,11 +58,10 @@ const handleHTMLBodyWithHead = (
|
|
|
57
58
|
|
|
58
59
|
const cssResult = processCSSLinks(htmlHead);
|
|
59
60
|
|
|
60
|
-
const updateBodyAfterCSS = () =>
|
|
61
|
+
const updateBodyAfterCSS = () =>
|
|
61
62
|
updateHTMLBody(htmlBody, htmlDomState, document.body);
|
|
62
|
-
};
|
|
63
63
|
|
|
64
|
-
waitForCSSAndUpdate(cssResult, updateBodyAfterCSS);
|
|
64
|
+
return waitForCSSAndUpdate(cssResult, updateBodyAfterCSS);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
const handleHTMLBodyWithoutHead = (
|
|
@@ -72,17 +72,21 @@ const handleHTMLBodyWithoutHead = (
|
|
|
72
72
|
if (!container) {
|
|
73
73
|
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
74
74
|
|
|
75
|
-
return;
|
|
75
|
+
return Promise.resolve();
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
updateHTMLBodyDirect(htmlBody, htmlDomState, container);
|
|
78
|
+
const updated = updateHTMLBodyDirect(htmlBody, htmlDomState, container);
|
|
79
79
|
restoreDOMState(container, htmlDomState);
|
|
80
|
+
|
|
81
|
+
return updated;
|
|
80
82
|
};
|
|
81
83
|
|
|
82
84
|
export const handleHTMLUpdate = (message: {
|
|
83
85
|
data: {
|
|
84
86
|
html?: string | { body?: string; head?: string } | null;
|
|
87
|
+
serverDuration?: number;
|
|
85
88
|
};
|
|
89
|
+
timestamp?: number;
|
|
86
90
|
}) => {
|
|
87
91
|
const htmlFrameworkCheck = detectCurrentFramework();
|
|
88
92
|
if (htmlFrameworkCheck !== 'html') {
|
|
@@ -94,6 +98,7 @@ export const handleHTMLUpdate = (message: {
|
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
sessionStorage.setItem('__HMR_ACTIVE__', 'true');
|
|
101
|
+
const clientStart = performance.now();
|
|
97
102
|
|
|
98
103
|
const htmlDomState = saveDOMState(document.body);
|
|
99
104
|
const { body: htmlBody, head: htmlHead } = parseHTMLMessage(
|
|
@@ -102,18 +107,48 @@ export const handleHTMLUpdate = (message: {
|
|
|
102
107
|
|
|
103
108
|
if (!htmlBody) {
|
|
104
109
|
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
110
|
+
sendAbsoluteHmrTiming({
|
|
111
|
+
clientStart,
|
|
112
|
+
kind: 'html',
|
|
113
|
+
outcome: 'failed',
|
|
114
|
+
serverMs: message.data.serverDuration,
|
|
115
|
+
updateId: message.timestamp
|
|
116
|
+
});
|
|
105
117
|
|
|
106
118
|
return;
|
|
107
119
|
}
|
|
108
120
|
|
|
109
|
-
|
|
110
|
-
handleHTMLBodyWithHead(htmlBody, htmlHead, htmlDomState)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
121
|
+
const update = htmlHead
|
|
122
|
+
? handleHTMLBodyWithHead(htmlBody, htmlHead, htmlDomState)
|
|
123
|
+
: handleHTMLBodyWithoutHead(htmlBody, htmlDomState);
|
|
124
|
+
void update.then(
|
|
125
|
+
() => {
|
|
126
|
+
sendAbsoluteHmrTiming({
|
|
127
|
+
clientStart,
|
|
128
|
+
kind: 'html',
|
|
129
|
+
serverMs: message.data.serverDuration,
|
|
130
|
+
updateId: message.timestamp
|
|
131
|
+
});
|
|
132
|
+
},
|
|
133
|
+
() => {
|
|
134
|
+
sendAbsoluteHmrTiming({
|
|
135
|
+
clientStart,
|
|
136
|
+
kind: 'html',
|
|
137
|
+
outcome: 'reloaded',
|
|
138
|
+
serverMs: message.data.serverDuration,
|
|
139
|
+
updateId: message.timestamp
|
|
140
|
+
});
|
|
141
|
+
window.location.reload();
|
|
142
|
+
}
|
|
143
|
+
);
|
|
114
144
|
};
|
|
115
145
|
export const handleScriptUpdate = (message: {
|
|
116
|
-
data: {
|
|
146
|
+
data: {
|
|
147
|
+
framework?: string;
|
|
148
|
+
scriptPath?: string;
|
|
149
|
+
serverDuration?: number;
|
|
150
|
+
};
|
|
151
|
+
timestamp?: number;
|
|
117
152
|
}) => {
|
|
118
153
|
const scriptFramework = message.data.framework;
|
|
119
154
|
const currentFw = detectCurrentFramework();
|
|
@@ -139,13 +174,30 @@ export const handleScriptUpdate = (message: {
|
|
|
139
174
|
});
|
|
140
175
|
|
|
141
176
|
const cacheBustedPath = `${scriptPath}?t=${Date.now()}`;
|
|
177
|
+
const clientStart = performance.now();
|
|
142
178
|
import(cacheBustedPath)
|
|
143
|
-
.then(() =>
|
|
179
|
+
.then(() => {
|
|
180
|
+
sendAbsoluteHmrTiming({
|
|
181
|
+
clientStart,
|
|
182
|
+
kind: 'script',
|
|
183
|
+
serverMs: message.data.serverDuration,
|
|
184
|
+
updateId: message.timestamp
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return true;
|
|
188
|
+
})
|
|
144
189
|
.catch((err: unknown) => {
|
|
145
190
|
console.error(
|
|
146
191
|
'[HMR] Script hot-reload failed, falling back to page reload:',
|
|
147
192
|
err
|
|
148
193
|
);
|
|
194
|
+
sendAbsoluteHmrTiming({
|
|
195
|
+
clientStart,
|
|
196
|
+
kind: 'script',
|
|
197
|
+
outcome: 'reloaded',
|
|
198
|
+
serverMs: message.data.serverDuration,
|
|
199
|
+
updateId: message.timestamp
|
|
200
|
+
});
|
|
149
201
|
window.location.reload();
|
|
150
202
|
});
|
|
151
203
|
};
|
|
@@ -172,21 +224,30 @@ const updateHTMLBody = (
|
|
|
172
224
|
container: HTMLElement
|
|
173
225
|
) => {
|
|
174
226
|
if (!container) {
|
|
175
|
-
return;
|
|
227
|
+
return Promise.resolve();
|
|
176
228
|
}
|
|
229
|
+
const { promise, resolve } = Promise.withResolvers<void>();
|
|
177
230
|
|
|
178
231
|
const savedState = saveHTMLState();
|
|
179
232
|
const domSnapshot = snapshotDOMChanges(container);
|
|
180
233
|
|
|
181
234
|
const existingScripts = collectScripts(container);
|
|
235
|
+
const oldInlineScripts = collectInlineScripts(container);
|
|
182
236
|
const hmrScript = container.querySelector('script[data-hmr-client]');
|
|
183
237
|
const tempDiv = document.createElement('div');
|
|
184
238
|
tempDiv.innerHTML = htmlBody;
|
|
185
239
|
const newScripts = collectScriptsFromElement(tempDiv);
|
|
240
|
+
const newInlineScripts = collectInlineScripts(tempDiv);
|
|
186
241
|
|
|
187
242
|
const htmlStructureChanged = didHTMLStructureChange(container, tempDiv);
|
|
243
|
+
const inlineScriptsChanged = didInlineScriptsChange(
|
|
244
|
+
oldInlineScripts,
|
|
245
|
+
newInlineScripts
|
|
246
|
+
);
|
|
247
|
+
const scriptsChanged =
|
|
248
|
+
didScriptsChange(existingScripts, newScripts) || inlineScriptsChanged;
|
|
188
249
|
|
|
189
|
-
if (htmlStructureChanged ||
|
|
250
|
+
if (htmlStructureChanged || scriptsChanged) {
|
|
190
251
|
patchDOMInPlace(container, htmlBody);
|
|
191
252
|
restoreDOMChanges(container, domSnapshot, htmlBody);
|
|
192
253
|
}
|
|
@@ -198,29 +259,27 @@ const updateHTMLBody = (
|
|
|
198
259
|
restoreFormState(savedState.forms);
|
|
199
260
|
restoreScrollState(savedState.scroll);
|
|
200
261
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
) {
|
|
205
|
-
|
|
206
|
-
|
|
262
|
+
// Only touch scripts/interactive elements when a script actually
|
|
263
|
+
// changed. A pure markup edit (e.g. a heading) leaves inline-script
|
|
264
|
+
// state and `addEventListener` handlers intact.
|
|
265
|
+
if (scriptsChanged) {
|
|
266
|
+
// Clone (which strips listeners via cloneNode) ONLY when an inline
|
|
267
|
+
// script changed: a changed inline script re-runs in place below
|
|
268
|
+
// and would otherwise double-bind on elements that still carry the
|
|
269
|
+
// old handler. Unchanged inline scripts are skipped on re-exec, and
|
|
270
|
+
// external modules are re-imported via `import()` whose module cache
|
|
271
|
+
// means an unchanged body never re-runs — cloning for those would
|
|
272
|
+
// orphan their listeners forever (the regression this fixes).
|
|
273
|
+
if (inlineScriptsChanged) {
|
|
274
|
+
cloneInteractiveElements(container);
|
|
275
|
+
}
|
|
276
|
+
reExecuteScripts(container, newScripts, oldInlineScripts);
|
|
207
277
|
}
|
|
278
|
+
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
279
|
+
resolve();
|
|
208
280
|
});
|
|
209
|
-
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
210
|
-
};
|
|
211
281
|
|
|
212
|
-
|
|
213
|
-
container
|
|
214
|
-
.querySelectorAll('[data-hmr-listeners-attached]')
|
|
215
|
-
.forEach((elem) => {
|
|
216
|
-
const cloned = elem.cloneNode(true);
|
|
217
|
-
if (elem.parentNode) {
|
|
218
|
-
elem.parentNode.replaceChild(cloned, elem);
|
|
219
|
-
}
|
|
220
|
-
if (cloned instanceof Element) {
|
|
221
|
-
cloned.removeAttribute('data-hmr-listeners-attached');
|
|
222
|
-
}
|
|
223
|
-
});
|
|
282
|
+
return promise;
|
|
224
283
|
};
|
|
225
284
|
|
|
226
285
|
const replaceInlineScript = (script: Element) => {
|
|
@@ -242,9 +301,11 @@ const updateHTMLBodyDirect = (
|
|
|
242
301
|
htmlDomState: ReturnType<typeof saveDOMState>,
|
|
243
302
|
container: HTMLElement
|
|
244
303
|
) => {
|
|
304
|
+
const { promise, resolve } = Promise.withResolvers<void>();
|
|
245
305
|
const savedState = saveHTMLState();
|
|
246
306
|
const domSnapshot = snapshotDOMChanges(container);
|
|
247
307
|
|
|
308
|
+
const oldInlineScripts = collectInlineScripts(container);
|
|
248
309
|
const tempDiv = document.createElement('div');
|
|
249
310
|
tempDiv.innerHTML = htmlBody;
|
|
250
311
|
const newScripts = collectScriptsFromElement(tempDiv);
|
|
@@ -260,7 +321,13 @@ const updateHTMLBodyDirect = (
|
|
|
260
321
|
restoreFormState(savedState.forms);
|
|
261
322
|
restoreScrollState(savedState.scroll);
|
|
262
323
|
|
|
263
|
-
|
|
324
|
+
// Unlike `updateHTMLBody` (which re-imports externals as ES modules and
|
|
325
|
+
// must not clone unchanged ones), this path rebuilds EVERY external
|
|
326
|
+
// script below as a fresh `<script src?t=>` tag that always
|
|
327
|
+
// re-executes. So a single clone here is correct and necessary: it
|
|
328
|
+
// gives each re-running script a pristine element to bind once, with no
|
|
329
|
+
// double-binding.
|
|
330
|
+
cloneInteractiveElements(container);
|
|
264
331
|
|
|
265
332
|
removeOldScripts(container);
|
|
266
333
|
newScripts.forEach((scriptInfo) => {
|
|
@@ -271,10 +338,12 @@ const updateHTMLBodyDirect = (
|
|
|
271
338
|
container.appendChild(newScript);
|
|
272
339
|
});
|
|
273
340
|
|
|
274
|
-
|
|
275
|
-
|
|
341
|
+
reExecuteInlineScripts(container, oldInlineScripts);
|
|
342
|
+
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
343
|
+
resolve();
|
|
276
344
|
});
|
|
277
|
-
|
|
345
|
+
|
|
346
|
+
return promise;
|
|
278
347
|
};
|
|
279
348
|
|
|
280
349
|
/* Shared helpers for HTML body updates */
|
|
@@ -291,6 +360,18 @@ const collectScriptsFromElement = (elem: HTMLElement) =>
|
|
|
291
360
|
type: script.getAttribute('type') || 'text/javascript'
|
|
292
361
|
}));
|
|
293
362
|
|
|
363
|
+
/* Inline (non-src) scripts, excluding the HMR client. Captured by ordinal so
|
|
364
|
+
* an unchanged inline script can be skipped on re-execution — re-running it
|
|
365
|
+
* would reset its module/global state (e.g. `let count = 0`) on every edit. */
|
|
366
|
+
const collectInlineScripts = (elem: HTMLElement) =>
|
|
367
|
+
Array.from(
|
|
368
|
+
elem.querySelectorAll('script:not([src]):not([data-hmr-client])')
|
|
369
|
+
).map((script) => script.textContent || '');
|
|
370
|
+
|
|
371
|
+
const didInlineScriptsChange = (oldInline: string[], newInline: string[]) =>
|
|
372
|
+
oldInline.length !== newInline.length ||
|
|
373
|
+
oldInline.some((content, idx) => content !== newInline[idx]);
|
|
374
|
+
|
|
294
375
|
const didScriptsChange = (oldScripts: ScriptInfo[], newScripts: ScriptInfo[]) =>
|
|
295
376
|
oldScripts.length !== newScripts.length ||
|
|
296
377
|
oldScripts.some((oldScript, idx) => {
|
|
@@ -348,7 +429,11 @@ const removeOldScripts = (container: HTMLElement) => {
|
|
|
348
429
|
});
|
|
349
430
|
};
|
|
350
431
|
|
|
351
|
-
const reExecuteScripts = (
|
|
432
|
+
const reExecuteScripts = (
|
|
433
|
+
container: HTMLElement,
|
|
434
|
+
newScripts: ScriptInfo[],
|
|
435
|
+
oldInlineScripts: string[]
|
|
436
|
+
) => {
|
|
352
437
|
removeOldScripts(container);
|
|
353
438
|
|
|
354
439
|
newScripts.forEach((scriptInfo) => {
|
|
@@ -359,6 +444,24 @@ const reExecuteScripts = (container: HTMLElement, newScripts: ScriptInfo[]) => {
|
|
|
359
444
|
container.appendChild(newScript);
|
|
360
445
|
});
|
|
361
446
|
|
|
362
|
-
|
|
363
|
-
|
|
447
|
+
reExecuteInlineScripts(container, oldInlineScripts);
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
/* Re-execute inline scripts by replacing them with fresh nodes, but skip any
|
|
451
|
+
* whose textContent is byte-identical to its previous counterpart (matched by
|
|
452
|
+
* ordinal). Skipping leaves the original execution's global bindings intact,
|
|
453
|
+
* so unrelated edits don't reset inline-script state. */
|
|
454
|
+
const reExecuteInlineScripts = (
|
|
455
|
+
container: HTMLElement,
|
|
456
|
+
oldInlineScripts: string[]
|
|
457
|
+
) => {
|
|
458
|
+
const inlineScripts = container.querySelectorAll(
|
|
459
|
+
'script:not([src]):not([data-hmr-client])'
|
|
460
|
+
);
|
|
461
|
+
inlineScripts.forEach((script, idx) => {
|
|
462
|
+
if (oldInlineScripts[idx] === (script.textContent || '')) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
replaceInlineScript(script);
|
|
466
|
+
});
|
|
364
467
|
};
|
|
@@ -16,6 +16,7 @@ import { patchHeadInPlace } from '../headPatch';
|
|
|
16
16
|
import { detectCurrentFramework } from '../frameworkDetect';
|
|
17
17
|
import { type HTMXSavedState, type ScriptInfo } from '../../../types/client';
|
|
18
18
|
import { hmrState } from '../hmrState';
|
|
19
|
+
import { sendAbsoluteHmrTiming } from '../hmrTiming';
|
|
19
20
|
|
|
20
21
|
const parseHTMXMessage = (
|
|
21
22
|
html: string | { body?: string; head?: string } | null | undefined
|
|
@@ -52,23 +53,26 @@ const handleHTMXBodyUpdate = (
|
|
|
52
53
|
htmxHead: string | null,
|
|
53
54
|
htmxDomState: ReturnType<typeof saveDOMState>
|
|
54
55
|
) => {
|
|
55
|
-
const updateHTMXBodyAfterCSS = () =>
|
|
56
|
+
const updateHTMXBodyAfterCSS = () =>
|
|
56
57
|
updateHTMXBody(htmxBody, htmxDomState, document.body);
|
|
57
|
-
};
|
|
58
58
|
|
|
59
59
|
if (htmxHead) {
|
|
60
60
|
applyHeadPatch(htmxHead);
|
|
61
|
+
|
|
61
62
|
const cssResult = processCSSLinks(htmxHead);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
updateHTMXBodyAfterCSS();
|
|
63
|
+
|
|
64
|
+
return waitForCSSAndUpdate(cssResult, updateHTMXBodyAfterCSS);
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
return updateHTMXBodyAfterCSS();
|
|
66
68
|
};
|
|
67
69
|
|
|
68
70
|
export const handleHTMXUpdate = (message: {
|
|
69
71
|
data: {
|
|
70
72
|
html?: string | { body?: string; head?: string } | null;
|
|
73
|
+
serverDuration?: number;
|
|
71
74
|
};
|
|
75
|
+
timestamp?: number;
|
|
72
76
|
}) => {
|
|
73
77
|
const htmxFrameworkCheck = detectCurrentFramework();
|
|
74
78
|
if (htmxFrameworkCheck !== 'htmx') return;
|
|
@@ -78,6 +82,7 @@ export const handleHTMXUpdate = (message: {
|
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
sessionStorage.setItem('__HMR_ACTIVE__', 'true');
|
|
85
|
+
const clientStart = performance.now();
|
|
81
86
|
|
|
82
87
|
const htmxDomState = saveDOMState(document.body);
|
|
83
88
|
const { body: htmxBody, head: htmxHead } = parseHTMXMessage(
|
|
@@ -86,11 +91,37 @@ export const handleHTMXUpdate = (message: {
|
|
|
86
91
|
|
|
87
92
|
if (!htmxBody) {
|
|
88
93
|
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
94
|
+
sendAbsoluteHmrTiming({
|
|
95
|
+
clientStart,
|
|
96
|
+
kind: 'htmx',
|
|
97
|
+
outcome: 'failed',
|
|
98
|
+
serverMs: message.data.serverDuration,
|
|
99
|
+
updateId: message.timestamp
|
|
100
|
+
});
|
|
89
101
|
|
|
90
102
|
return;
|
|
91
103
|
}
|
|
92
104
|
|
|
93
|
-
handleHTMXBodyUpdate(htmxBody, htmxHead, htmxDomState)
|
|
105
|
+
void handleHTMXBodyUpdate(htmxBody, htmxHead, htmxDomState).then(
|
|
106
|
+
() => {
|
|
107
|
+
sendAbsoluteHmrTiming({
|
|
108
|
+
clientStart,
|
|
109
|
+
kind: 'htmx',
|
|
110
|
+
serverMs: message.data.serverDuration,
|
|
111
|
+
updateId: message.timestamp
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
() => {
|
|
115
|
+
sendAbsoluteHmrTiming({
|
|
116
|
+
clientStart,
|
|
117
|
+
kind: 'htmx',
|
|
118
|
+
outcome: 'reloaded',
|
|
119
|
+
serverMs: message.data.serverDuration,
|
|
120
|
+
updateId: message.timestamp
|
|
121
|
+
});
|
|
122
|
+
window.location.reload();
|
|
123
|
+
}
|
|
124
|
+
);
|
|
94
125
|
};
|
|
95
126
|
|
|
96
127
|
const cloneHmrListenerElements = (container: HTMLElement) => {
|
|
@@ -169,7 +200,8 @@ const updateHTMXBody = (
|
|
|
169
200
|
htmxDomState: ReturnType<typeof saveDOMState>,
|
|
170
201
|
container: HTMLElement
|
|
171
202
|
) => {
|
|
172
|
-
if (!container) return;
|
|
203
|
+
if (!container) return Promise.resolve();
|
|
204
|
+
const { promise, resolve } = Promise.withResolvers<void>();
|
|
173
205
|
|
|
174
206
|
const countSpan = container.querySelector('#count');
|
|
175
207
|
const countValue = countSpan
|
|
@@ -218,8 +250,11 @@ const updateHTMXBody = (
|
|
|
218
250
|
if (window.htmx) {
|
|
219
251
|
window.htmx.process(container);
|
|
220
252
|
}
|
|
253
|
+
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
254
|
+
resolve();
|
|
221
255
|
});
|
|
222
|
-
|
|
256
|
+
|
|
257
|
+
return promise;
|
|
223
258
|
};
|
|
224
259
|
|
|
225
260
|
/* Shared helpers */
|
|
@@ -6,9 +6,18 @@ import type {} from '../../../types/globals';
|
|
|
6
6
|
|
|
7
7
|
import { hideErrorOverlay } from '../errorOverlay';
|
|
8
8
|
import { detectCurrentFramework } from '../frameworkDetect';
|
|
9
|
+
import { sendAbsoluteHmrTiming } from '../hmrTiming';
|
|
10
|
+
import { swapCSSStylesheet } from '../cssUtils';
|
|
11
|
+
|
|
12
|
+
const reloadReactPage = () => {
|
|
13
|
+
const url = new URL(window.location.href);
|
|
14
|
+
url.searchParams.set('__absolute_hmr', Date.now().toString());
|
|
15
|
+
window.location.replace(url.href);
|
|
16
|
+
};
|
|
9
17
|
|
|
10
18
|
export const handleReactUpdate = (message: {
|
|
11
19
|
data: {
|
|
20
|
+
fastRefreshSupported?: boolean;
|
|
12
21
|
hasCSSChanges?: boolean;
|
|
13
22
|
hasComponentChanges?: boolean;
|
|
14
23
|
manifest?: Record<string, string>;
|
|
@@ -16,6 +25,7 @@ export const handleReactUpdate = (message: {
|
|
|
16
25
|
primarySource?: string;
|
|
17
26
|
serverDuration?: number;
|
|
18
27
|
};
|
|
28
|
+
timestamp?: number;
|
|
19
29
|
}) => {
|
|
20
30
|
const currentFramework = detectCurrentFramework();
|
|
21
31
|
if (currentFramework !== 'react') return;
|
|
@@ -24,52 +34,99 @@ export const handleReactUpdate = (message: {
|
|
|
24
34
|
const hasCSSChanges = message.data.hasCSSChanges === true;
|
|
25
35
|
const cssPath =
|
|
26
36
|
message.data.manifest && message.data.manifest.ReactExampleCSS;
|
|
27
|
-
|
|
28
37
|
if (!hasComponentChanges && hasCSSChanges && cssPath) {
|
|
29
|
-
|
|
38
|
+
const clientStart = performance.now();
|
|
39
|
+
void reloadReactCSS(cssPath).then((applied) => {
|
|
40
|
+
sendAbsoluteHmrTiming({
|
|
41
|
+
clientStart,
|
|
42
|
+
kind: 'css',
|
|
43
|
+
outcome: applied ? 'applied' : 'failed',
|
|
44
|
+
serverMs: message.data.serverDuration,
|
|
45
|
+
updateId: message.timestamp
|
|
46
|
+
});
|
|
47
|
+
});
|
|
30
48
|
|
|
31
49
|
return;
|
|
32
50
|
}
|
|
51
|
+
if (message.data.fastRefreshSupported === false) {
|
|
52
|
+
const { pageModuleUrl } = message.data;
|
|
53
|
+
const remount = window.__ABS_REACT_REMOUNT__;
|
|
54
|
+
if (pageModuleUrl && remount) {
|
|
55
|
+
applyRemountImport(
|
|
56
|
+
pageModuleUrl,
|
|
57
|
+
remount,
|
|
58
|
+
message.data.serverDuration,
|
|
59
|
+
message.timestamp
|
|
60
|
+
);
|
|
61
|
+
} else {
|
|
62
|
+
const clientStart = performance.now();
|
|
63
|
+
sendAbsoluteHmrTiming({
|
|
64
|
+
clientStart,
|
|
65
|
+
kind: 'component',
|
|
66
|
+
outcome: 'reloaded',
|
|
67
|
+
serverMs: message.data.serverDuration,
|
|
68
|
+
updateId: message.timestamp
|
|
69
|
+
});
|
|
70
|
+
reloadReactPage();
|
|
71
|
+
}
|
|
33
72
|
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
34
75
|
const refreshRuntime = window.$RefreshRuntime$;
|
|
35
76
|
const { serverDuration } = message.data;
|
|
36
77
|
const { pageModuleUrl } = message.data;
|
|
37
78
|
|
|
38
79
|
if (pageModuleUrl && refreshRuntime) {
|
|
39
|
-
applyRefreshImport(
|
|
80
|
+
applyRefreshImport(
|
|
81
|
+
pageModuleUrl,
|
|
82
|
+
refreshRuntime,
|
|
83
|
+
serverDuration,
|
|
84
|
+
message.timestamp
|
|
85
|
+
);
|
|
40
86
|
|
|
41
87
|
return;
|
|
42
88
|
}
|
|
43
89
|
|
|
44
90
|
// No module URL — shouldn't happen, but reload as safety fallback
|
|
91
|
+
const clientStart = performance.now();
|
|
92
|
+
sendAbsoluteHmrTiming({
|
|
93
|
+
clientStart,
|
|
94
|
+
kind: 'component',
|
|
95
|
+
outcome: 'reloaded',
|
|
96
|
+
serverMs: message.data.serverDuration,
|
|
97
|
+
updateId: message.timestamp
|
|
98
|
+
});
|
|
45
99
|
window.location.reload();
|
|
46
100
|
};
|
|
47
101
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
102
|
+
const finishUpdate = (
|
|
103
|
+
clientStart: number,
|
|
104
|
+
serverDuration?: number,
|
|
105
|
+
updateId?: number
|
|
106
|
+
) => {
|
|
107
|
+
sendAbsoluteHmrTiming({
|
|
108
|
+
clientStart,
|
|
109
|
+
kind: 'component',
|
|
110
|
+
serverMs: serverDuration,
|
|
111
|
+
updateId
|
|
112
|
+
});
|
|
56
113
|
if (window.__ERROR_BOUNDARY__) {
|
|
57
114
|
window.__ERROR_BOUNDARY__.reset();
|
|
58
|
-
} else {
|
|
59
|
-
hideErrorOverlay();
|
|
60
115
|
}
|
|
116
|
+
hideErrorOverlay();
|
|
61
117
|
};
|
|
62
118
|
|
|
63
119
|
const applyRefreshImport = (
|
|
64
120
|
moduleUrl: string,
|
|
65
121
|
refreshRuntime: { performReactRefresh: () => unknown },
|
|
66
|
-
serverDuration?: number
|
|
122
|
+
serverDuration?: number,
|
|
123
|
+
updateId?: number
|
|
67
124
|
) => {
|
|
68
125
|
const clientStart = performance.now();
|
|
69
126
|
import(`${moduleUrl}?t=${Date.now()}`)
|
|
70
127
|
.then(() => {
|
|
71
128
|
refreshRuntime.performReactRefresh();
|
|
72
|
-
|
|
129
|
+
finishUpdate(clientStart, serverDuration, updateId);
|
|
73
130
|
|
|
74
131
|
return undefined;
|
|
75
132
|
})
|
|
@@ -78,31 +135,56 @@ const applyRefreshImport = (
|
|
|
78
135
|
'[HMR] React Fast Refresh failed, falling back to reload:',
|
|
79
136
|
err
|
|
80
137
|
);
|
|
138
|
+
sendAbsoluteHmrTiming({
|
|
139
|
+
clientStart,
|
|
140
|
+
kind: 'component',
|
|
141
|
+
outcome: 'reloaded',
|
|
142
|
+
serverMs: serverDuration,
|
|
143
|
+
updateId
|
|
144
|
+
});
|
|
81
145
|
window.location.reload();
|
|
82
146
|
});
|
|
83
147
|
};
|
|
84
148
|
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
149
|
+
const applyRemountImport = (
|
|
150
|
+
moduleUrl: string,
|
|
151
|
+
remount: (module: Record<string, unknown>) => void,
|
|
152
|
+
serverDuration?: number,
|
|
153
|
+
updateId?: number
|
|
154
|
+
) => {
|
|
155
|
+
const clientStart = performance.now();
|
|
156
|
+
import(`${moduleUrl}?t=${Date.now()}`)
|
|
157
|
+
.then((module) => {
|
|
158
|
+
remount(module);
|
|
159
|
+
finishUpdate(clientStart, serverDuration, updateId);
|
|
160
|
+
|
|
161
|
+
return undefined;
|
|
162
|
+
})
|
|
163
|
+
.catch((err) => {
|
|
164
|
+
console.warn(
|
|
165
|
+
'[HMR] React remount failed, falling back to reload:',
|
|
166
|
+
err
|
|
167
|
+
);
|
|
168
|
+
sendAbsoluteHmrTiming({
|
|
169
|
+
clientStart,
|
|
170
|
+
kind: 'component',
|
|
171
|
+
outcome: 'reloaded',
|
|
172
|
+
serverMs: serverDuration,
|
|
173
|
+
updateId
|
|
174
|
+
});
|
|
175
|
+
reloadReactPage();
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const reloadReactCSS = (cssPath: string) =>
|
|
180
|
+
swapCSSStylesheet(cssPath, (href) => {
|
|
94
181
|
const hrefBase = (href.split('?')[0] ?? '').split('/').pop() ?? '';
|
|
95
182
|
const cssPathBase =
|
|
96
183
|
(cssPath.split('?')[0] ?? '').split('/').pop() ?? '';
|
|
97
|
-
|
|
184
|
+
|
|
185
|
+
return (
|
|
98
186
|
hrefBase === cssPathBase ||
|
|
99
187
|
href.includes('react-example') ||
|
|
100
188
|
cssPathBase.includes(hrefBase)
|
|
101
|
-
)
|
|
102
|
-
const newHref = `${
|
|
103
|
-
cssPath + (cssPath.includes('?') ? '&' : '?')
|
|
104
|
-
}t=${Date.now()}`;
|
|
105
|
-
link.href = newHref;
|
|
106
|
-
}
|
|
189
|
+
);
|
|
107
190
|
});
|
|
108
|
-
};
|
|
@@ -7,8 +7,20 @@ import {
|
|
|
7
7
|
isRuntimeErrorOverlay,
|
|
8
8
|
showErrorOverlay
|
|
9
9
|
} from '../errorOverlay';
|
|
10
|
+
import { sendAbsoluteHmrTiming } from '../hmrTiming';
|
|
10
11
|
|
|
11
|
-
export const handleFullReload = (
|
|
12
|
+
export const handleFullReload = (message?: {
|
|
13
|
+
data: { serverDuration?: number };
|
|
14
|
+
timestamp?: number;
|
|
15
|
+
}) => {
|
|
16
|
+
const clientStart = performance.now();
|
|
17
|
+
sendAbsoluteHmrTiming({
|
|
18
|
+
clientStart,
|
|
19
|
+
kind: 'full-reload',
|
|
20
|
+
outcome: 'reloaded',
|
|
21
|
+
serverMs: message?.data.serverDuration,
|
|
22
|
+
updateId: message?.timestamp
|
|
23
|
+
});
|
|
12
24
|
setTimeout(() => {
|
|
13
25
|
window.location.reload();
|
|
14
26
|
}, REBUILD_RELOAD_DELAY_MS);
|
|
@@ -33,7 +45,18 @@ export const handleManifest = (message: {
|
|
|
33
45
|
window.__HMR_MODULE_UPDATES__ = [];
|
|
34
46
|
};
|
|
35
47
|
|
|
36
|
-
const HMR_FRAMEWORKS = [
|
|
48
|
+
const HMR_FRAMEWORKS = [
|
|
49
|
+
'angular',
|
|
50
|
+
'assets',
|
|
51
|
+
'ember',
|
|
52
|
+
'html',
|
|
53
|
+
'htmx',
|
|
54
|
+
'react',
|
|
55
|
+
'styles',
|
|
56
|
+
'svelte',
|
|
57
|
+
'tailwind',
|
|
58
|
+
'vue'
|
|
59
|
+
];
|
|
37
60
|
|
|
38
61
|
const mergeRecord = (
|
|
39
62
|
source: Record<string, string | number>,
|
|
@@ -115,12 +138,9 @@ export const handleRebuildComplete = (message: {
|
|
|
115
138
|
|
|
116
139
|
if (
|
|
117
140
|
message.data.affectedFrameworks &&
|
|
118
|
-
!message.data.affectedFrameworks.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
!message.data.affectedFrameworks.includes('htmx') &&
|
|
122
|
-
!message.data.affectedFrameworks.includes('vue') &&
|
|
123
|
-
!message.data.affectedFrameworks.includes('svelte')
|
|
141
|
+
!message.data.affectedFrameworks.some((framework) =>
|
|
142
|
+
HMR_FRAMEWORKS.includes(framework)
|
|
143
|
+
)
|
|
124
144
|
) {
|
|
125
145
|
const url = new URL(window.location.href);
|
|
126
146
|
url.searchParams.set('_cb', Date.now().toString());
|