stx-router 0.2.607 → 0.2.612

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.
Files changed (2) hide show
  1. package/dist/client.js +30 -6
  2. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -1321,7 +1321,13 @@ function routerSource() {
1321
1321
  // Cache hit \u2192 promote in LRU order so this entry survives eviction
1322
1322
  // longer than other entries that haven't been touched.
1323
1323
  touchCache(targetPath);
1324
- if(checkLayoutChange(layoutCache[targetPath],url,layoutGroupCache[targetPath])){
1324
+ var cached=cache[targetPath];
1325
+ // A whole document swaps in as it is: one prefetched across a layout
1326
+ // change (prefetchLink), or kept from an earlier full-page answer. Only a
1327
+ // fragment from another layout still needs its document fetched; asking
1328
+ // again was a second round trip on every tap into another layout.
1329
+ var isDoc=cached.indexOf('<!--stx-fragment')!==0;
1330
+ if(!isDoc&&checkLayoutChange(layoutCache[targetPath],url,layoutGroupCache[targetPath])){
1325
1331
  // Layout changed \u2014 fetch full page and do full document swap
1326
1332
  log('[router] cache hit but layout changed \u2014 fetching full page');
1327
1333
  return routerFetch(url,{'Accept':'text/html'}).then(function(r){
@@ -1335,11 +1341,10 @@ function routerSource() {
1335
1341
  return swapWith(html,targetPath);
1336
1342
  }).catch(failed).finally(done);
1337
1343
  }
1338
- var cached=cache[targetPath];
1339
1344
  var swapCached=function(){
1340
1345
  if(stale())return false;
1341
1346
  pendingContainerAttrs=attrsCache[targetPath]||'';
1342
- pendingLayoutDecl=null;
1347
+ pendingLayoutDecl=isDoc?{layout:layoutCache[targetPath]||'',group:layoutGroupCache[targetPath]||''}:null;
1343
1348
  return swapWith(cached,targetPath);
1344
1349
  };
1345
1350
  var loading=beforeSwap(cached,url);
@@ -1347,8 +1352,10 @@ function routerSource() {
1347
1352
  if(swapped===false)return false;
1348
1353
  applyTitle(titleCache[targetPath]);
1349
1354
  // Shown from the cache at once; asked again behind it, so a page that
1350
- // changed since says so (stx:updated) instead of staying stale.
1351
- revalidate(targetPath,url);
1355
+ // changed since says so (stx:updated) instead of staying stale. Not a
1356
+ // whole document: it would be compared with a fragment and always
1357
+ // read as changed.
1358
+ if(!isDoc)revalidate(targetPath,url);
1352
1359
  return true;
1353
1360
  }).finally(done);
1354
1361
  }
@@ -3520,6 +3527,16 @@ else {
3520
3527
  var wantsFragment=shouldUseFragmentResponse();
3521
3528
  prefetching[key]=fetch(href,{headers:wantsFragment?{'X-STX-Router':'true','Accept':'text/html'}:{'Accept':'text/html'}}).then(function(r){
3522
3529
  return readPrefetchResponse(r,wantsFragment);
3530
+ }).then(function(result){
3531
+ // A page in another layout cannot be swapped in as a fragment: the tap
3532
+ // would read this answer, see the layout change, and fetch the whole
3533
+ // document then (navigate). Fetch it now instead, while the person is
3534
+ // still reaching for the link, so the tap is a swap like any other.
3535
+ if(!result||result.html.indexOf('<!--stx-fragment')||!checkLayoutChange(result.layout,href,result.layoutGroup))return result;
3536
+ // Same guards as any prefetch; the layout is the one the fragment declared.
3537
+ return fetch(href,{headers:{'Accept':'text/html'}}).then(function(full){
3538
+ return full.ok?readPrefetchResponse(full,false).then(function(doc){return doc&&(doc.layout=result.layout,doc.layoutGroup=result.layoutGroup,doc)}):null;
3539
+ });
3523
3540
  }).then(function(result){
3524
3541
  if(result&&o.cache){
3525
3542
  setCache(key,result.html,result.layout,result.layoutGroup,result.title,result.containerAttrs);
@@ -3530,7 +3547,8 @@ else {
3530
3547
  // Its stylesheet too, so the tap never waits on cssLoadTimeout for a
3531
3548
  // sheet it could have had all along. Added unapplied (media=print),
3532
3549
  // as a navigation adds it; the swap makes it live.
3533
- if(result.html.indexOf('<!--stx-fragment')===0)preloadGeneratedCss(fragmentCssHrefs(result.html),location.href);
3550
+ // A whole document's generated sheets too, named the same way in its head.
3551
+ preloadGeneratedCss(fragmentCssHrefs(result.html),location.href);
3534
3552
  }
3535
3553
  }).catch(function(){}).finally(function(){delete prefetching[key]});
3536
3554
  }
@@ -3609,6 +3627,12 @@ else {
3609
3627
  // Answers false when a bundle failed: that page cannot bind, and is
3610
3628
  // recovered (recoverUnbound) rather than swapped in bare.
3611
3629
  function beforeSwap(html,base){
3630
+ // Its generated stylesheets start now too, beside the bundles: the swap
3631
+ // waits for them anyway, and fetched one after the other a tap paid for
3632
+ // two round trips where one would do. The swap finds them here (pending
3633
+ // or loaded) rather than starting them; a failed sheet is the swap's to
3634
+ // handle, so it does not hold this up. Generated sheets are root paths.
3635
+ preloadGeneratedCss(fragmentCssHrefs(html),location.href);
3612
3636
  var waits=loadModuleRegistries(html,base);
3613
3637
  if(!waits)return null;
3614
3638
  return Promise.race([
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stx-router",
3
3
  "type": "module",
4
- "version": "0.2.607",
4
+ "version": "0.2.612",
5
5
  "description": "File-based router for STX — .stx template discovery, nested layouts, typed route params, middleware, and client-side SPA navigation.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",