@absolutejs/absolute 0.20.0-beta.139 → 0.20.0-beta.140

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/CHANGELOG.md CHANGED
@@ -6,6 +6,17 @@ This file is generated by `absolute-changelog` from the entries in
6
6
  `changelog/`. Edit an entry, not this file — and add new ones under
7
7
  `changelog/unreleased/`.
8
8
 
9
+ ## 0.20.0-beta.140 — 2026-10-18
10
+
11
+ ### Fixed
12
+
13
+ - **Dev pages reconnect after a dropped connection without reloading, and keep trying through long outages**
14
+ When the dev-server socket dropped, `absolute dev` pages polled for about 18 seconds and reloaded as soon as the server answered. On weak wifi every network change became a full reload, refetching every stylesheet and script and losing the page's state, and an outage longer than 18 seconds left the page disconnected until a manual reload. The page now reconnects the socket for up to 30 minutes, backing off from half a second to ten, waits for the network instead of retrying while the browser is offline, and retries at once when the network or the tab returns. It reloads only if it missed something: the server restarted, or sent an update while the page was away. The server now includes when it started and when it last sent an update in the manifest it sends each connecting page. The banner says when the browser is offline.
15
+ - **Production builds ship React's production build (react-dom 903 KB → 400 KB, no development checks)**
16
+ Production builds bundled React into its vendor files without setting `process.env.NODE_ENV`, so React picked its development build: `react-dom_client.js` was 903 KB, and React ran its development checks in every production page. Production builds now set `process.env.NODE_ENV` to `"production"`: 400 KB, 81 KB gzipped. Only whitespace is minified; renaming identifiers or minifying syntax across the split vendor chunks makes Bun emit an export named `__INVALID__REF__`, which stopped compiled executables from hydrating. `absolute dev` is unchanged; Fast Refresh needs the development build.
17
+ - **Edits to class components and `memo`/`forwardRef` wrappers appear in `absolute dev` without a reload**
18
+ React Fast Refresh updates the components it registered. Editing a module that registers none (a class component, or a `memo`/`forwardRef` wrapper the transpiler does not register) re-ran only that module, and its importer kept rendering the old one, so the edit never showed until a reload. The update now also re-imports the module's importers up to the nearest one that registers a component, so the edit appears and the rest of the page keeps its state.
19
+
9
20
  ## 0.20.0-beta.139 — 2026-10-16
10
21
 
11
22
  ### Changed
package/changelog.json CHANGED
@@ -2,6 +2,27 @@
2
2
  "contract": 1,
3
3
  "name": "@absolutejs/absolute",
