vite-plugin-smart-prefetch 0.1.0 → 0.3.0

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/dist/index.d.cts CHANGED
@@ -111,6 +111,8 @@ interface DataSourceMetadata {
111
111
  totalRoutes?: number;
112
112
  }
113
113
  interface RoutePrediction {
114
+ /** Route pattern variants (for matching dynamic routes like /order/:id) */
115
+ patterns?: string[];
114
116
  /** Routes to prefetch from this source (default/common rules) */
115
117
  prefetch: PrefetchTarget[];
116
118
  /** Segment-specific prefetch rules */
@@ -131,6 +133,8 @@ interface PrefetchTarget {
131
133
  count: number;
132
134
  /** Chunk file to prefetch (set by config generator) */
133
135
  chunk?: string;
136
+ /** Production chunk file path (for production builds) */
137
+ chunk_prod?: string;
134
138
  /** Dependency chunks to prefetch (extracted from Vite manifest imports) */
135
139
  imports?: string[];
136
140
  /** Priority level */
@@ -162,9 +166,13 @@ interface PrefetchConfig {
162
166
  maxPrefetch: number;
163
167
  accuracy?: number;
164
168
  };
169
+ /** Global route patterns for dynamic route matching */
170
+ routePatterns?: Record<string, string[]>;
165
171
  /** Route predictions with chunk mappings */
166
172
  routes: {
167
173
  [sourceRoute: string]: {
174
+ /** Route pattern variants (for matching dynamic routes like /order/:id) */
175
+ patterns?: string[];
168
176
  /** Default/common prefetch rules (works for all users) */
169
177
  prefetch: Array<PrefetchTarget & {
170
178
  chunk: string;
package/dist/index.d.ts CHANGED
@@ -111,6 +111,8 @@ interface DataSourceMetadata {
111
111
  totalRoutes?: number;
112
112
  }
113
113
  interface RoutePrediction {
114
+ /** Route pattern variants (for matching dynamic routes like /order/:id) */
115
+ patterns?: string[];
114
116
  /** Routes to prefetch from this source (default/common rules) */
115
117
  prefetch: PrefetchTarget[];
116
118
  /** Segment-specific prefetch rules */
@@ -131,6 +133,8 @@ interface PrefetchTarget {
131
133
  count: number;
132
134
  /** Chunk file to prefetch (set by config generator) */
133
135
  chunk?: string;
136
+ /** Production chunk file path (for production builds) */
137
+ chunk_prod?: string;
134
138
  /** Dependency chunks to prefetch (extracted from Vite manifest imports) */
135
139
  imports?: string[];
136
140
  /** Priority level */
@@ -162,9 +166,13 @@ interface PrefetchConfig {
162
166
  maxPrefetch: number;
163
167
  accuracy?: number;
164
168
  };
169
+ /** Global route patterns for dynamic route matching */
170
+ routePatterns?: Record<string, string[]>;
165
171
  /** Route predictions with chunk mappings */
166
172
  routes: {
167
173
  [sourceRoute: string]: {
174
+ /** Route pattern variants (for matching dynamic routes like /order/:id) */
175
+ patterns?: string[];
168
176
  /** Default/common prefetch rules (works for all users) */
169
177
  prefetch: Array<PrefetchTarget & {
170
178
  chunk: string;
package/dist/index.js CHANGED
@@ -645,10 +645,14 @@ var MarkovChainTrainer = class {
645
645
 
646
646
  // src/plugin/config-generator.ts
647
647
  var _ConfigGenerator = class _ConfigGenerator {
648
- constructor(manifest, manualRules = {}, debug = false) {
648
+ constructor(manifest, manualRules = {}, debug = false, vite) {
649
+ this.vite = null;
650
+ this.isDev = false;
649
651
  this.manifest = manifest;
650
652
  this.manualRules = manualRules;
651
653
  this.debug = debug;
654
+ this.vite = vite || null;
655
+ this.isDev = !!vite;
652
656
  }
653
657
  /**
654
658
  * Generate final prefetch configuration with chunk mappings
@@ -666,6 +670,7 @@ var _ConfigGenerator = class _ConfigGenerator {
666
670
  }
667
671
  }
668
672
  const mergedModel = this.mergeManualRules(model);
673
+ const routePatterns = this.extractRoutePatterns(Object.keys(mergedModel.routes));
669
674
  const config = {
670
675
  version: model.version,
671
676
  generatedAt: model.generatedAt,
@@ -676,6 +681,8 @@ var _ConfigGenerator = class _ConfigGenerator {
676
681
  threshold: model.config.threshold,
677
682
  maxPrefetch: model.config.maxPrefetch
678
683
  },
684
+ routePatterns,
685
+ // NEW: Include route patterns for dynamic matching
679
686
  routes: {},
680
687
  chunks: {}
681
688
  };
@@ -701,6 +708,8 @@ var _ConfigGenerator = class _ConfigGenerator {
701
708
  prefetchTargets.push({
702
709
  ...target,
703
710
  chunk: chunkFile,
711
+ chunk_prod: chunkFile,
712
+ // NEW: Include production chunk path
704
713
  imports
705
714
  // Include dependency chunks (resolved to file paths)
706
715
  });
@@ -736,6 +745,8 @@ var _ConfigGenerator = class _ConfigGenerator {
736
745
  segmentPrefetchTargets.push({
737
746
  ...target,
738
747
  chunk: chunkFile,
748
+ chunk_prod: chunkFile,
749
+ // NEW: Include production chunk path
739
750
  imports
740
751
  });
741
752
  config.chunks[target.route] = chunkFile;
@@ -750,8 +761,11 @@ var _ConfigGenerator = class _ConfigGenerator {
750
761
  console.log(` \u{1F465} Segment configs for ${sourceRoute}: ${Object.keys(segmentConfigs).join(", ")}`);
751
762
  }
752
763
  }
764
+ const patterns = routePatterns[sourceRoute] || [sourceRoute];
753
765
  if (prefetchTargets.length > 0 || Object.keys(segmentConfigs).length > 0) {
754
766
  config.routes[sourceRoute] = {
767
+ patterns,
768
+ // NEW: Include patterns for dynamic route matching
755
769
  prefetch: prefetchTargets,
756
770
  ...Object.keys(segmentConfigs).length > 0 && {
757
771
  segments: segmentConfigs
@@ -931,6 +945,7 @@ var _ConfigGenerator = class _ConfigGenerator {
931
945
  ].filter(Boolean);
932
946
  for (let i = 0; i < patterns.length; i++) {
933
947
  const pattern = patterns[i];
948
+ if (!pattern) continue;
934
949
  const entry = this.manifest[pattern];
935
950
  if (entry) {
936
951
  return entry.file;
@@ -1067,6 +1082,65 @@ var _ConfigGenerator = class _ConfigGenerator {
1067
1082
  missing
1068
1083
  };
1069
1084
  }
1085
+ /**
1086
+ * Extract route patterns for dynamic route matching
1087
+ * Groups routes by their base path and includes pattern variants
1088
+ * E.g., /purchase-order and /purchase-order/:id become patterns for matching
1089
+ */
1090
+ extractRoutePatterns(routes) {
1091
+ const patterns = {};
1092
+ for (const route of routes) {
1093
+ if (route.includes(":") || route.includes("$")) {
1094
+ patterns[route] = [route];
1095
+ const base = route.split(/[:$]/)[0];
1096
+ if (base && base !== route) {
1097
+ if (!patterns[base]) {
1098
+ patterns[base] = [base, route];
1099
+ } else if (!patterns[base].includes(route)) {
1100
+ patterns[base].push(route);
1101
+ }
1102
+ }
1103
+ } else {
1104
+ patterns[route] = [route];
1105
+ }
1106
+ }
1107
+ if (this.debug && Object.keys(patterns).length > 0) {
1108
+ console.log(`
1109
+ \u{1F50D} Extracted route patterns for dynamic matching:`);
1110
+ Object.entries(patterns).forEach(([route, patternList]) => {
1111
+ if (patternList.length > 1) {
1112
+ console.log(` ${route} \u2192 [${patternList.join(", ")}]`);
1113
+ }
1114
+ });
1115
+ }
1116
+ return patterns;
1117
+ }
1118
+ /**
1119
+ * Match a pathname against route patterns
1120
+ * Supports both static routes and dynamic routes with parameters
1121
+ */
1122
+ matchRoutePattern(pathname, pattern) {
1123
+ const patternRegex = new RegExp(
1124
+ "^" + pattern.replace(/:[^/]+/g, "[^/]+").replace(/\$[^/]+/g, "[^/]+").replace(/\*/g, ".*") + // Match wildcard
1125
+ "$"
1126
+ );
1127
+ return patternRegex.test(pathname);
1128
+ }
1129
+ /**
1130
+ * Find matching route pattern for a given pathname
1131
+ * Used by hooks to match actual navigation paths to config routes
1132
+ */
1133
+ findMatchingPattern(pathname, routes) {
1134
+ for (const [route, config] of Object.entries(routes)) {
1135
+ const patterns = config.patterns || [route];
1136
+ for (const pattern of patterns) {
1137
+ if (this.matchRoutePattern(pathname, pattern)) {
1138
+ return route;
1139
+ }
1140
+ }
1141
+ }
1142
+ return null;
1143
+ }
1070
1144
  /**
1071
1145
  * Generate segment-specific prefetch configurations
1072
1146
  * Creates one config per user segment/role
@@ -1427,7 +1501,7 @@ function smartPrefetch(options = {}) {
1427
1501
  imports: []
1428
1502
  };
1429
1503
  });
1430
- const generator = new ConfigGenerator(devManifest, manualRules, debug);
1504
+ const generator = new ConfigGenerator(devManifest, manualRules, debug, server);
1431
1505
  const finalConfig = generator.generate(prefetchModel);
1432
1506
  res.setHeader("Content-Type", "application/json");
1433
1507
  res.setHeader("Access-Control-Allow-Origin", "*");