rsbuild-plugin-react-router 0.7.1 → 0.7.2

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.
@@ -1,11 +1,13 @@
1
1
  import type { RsbuildDevServer, Rspack } from '@rsbuild/core';
2
2
  import type { ServerBuild } from 'react-router';
3
- import { type DevGraphChanges, type DevGraphIdentity, type DevRuntimeStats, type ReactRouterDevBuildPlan, type ReactRouterDevManifestSet } from './dev-runtime-artifacts.js';
3
+ import { type DevCompilationIdentity, type DevGraphChanges, type DevGraphIdentity, type DevRuntimeStats, type ReactRouterDevBuildPlan, type ReactRouterDevManifestSet } from './dev-runtime-artifacts.js';
4
4
  export type { DevGraphChanges, DevGraphIdentity, ReactRouterDevManifest, } from './dev-runtime-artifacts.js';
5
5
  export type ReactRouterDevRuntime = {
6
6
  beginAttempt: () => void;
7
7
  captureWeb: (compilation: Rspack.Compilation, manifestsByEntryName: ReactRouterDevManifestSet) => void;
8
8
  finishAttempt: (stats: DevRuntimeStats, changes: DevGraphChanges, identity: DevGraphIdentity) => Promise<'committed' | 'ignored' | 'retry-node'>;
9
+ /** Node identity actually retained by the last successful generation. */
10
+ getCommittedNodeIdentity: () => DevCompilationIdentity | undefined;
9
11
  failAttempt: (error: Error) => void;
10
12
  load: (entryName?: string) => Promise<ServerBuild>;
11
13
  close: (error?: Error) => void;
@@ -0,0 +1,5 @@
1
+ /** Tracks unsignaled node edits across compiler retries within one dev session. */
2
+ export declare const createDevHdrIntentTracker: () => {
3
+ capture(compilation: object, hasRelevantChanges: boolean): void;
4
+ signalCommitted(compilation: object, signal: () => void): void;
5
+ };
package/dist/index.cjs CHANGED
@@ -15246,6 +15246,7 @@ export default entryJsFiles;
15246
15246
  return rejectAttempt(attemptId, normalizeEffectError(cause), !0), 'ignored';
15247
15247
  }
15248
15248
  },