4
4
  "releases": [
5
+ {
6
+ "changes": [
7
+ {
8
+ "detail": "When the dev-server socket dropped, `absolute dev` pages polled for about 18 seconds and reloaded as soon as the server answered. On weak wifi every network change became a full reload, refetching every stylesheet and script and losing the page's state, and an outage longer than 18 seconds left the page disconnected until a manual reload. The page now reconnects the socket for up to 30 minutes, backing off from half a second to ten, waits for the network instead of retrying while the browser is offline, and retries at once when the network or the tab returns. It reloads only if it missed something: the server restarted, or sent an update while the page was away. The server now includes when it started and when it last sent an update in the manifest it sends each connecting page. The banner says when the browser is offline.",
9
+ "kind": "fixed",
10
+ "summary": "Dev pages reconnect after a dropped connection without reloading, and keep trying through long outages"
11
+ },
12
+ {
13
+ "detail": "Production builds bundled React into its vendor files without setting `process.env.NODE_ENV`, so React picked its development build: `react-dom_client.js` was 903 KB, and React ran its development checks in every production page. Production builds now set `process.env.NODE_ENV` to `\"production\"`: 400 KB, 81 KB gzipped. Only whitespace is minified; renaming identifiers or minifying syntax across the split vendor chunks makes Bun emit an export named `__INVALID__REF__`, which stopped compiled executables from hydrating. `absolute dev` is unchanged; Fast Refresh needs the development build.",
14
+ "kind": "fixed",
15
+ "summary": "Production builds ship React's production build (react-dom 903 KB → 400 KB, no development checks)"
16
+ },
17
+ {
18
+ "detail": "React Fast Refresh updates the components it registered. Editing a module that registers none (a class component, or a `memo`/`forwardRef` wrapper the transpiler does not register) re-ran only that module, and its importer kept rendering the old one, so the edit never showed until a reload. The update now also re-imports the module's importers up to the nearest one that registers a component, so the edit appears and the rest of the page keeps its state.",
19
+ "kind": "fixed",
20
+ "summary": "Edits to class components and `memo`/`forwardRef` wrappers appear in `absolute dev` without a reload"
21
+ }
22
+ ],
23
+ "date": "2026-10-18",
24
+ "version": "0.20.0-beta.140"
25
+ },
5
26
  {
6
27
  "changes": [
7
28
  {
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- // .angular-partial-tmp-cVJTxm/src/core/streamingSlotRegistrar.ts
2
+ // .angular-partial-tmp-UKvYic/src/core/streamingSlotRegistrar.ts
3
3
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
4
4
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
5
5
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- // .angular-partial-tmp-cVJTxm/src/core/streamingSlotRegistrar.ts
2
+ // .angular-partial-tmp-UKvYic/src/core/streamingSlotRegistrar.ts
3
3
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
4
4
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
5
5
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -46,7 +46,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
46
46
  getWarningController()?.maybeWarn(primitiveName);
47
47
  };
48
48
 
49
- // .angular-partial-tmp-cVJTxm/src/core/streamingSlotRegistry.ts
49
+ // .angular-partial-tmp-UKvYic/src/core/streamingSlotRegistry.ts
50
50
  var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
51
51
  var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
52
52
  var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
package/dist/build.js CHANGED
@@ -22361,7 +22361,7 @@ var resolveJsxDevRuntimeCompatPath = () => {
22361
22361
  return `${lines.join(`
22362
22362
  `)}
22363
22363
  `;
22364
- }, buildReactVendor = async (buildDir) => {
22364
+ }, buildReactVendor = async (buildDir, { production = false } = {}) => {
22365
22365
  const vendorDir = join41(buildDir, "react", "vendor");
22366
22366
  mkdirSync8(vendorDir, { recursive: true });
22367
22367
  const tmpDir = join41(buildDir, "_vendor_tmp");
@@ -22375,9 +22375,10 @@ var resolveJsxDevRuntimeCompatPath = () => {
22375
22375
  return entryPath;
22376
22376
  }));
22377
22377
  const result = await bunBuild3({
22378
+ ...production ? { define: { "process.env.NODE_ENV": '"production"' } } : {},
22378
22379
  entrypoints,
22379
22380
  format: "esm",
22380
- minify: false,
22381
+ minify: production ? { whitespace: true } : false,
22381
22382
  naming: "[name].[ext]",
22382
22383
  outdir: vendorDir,
22383
22384
  splitting: true,
@@ -23893,7 +23894,7 @@ ${offenders.map((o) => ` \u2022 ${o}`).join(`
23893
23894
  }
23894
23895
  if (!hmr && reactDir) {
23895
23896
  await Promise.resolve().then(() => init_buildReactVendor());
23896
- await buildReactVendor(buildPath);
23897
+ await buildReactVendor(buildPath, { production: !isDev });
23897
23898
  vendorPaths = computeVendorPaths();
23898
23899
  setDevVendorPaths(vendorPaths);
23899
23900
  }
@@ -26567,12 +26568,14 @@ var MAX_RETAINED_HMR_UPDATES = 100, normalizedHmrTarget = (value) => {
26567
26568
  state.connectedClients.delete(client);
26568
26569
  state.clientTargets.delete(client);
26569
26570
  });
26570
- }, handleClientConnect = (state, client, manifest) => {
26571
+ }, SERVER_STARTED_AT, handleClientConnect = (state, client, manifest) => {
26571
26572
  state.connectedClients.add(canonicalClient(client));
26572
26573
  const serverVersions = serializeModuleVersions(state.moduleVersions);
26573
26574
  client.send(JSON.stringify({
26574
26575
  data: {
26576
+ lastBroadcastAt: state.lastBroadcastTimestamp,
26575
26577
  manifest,
26578
+ serverStartedAt: SERVER_STARTED_AT,
26576
26579
  serverVersions
26577
26580
  },
26578
26581
  timestamp: Date.now(),
@@ -26692,6 +26695,7 @@ var init_webSocket = __esm(() => {
26692
26695
  init_telemetryEvent();
26693
26696
  init_logger();
26694
26697
  canonicalClients = new WeakMap;
26698
+ SERVER_STARTED_AT = Math.round(performance.timeOrigin);
26695
26699
  });
26696
26700
 
26697
26701
  // src/utils/loadConfig.ts
@@ -35009,6 +35013,20 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
35009
35013
  return nearest;
35010
35014
  const dependents = reactFiles.filter((candidate) => !edited.has(candidate) && isReactComponentPath(candidate) && isImportableModule(candidate));
35011
35015
  return dependents.find((candidate) => !isReactPagePath(candidate)) ?? dependents[0] ?? file;
35016
+ }, MAX_REFRESH_BOUNDARY_HOPS = 8, registersRefreshComponent = (file) => /\$RefreshReg\$\(/u.test(getTransformed(resolvePath4(file)) ?? ""), refreshBoundaryUrls = async (targets) => {
35017
+ const urls = [];
35018
+ const seen = new Set(targets.map((file) => resolvePath4(file)));
35019
+ const climb = async (file, hops) => {
35020
+ const importer = findNearestComponent(resolvePath4(file));
35021
+ if (!importer || seen.has(importer) || hops >= MAX_REFRESH_BOUNDARY_HOPS)
35022
+ return;
35023
+ seen.add(importer);
35024
+ urls.push(await getReactModuleUrl(importer));
35025
+ if (!registersRefreshComponent(importer))
35026
+ await climb(importer, hops + 1);
35027
+ };
35028
+ await targets.reduce((previous, target) => previous.then(() => registersRefreshComponent(target) ? undefined : climb(target, 0)), Promise.resolve());
35029
+ return urls;
35012
35030
  }, resolveReactUpdateTargets = (state, reactFiles) => {
35013
35031
  const importable = reactFiles.filter(isImportableModule);
35014
35032
  const userEdited = importable.filter((file) => state.lastUserEditedFiles?.has(resolvePath4(file)));
@@ -35041,7 +35059,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
35041
35059
  });
35042
35060
  return state.manifest;
35043
35061
  }
35044
- const moduleUrls = await Promise.all(targets.map(getReactModuleUrl));
35062
+ const targetUrls = await Promise.all(targets.map(getReactModuleUrl));
35063
+ const moduleUrls = fastRefreshSupported ? [...targetUrls, ...await refreshBoundaryUrls(targets)] : targetUrls;
35045
35064
  await Promise.all(editedFiles.filter((file) => !targets.includes(file)).map(getReactModuleUrl));
35046
35065
  const { getTransformError } = await getModuleServer();
35047
35066
  const failed = [...new Set([...editedFiles, ...targets])].map((file) => ({ error: getTransformError(file), file })).find((entry) => entry.error !== undefined);
@@ -37625,5 +37644,5 @@ export {
37625
37644
  devBuild
37626
37645
  };
37627
37646
 
37628
- //# debugId=2A99D03636D2BB0864756E2164756E21
37647
+ //# debugId=FA2E655602E07F4664756E2164756E21
37629
37648
  //# sourceMappingURL=build.js.map