15249
+ getCommittedNodeIdentity: ()=>'ready' === state.kind ? state.committed.nodeIdentity : void 0,
15249
15250
  failAttempt (error) {
15250
15251
  let attemptId = getCurrentAttemptId();
15251
15252
  null !== attemptId && rejectAttempt(attemptId, error, !1);
@@ -15279,6 +15280,17 @@ export default entryJsFiles;
15279
15280
  }, loadReactRouterServerBuild = (server, entryName)=>{
15280
15281
  let runtime = Reflect.get(server, DEV_RUNTIME_KEY);
15281
15282
  return runtime ? runtime.load(entryName) : Promise.reject(Error('[rsbuild-plugin-react-router] This Rsbuild development server is not registered with the React Router plugin. Add pluginReactRouter() before calling loadReactRouterServerBuild().'));
15283
+ }, createDevHdrIntentTracker = ()=>{
15284
+ let latestRelevantEditRevision = 0, signaledRevision = 0, revisionByCompilation = new WeakMap();
15285
+ return {
15286
+ capture (compilation, hasRelevantChanges) {
15287
+ hasRelevantChanges && (latestRelevantEditRevision += 1), revisionByCompilation.set(compilation, latestRelevantEditRevision);
15288
+ },
15289
+ signalCommitted (compilation, signal) {
15290
+ let compilationRevision = revisionByCompilation.get(compilation);
15291
+ void 0 === compilationRevision || compilationRevision <= signaledRevision || (signal(), signaledRevision = Math.max(signaledRevision, compilationRevision));
15292
+ }
15293
+ };
15282
15294
  }, createDevRuntimeSessionManager = (closeBinding)=>{
15283
15295
  let state = {
15284
15296
  status: 'idle'
@@ -15384,12 +15396,15 @@ export default entryJsFiles;
15384
15396
  scheduledCssAssetOwnershipReload && (clearTimeout(scheduledCssAssetOwnershipReload), scheduledCssAssetOwnershipReload = void 0), reloadAfterCssAssetOwnershipRemoval = !1;
15385
15397
  let pair = binding.compilers;
15386
15398
  pair && resetDevCompilerPair(pair), binding.compilers = void 0, binding.runtime.close(error), unregisterReactRouterDevRuntime(binding.server, binding.runtime);
15387
- }, sessions = createDevRuntimeSessionManager(closeBinding), compilationIdentities = createCompilationIdentityTracker(), { getCompilationIdentity } = compilationIdentities, hdrSignaledNodeIdentity = new WeakMap(), finishRuntimeAttempt = async (binding, pair, stats, changes, identity1)=>{
15399
+ }, sessions = createDevRuntimeSessionManager(closeBinding), compilationIdentities = createCompilationIdentityTracker(), { getCompilationIdentity } = compilationIdentities, hdrIntentsByPair = new WeakMap(), finishRuntimeAttempt = async (binding, pair, stats, changes, identity1)=>{
15388
15400
  try {
15389
15401
  let result = await binding.runtime.finishAttempt(stats, changes, identity1);
15390
15402
  if (sessions.getActiveBinding()?.id !== binding.id) return;
15391
15403
  if ('retry-node' === result) return void pair.node.watching?.invalidate();
15392
- 'committed' === result && changes.node.known && void 0 !== identity1.node && hdrSignaledNodeIdentity.get(pair) !== identity1.node && Array.from(changes.node.files).some((file)=>!file.includes('.react-router/hdr-revision.mjs') && !/\.css(?:\.[cm]?[jt]s)?$/.test(file)) && (hdrSignaledNodeIdentity.set(pair, identity1.node), onNodeRebuildCommitted?.());
15404
+ let nodeCompilation = getEnvironmentStats(stats, 'node')?.compilation;
15405
+ 'committed' === result && nodeCompilation && identity1.node === binding.runtime.getCommittedNodeIdentity() && hdrIntentsByPair.get(pair)?.signalCommitted(nodeCompilation, ()=>{
15406
+ onNodeRebuildCommitted?.();
15407
+ });
15393
15408
  } catch (cause) {
15394
15409
  sessions.getActiveBinding()?.id === binding.id && binding.runtime.failAttempt(normalizeEffectError(cause));
15395
15410
  }
@@ -15476,6 +15491,8 @@ export default entryJsFiles;
15476
15491
  node
15477
15492
  });
15478
15493
  binding.compilers = pair;
15494
+ let hdrIntents = createDevHdrIntentTracker();
15495
+ hdrIntentsByPair.set(pair, hdrIntents);
15479
15496
  let sessionId = binding.id, runtime = binding.runtime, failCurrentAttempt = (side, error)=>{
15480
15497
  sessions.getActiveBinding()?.id === sessionId && ('web' === side ? clearDevCompilerStart(pair, 'latestWebStart') : clearDevCompilerStart(pair, 'latestNodeStart'), runtime.failAttempt(error));
15481
15498
  }, beginCompilerAttempt = (side)=>{
@@ -15497,10 +15514,12 @@ export default entryJsFiles;
15497
15514
  identity: getCompilationIdentity(compilation)
15498
15515
  }, reloadAfterCssAssetOwnershipRemoval && (reloadAfterCssAssetOwnershipRemoval = !1, scheduleCssAssetOwnershipReload()));
15499
15516
  }), node.hooks.thisCompilation.tap(`${PLUGIN_NAME}:dev-node-web-compilation`, (compilation)=>{
15500
- sessions.getActiveBinding()?.id === sessionId && (pair.latestNodeStart = {
15517
+ if (sessions.getActiveBinding()?.id !== sessionId) return;
15518
+ let changes = snapshotDevChangedFiles(pair.node);
15519
+ hdrIntents.capture(compilation, changes.known && Array.from(changes.files).some((file)=>!file.includes('.react-router/hdr-revision.mjs') && !/\.css(?:\.[cm]?[jt]s)?$/.test(file))), pair.latestNodeStart = {
15501
15520
  status: 'started',
15502
15521
  identity: getCompilationIdentity(compilation)
15503
- }, pair.currentAttemptIdentity && compilationIdentities.setAttemptIdentityForCompilation(compilation, pair.currentAttemptIdentity), pair.latestCompletedWebIdentity && compilationIdentities.setWebIdentityForNodeCompilation(compilation, pair.latestCompletedWebIdentity));
15522
+ }, pair.currentAttemptIdentity && compilationIdentities.setAttemptIdentityForCompilation(compilation, pair.currentAttemptIdentity), pair.latestCompletedWebIdentity && compilationIdentities.setWebIdentityForNodeCompilation(compilation, pair.latestCompletedWebIdentity);
15504
15523
  });
15505
15524
  let settleCompilation = (stats)=>{
15506
15525
  sessions.getActiveBinding()?.id === sessionId && (pair.settledCompilations.add(stats.compilation), flushSettledAttempt(binding, pair));
package/dist/index.js CHANGED
@@ -9139,12 +9139,15 @@ export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRoute
9139
9139
  setWebIdentityForNodeCompilation (compilation, identity) {
9140
9140
  webIdentityByNodeCompilation.set(compilation, identity);
9141
9141
  }
9142
- }), { getCompilationIdentity } = compilationIdentities, hdrSignaledNodeIdentity = new WeakMap(), finishRuntimeAttempt = async (binding, pair, stats, changes, identity)=>{
9142
+ }), { getCompilationIdentity } = compilationIdentities, hdrIntentsByPair = new WeakMap(), finishRuntimeAttempt = async (binding, pair, stats, changes, identity)=>{
9143
9143
  try {
9144
9144
  let result = await binding.runtime.finishAttempt(stats, changes, identity);
9145
9145
  if (sessions.getActiveBinding()?.id !== binding.id) return;
9146
9146
  if ('retry-node' === result) return void pair.node.watching?.invalidate();
9147
- 'committed' === result && changes.node.known && void 0 !== identity.node && hdrSignaledNodeIdentity.get(pair) !== identity.node && Array.from(changes.node.files).some((file)=>!file.includes('.react-router/hdr-revision.mjs') && !/\.css(?:\.[cm]?[jt]s)?$/.test(file)) && (hdrSignaledNodeIdentity.set(pair, identity.node), onNodeRebuildCommitted?.());
9147
+ let nodeCompilation = getEnvironmentStats(stats, 'node')?.compilation;
9148
+ 'committed' === result && nodeCompilation && identity.node === binding.runtime.getCommittedNodeIdentity() && hdrIntentsByPair.get(pair)?.signalCommitted(nodeCompilation, ()=>{
9149
+ onNodeRebuildCommitted?.();
9150
+ });
9148
9151
  } catch (cause) {
9149
9152
  sessions.getActiveBinding()?.id === binding.id && binding.runtime.failAttempt(normalizeEffectError(cause));
9150
9153
  }
@@ -9334,6 +9337,7 @@ export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRoute
9334
9337
  return rejectAttempt(attemptId, normalizeEffectError(cause), !0), 'ignored';
9335
9338
  }
9336
9339
  },
9340
+ getCommittedNodeIdentity: ()=>'ready' === state.kind ? state.committed.nodeIdentity : void 0,
9337
9341
  failAttempt (error) {
9338
9342
  let attemptId = getCurrentAttemptId();
9339
9343
  null !== attemptId && rejectAttempt(attemptId, error, !1);
@@ -9399,6 +9403,7 @@ export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRoute
9399
9403
  !(!binding || !pair || hasPendingCompilation(pair)) && (pair.pendingAttempt = void 0, pair.currentAttemptIdentity = Symbol(), binding.runtime.beginAttempt());
9400
9404
  }
9401
9405
  }), api.onAfterCreateCompiler(({ compiler })=>{
9406
+ let latestRelevantEditRevision, signaledRevision, revisionByCompilation;
9402
9407
  if (!('compilers' in compiler)) return void rejectUnsupportedCompiler('Rsbuild did not create a multi-compiler');
9403
9408
  let web = compiler.compilers.find((item)=>'web' === item.name), node = compiler.compilers.find((item)=>'node' === item.name);
9404
9409
  if (!web || !node) return void rejectUnsupportedCompiler('the web or node compiler was missing');
@@ -9413,6 +9418,16 @@ export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRoute
9413
9418
  node
9414
9419
  });
9415
9420
  binding.compilers = pair;
9421
+ let hdrIntents = (latestRelevantEditRevision = 0, signaledRevision = 0, revisionByCompilation = new WeakMap(), {
9422
+ capture (compilation, hasRelevantChanges) {
9423
+ hasRelevantChanges && (latestRelevantEditRevision += 1), revisionByCompilation.set(compilation, latestRelevantEditRevision);
9424
+ },
9425
+ signalCommitted (compilation, signal) {
9426
+ let compilationRevision = revisionByCompilation.get(compilation);
9427
+ void 0 === compilationRevision || compilationRevision <= signaledRevision || (signal(), signaledRevision = Math.max(signaledRevision, compilationRevision));
9428
+ }
9429
+ });
9430
+ hdrIntentsByPair.set(pair, hdrIntents);
9416
9431
  let sessionId = binding.id, runtime = binding.runtime, failCurrentAttempt = (side, error)=>{
9417
9432
  sessions.getActiveBinding()?.id === sessionId && ('web' === side ? clearDevCompilerStart(pair, 'latestWebStart') : clearDevCompilerStart(pair, 'latestNodeStart'), runtime.failAttempt(error));
9418
9433
  }, beginCompilerAttempt = (side)=>{
@@ -9439,10 +9454,12 @@ export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRoute
9439
9454
  identity: getCompilationIdentity(compilation)
9440
9455
  }, reloadAfterCssAssetOwnershipRemoval && (reloadAfterCssAssetOwnershipRemoval = !1, scheduleCssAssetOwnershipReload()));
9441
9456
  }), node.hooks.thisCompilation.tap(`${PLUGIN_NAME}:dev-node-web-compilation`, (compilation)=>{
9442
- sessions.getActiveBinding()?.id === sessionId && (pair.latestNodeStart = {
9457
+ if (sessions.getActiveBinding()?.id !== sessionId) return;
9458
+ let changes = snapshotDevChangedFiles(pair.node);
9459
+ hdrIntents.capture(compilation, changes.known && Array.from(changes.files).some((file)=>!file.includes('.react-router/hdr-revision.mjs') && !/\.css(?:\.[cm]?[jt]s)?$/.test(file))), pair.latestNodeStart = {
9443
9460
  status: 'started',
9444
9461
  identity: getCompilationIdentity(compilation)
9445
- }, pair.currentAttemptIdentity && compilationIdentities.setAttemptIdentityForCompilation(compilation, pair.currentAttemptIdentity), pair.latestCompletedWebIdentity && compilationIdentities.setWebIdentityForNodeCompilation(compilation, pair.latestCompletedWebIdentity));
9462
+ }, pair.currentAttemptIdentity && compilationIdentities.setAttemptIdentityForCompilation(compilation, pair.currentAttemptIdentity), pair.latestCompletedWebIdentity && compilationIdentities.setWebIdentityForNodeCompilation(compilation, pair.latestCompletedWebIdentity);
9446
9463
  });
9447
9464
  let settleCompilation = (stats)=>{
9448
9465
  sessions.getActiveBinding()?.id === sessionId && (pair.settledCompilations.add(stats.compilation), flushSettledAttempt(binding, pair));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rsbuild-plugin-react-router",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "React Router plugin for Rsbuild",
5
5
  "repository": {
6
6
  "type": "git",
@@ -61,6 +61,8 @@ export type ReactRouterDevRuntime = {
61
61
  changes: DevGraphChanges,
62
62
  identity: DevGraphIdentity
63
63
  ) => Promise<'committed' | 'ignored' | 'retry-node'>;
64
+ /** Node identity actually retained by the last successful generation. */
65
+ getCommittedNodeIdentity: () => DevCompilationIdentity | undefined;
64
66
  failAttempt: (error: Error) => void;
65
67
  load: (entryName?: string) => Promise<ServerBuild>;
66
68
  close: (error?: Error) => void;
@@ -615,6 +617,10 @@ export const createReactRouterDevRuntime = ({
615
617
  }
616
618
  },
617
619
 
620
+ getCommittedNodeIdentity() {
621
+ return state.kind === 'ready' ? state.committed.nodeIdentity : undefined;
622
+ },
623
+
618
624
  failAttempt(error): void {
619
625
  const attemptId = getCurrentAttemptId();
620
626
  if (attemptId !== null) {
@@ -0,0 +1,27 @@
1
+ /** Tracks unsignaled node edits across compiler retries within one dev session. */
2
+ export const createDevHdrIntentTracker = () => {
3
+ let latestRelevantEditRevision = 0;
4
+ let signaledRevision = 0;
5
+ const revisionByCompilation = new WeakMap<object, number>();
6
+
7
+ return {
8
+ capture(compilation: object, hasRelevantChanges: boolean): void {
9
+ if (hasRelevantChanges) {
10
+ latestRelevantEditRevision += 1;
11
+ }
12
+ revisionByCompilation.set(compilation, latestRelevantEditRevision);
13
+ },
14
+
15
+ signalCommitted(compilation: object, signal: () => void): void {
16
+ const compilationRevision = revisionByCompilation.get(compilation);
17
+ if (
18
+ compilationRevision === undefined ||
19
+ compilationRevision <= signaledRevision
20
+ ) {
21
+ return;
22
+ }
23
+ signal();
24
+ signaledRevision = Math.max(signaledRevision, compilationRevision);
25
+ },
26
+ };
27
+ };
@@ -19,6 +19,7 @@ import {
19
19
  registerReactRouterDevRuntime,
20
20
  unregisterReactRouterDevRuntime,
21
21
  } from './dev-generation.js';
22
+ import { createDevHdrIntentTracker } from './dev-hdr-intent.js';
22
23
  import { DEV_MANIFEST_UPDATE_EVENT } from './dev-hmr.js';
23
24
  import {
24
25
  getEnvironmentStats,
@@ -140,12 +141,10 @@ export const createReactRouterDevRuntimeController = ({
140
141
  const compilationIdentities = createCompilationIdentityTracker();
141
142
  const { getCompilationIdentity } = compilationIdentities;
142
143
 
143
- // Web-only commits reuse the node compiler's stale `modifiedFiles`
144
- // snapshot, and every HDR bump itself triggers a web rebuild — so signal
145
- // once per node compilation identity or the bump loop self-sustains.
146
- const hdrSignaledNodeIdentity = new WeakMap<
144
+ // Pending node-edit intent until a coherent commit retains that compilation.
145
+ const hdrIntentsByPair = new WeakMap<
147
146
  DevCompilerPair,
148
- NonNullable<DevGraphIdentity['node']>
147
+ ReturnType<typeof createDevHdrIntentTracker>
149
148
  >();
150
149
 
151
150
  const finishRuntimeAttempt = async (
@@ -168,17 +167,15 @@ export const createReactRouterDevRuntimeController = ({
168
167
  pair.node.watching?.invalidate();
169
168
  return;
170
169
  }
170
+ const nodeCompilation = getEnvironmentStats(stats, 'node')?.compilation;
171
171
  if (
172
172
  result === 'committed' &&
173
- changes.node.known &&
174
- identity.node !== undefined &&
175
- hdrSignaledNodeIdentity.get(pair) !== identity.node &&
176
- Array.from(changes.node.files).some(
177
- file => !isHdrRevisionFile(file) && !isCssSourceFile(file)
178
- )
173
+ nodeCompilation &&
174
+ identity.node === binding.runtime.getCommittedNodeIdentity()
179
175
  ) {
180
- hdrSignaledNodeIdentity.set(pair, identity.node);
181
- onNodeRebuildCommitted?.();
176
+ hdrIntentsByPair.get(pair)?.signalCommitted(nodeCompilation, () => {
177
+ onNodeRebuildCommitted?.();
178
+ });
182
179
  }
183
180
  } catch (cause) {
184
181
  if (sessions.getActiveBinding()?.id === binding.id) {
@@ -344,6 +341,8 @@ export const createReactRouterDevRuntimeController = ({
344
341
  }
345
342
  const pair: DevCompilerPair = createDevCompilerPair({ web, node });
346
343
  binding.compilers = pair;
344
+ const hdrIntents = createDevHdrIntentTracker();
345
+ hdrIntentsByPair.set(pair, hdrIntents);
347
346
  const sessionId = binding.id;
348
347
  const runtime = binding.runtime;
349
348
  const failCurrentAttempt = (side: 'web' | 'node', error: Error): void => {
@@ -427,6 +426,14 @@ export const createReactRouterDevRuntimeController = ({
427
426
  if (sessions.getActiveBinding()?.id !== sessionId) {
428
427
  return;
429
428
  }
429
+ const changes = snapshotDevChangedFiles(pair.node);
430
+ hdrIntents.capture(
431
+ compilation,
432
+ changes.known &&
433
+ Array.from(changes.files).some(
434
+ file => !isHdrRevisionFile(file) && !isCssSourceFile(file)
435
+ )
436
+ );
430
437
  pair.latestNodeStart = {
431
438
  status: 'started',
432
439
  identity: getCompilationIdentity(compilation),