vite-plugin-preloader 1.0.1 → 1.1.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.
package/dist/index.js CHANGED
@@ -27,153 +27,198 @@ module.exports = __toCommonJS(index_exports);
27
27
 
28
28
  // src/runtime.ts
29
29
  var runtimeTemplate = `// \u{1F680} Auto-generated by vite-plugin-preloader
30
- import { ref, defineComponent, h, onMounted } from 'vue'
30
+ (function() {
31
+ 'use strict';
32
+
33
+ // \u{1F3AF} \u9884\u52A0\u8F7D\u914D\u7F6E\uFF08\u6784\u5EFA\u65F6\u6CE8\u5165\uFF09
34
+ const PRELOAD_ROUTES = __PRELOAD_ROUTES__
35
+ const PRELOAD_OPTIONS = __PRELOAD_OPTIONS__
31
36
 
32
- interface PreloadRoute {
33
- path: string
34
- component: () => Promise<any>
35
- reason: string
36
- priority: number
37
- }
37
+ class PreloaderManager {
38
+ constructor() {
39
+ this.preloadedRoutes = new Set()
40
+ this.isPreloading = false
41
+ this.stats = {
42
+ total: 0, completed: 0, failed: 0, startTime: 0, endTime: 0
43
+ }
44
+ this.statusElement = null
45
+ }
38
46
 
39
- interface PreloadStats {
40
- total: number
41
- completed: number
42
- failed: number
43
- startTime: number
44
- endTime: number
45
- }
47
+ async start() {
48
+ if (this.isPreloading) return
46
49
 
47
- // \u{1F3AF} \u9884\u52A0\u8F7D\u914D\u7F6E\uFF08\u6784\u5EFA\u65F6\u6CE8\u5165\uFF09
48
- const PRELOAD_ROUTES = __PRELOAD_ROUTES__
49
- const PRELOAD_OPTIONS = __PRELOAD_OPTIONS__
50
+ this.isPreloading = true
51
+ this.stats = {
52
+ total: PRELOAD_ROUTES.length,
53
+ completed: 0, failed: 0,
54
+ startTime: Date.now(), endTime: 0
55
+ }
50
56
 
51
- class PreloaderManager {
52
- private preloadedRoutes = new Set()
53
- private isPreloading = ref(false)
54
- private stats = ref({
55
- total: 0, completed: 0, failed: 0, startTime: 0, endTime: 0
56
- })
57
+ if (PRELOAD_OPTIONS.debug) {
58
+ console.log(\`\u{1F680} [\u9884\u52A0\u8F7D] \u5F00\u59CB\u9884\u52A0\u8F7D \${PRELOAD_ROUTES.length} \u4E2A\u9875\u9762\`)
59
+ }
57
60
 
58
- async start() {
59
- if (this.isPreloading.value) return
61
+ // \u663E\u793A\u72B6\u6001\u6307\u793A\u5668
62
+ this.showStatus()
60
63
 
61
- this.isPreloading.value = true
62
- this.stats.value = {
63
- total: PRELOAD_ROUTES.length,
64
- completed: 0, failed: 0,
65
- startTime: Date.now(), endTime: 0
64
+ const sortedRoutes = [...PRELOAD_ROUTES].sort((a, b) => a.priority - b.priority)
65
+
66
+ for (const route of sortedRoutes) {
67
+ await this.preloadSingle(route)
68
+ this.updateStatus()
69
+ await this.sleep(100)
70
+ }
71
+
72
+ this.stats.endTime = Date.now()
73
+ this.isPreloading = false
74
+
75
+ if (PRELOAD_OPTIONS.debug) {
76
+ console.log(\`\u{1F389} [\u9884\u52A0\u8F7D] \u5B8C\u6210! \u8017\u65F6 \${this.stats.endTime - this.stats.startTime}ms\`)
77
+ }
78
+
79
+ // \u9690\u85CF\u72B6\u6001\u6307\u793A\u5668
80
+ this.hideStatus()
66
81
  }
67
82
 
68
- console.log(\`\u{1F680} [\u9884\u52A0\u8F7D] \u5F00\u59CB\u9884\u52A0\u8F7D \${PRELOAD_ROUTES.length} \u4E2A\u9875\u9762\`)
83
+ async preloadSingle(route) {
84
+ if (this.preloadedRoutes.has(route.path)) return
69
85
 
70
- const sortedRoutes = [...PRELOAD_ROUTES].sort((a, b) => a.priority - b.priority)
71
-
72
- for (const route of sortedRoutes) {
73
- await this.preloadSingle(route)
74
- await this.sleep(100)
86
+ try {
87
+ const startTime = Date.now()
88
+ let componentPath = route.component
89
+
90
+ // \u5728\u5F00\u53D1\u73AF\u5883\u4E2D\uFF0CVite \u4F1A\u5904\u7406\u6A21\u5757\u89E3\u6790
91
+ // \u6211\u4EEC\u9700\u8981\u4F7F\u7528\u6B63\u786E\u7684\u6A21\u5757 ID
92
+ if (componentPath.startsWith('@/')) {
93
+ // \u5BF9\u4E8E Vite\uFF0C@ \u522B\u540D\u5E94\u8BE5\u5728\u6784\u5EFA\u65F6\u5C31\u88AB\u89E3\u6790
94
+ // \u4F46\u5728\u8FD0\u884C\u65F6\u6211\u4EEC\u9700\u8981\u4F7F\u7528\u5B9E\u9645\u7684\u8DEF\u5F84
95
+ componentPath = componentPath.replace('@/', '/src/')
96
+ }
97
+
98
+ // \u786E\u4FDD\u8DEF\u5F84\u4EE5 / \u5F00\u5934\uFF08\u76F8\u5BF9\u4E8E\u9879\u76EE\u6839\u76EE\u5F55\uFF09
99
+ if (!componentPath.startsWith('/') && !componentPath.startsWith('./')) {
100
+ componentPath = '/' + componentPath
101
+ }
102
+
103
+ if (PRELOAD_OPTIONS.debug) {
104
+ console.log(\`\u{1F50D} [\u9884\u52A0\u8F7D] \u5C1D\u8BD5\u52A0\u8F7D: \${componentPath}\`)
105
+ }
106
+
107
+ const module = await import(/* @vite-ignore */ componentPath)
108
+ const loadTime = Date.now() - startTime
109
+
110
+ this.preloadedRoutes.add(route.path)
111
+ this.stats.completed++
112
+
113
+ if (PRELOAD_OPTIONS.debug) {
114
+ console.log(\`\u2705 [\u9884\u52A0\u8F7D] \${route.path} (\${loadTime}ms) - \${route.reason}\`)
115
+ }
116
+ } catch (error) {
117
+ this.stats.failed++
118
+ if (PRELOAD_OPTIONS.debug) {
119
+ console.error(\`\u274C [\u9884\u52A0\u8F7D] \${route.path} \u5931\u8D25:\`, error)
120
+ }
121
+ }
75
122
  }
76
123
 
77
- this.stats.value.endTime = Date.now()
78
- this.isPreloading.value = false
79
-
80
- console.log(\`\u{1F389} [\u9884\u52A0\u8F7D] \u5B8C\u6210! \u8017\u65F6 \${this.stats.value.endTime - this.stats.value.startTime}ms\`)
81
- }
124
+ showStatus() {
125
+ if (!PRELOAD_OPTIONS.showStatus || !document.body) return
82
126
 
83
- async preloadSingle(route) {
84
- if (this.preloadedRoutes.has(route.path)) return
127
+ // \u6DFB\u52A0\u6837\u5F0F
128
+ if (!document.getElementById('preloader-styles')) {
129
+ const style = document.createElement('style')
130
+ style.id = 'preloader-styles'
131
+ const position = PRELOAD_OPTIONS.statusPosition.replace('-', ': 20px; ') + ': 20px;'
132
+ style.textContent = \`
133
+ .preloader-status {
134
+ position: fixed; \${position}
135
+ background: rgba(0,0,0,0.8); color: white; padding: 8px 16px;
136
+ border-radius: 6px; font-size: 12px; z-index: 9999;
137
+ pointer-events: none; font-family: system-ui;
138
+ transition: opacity 0.3s ease;
139
+ }
140
+ .preloader-status.fade-out {
141
+ opacity: 0;
142
+ }
143
+ \`
144
+ document.head.appendChild(style)
145
+ }
85
146
 
86
- try {
87
- const startTime = Date.now()
88
- await route.component()
89
- const loadTime = Date.now() - startTime
90
-
91
- this.preloadedRoutes.add(route.path)
92
- this.stats.value.completed++
93
- console.log(\`\u2705 [\u9884\u52A0\u8F7D] \${route.path} (\${loadTime}ms) - \${route.reason}\`)
94
- } catch (error) {
95
- this.stats.value.failed++
96
- console.error(\`\u274C [\u9884\u52A0\u8F7D] \${route.path} \u5931\u8D25:\`, error)
147
+ // \u521B\u5EFA\u72B6\u6001\u5143\u7D20
148
+ this.statusElement = document.createElement('div')
149
+ this.statusElement.className = 'preloader-status'
150
+ this.updateStatus()
151
+ document.body.appendChild(this.statusElement)
97
152
  }
98
- }
99
153
 
100
- sleep(ms) {
101
- return new Promise(resolve => setTimeout(resolve, ms))
102
- }
154
+ updateStatus() {
155
+ if (!this.statusElement) return
156
+ this.statusElement.textContent = \`\u{1F504} \u6B63\u5728\u4F18\u5316\u9875\u9762... \${this.stats.completed}/\${this.stats.total}\`
157
+ }
103
158
 
104
- isPreloaded(path) {
105
- return this.preloadedRoutes.has(path)
106
- }
159
+ hideStatus() {
160
+ if (!this.statusElement) return
161
+ this.statusElement.classList.add('fade-out')
162
+ setTimeout(() => {
163
+ if (this.statusElement && this.statusElement.parentNode) {
164
+ this.statusElement.parentNode.removeChild(this.statusElement)
165
+ }
166
+ }, 300)
167
+ }
107
168
 
108
- getStats() {
109
- return {
110
- ...this.stats.value,
111
- preloadedPaths: Array.from(this.preloadedRoutes),
112
- isPreloading: this.isPreloading.value
169
+ sleep(ms) {
170
+ return new Promise(resolve => setTimeout(resolve, ms))
113
171
  }
114
- }
115
172
 
116
- createStatusComponent() {
117
- const self = this
118
- return defineComponent({
119
- name: 'PreloadStatus',
120
- setup() {
121
- onMounted(() => {
122
- if (!document.getElementById('preloader-styles')) {
123
- const style = document.createElement('style')
124
- style.id = 'preloader-styles'
125
- const position = PRELOAD_OPTIONS.statusPosition.replace('-', ': 20px; ') + ': 20px;'
126
- style.textContent = \`
127
- .preloader-status {
128
- position: fixed; \${position}
129
- background: rgba(0,0,0,0.8); color: white; padding: 8px 16px;
130
- border-radius: 6px; font-size: 12px; z-index: 9999;
131
- pointer-events: none; font-family: system-ui;
132
- }
133
- \`
134
- document.head.appendChild(style)
135
- }
136
- })
173
+ isPreloaded(path) {
174
+ return this.preloadedRoutes.has(path)
175
+ }
137
176
 
138
- return () => {
139
- if (!self.isPreloading.value || !import.meta.env.DEV || !PRELOAD_OPTIONS.showStatus) {
140
- return null
141
- }
142
- return h('div', { class: 'preloader-status' }, [
143
- '\u{1F504} \u6B63\u5728\u4F18\u5316\u9875\u9762... ',
144
- \`\${self.stats.value.completed}/\${self.stats.value.total}\`
145
- ])
146
- }
177
+ getStats() {
178
+ return {
179
+ ...this.stats,
180
+ preloadedPaths: Array.from(this.preloadedRoutes),
181
+ isPreloading: this.isPreloading
147
182
  }
148
- })
183
+ }
149
184
  }
150
- }
151
185
 
152
- // \u{1F680} \u5168\u5C40\u5B9E\u4F8B
153
- const preloader = new PreloaderManager()
186
+ // \u{1F680} \u5168\u5C40\u5B9E\u4F8B
187
+ const preloader = new PreloaderManager()
188
+
189
+ // \u{1F6E0}\uFE0F \u5F00\u53D1\u73AF\u5883\u8C03\u8BD5\u5DE5\u5177
190
+ if (PRELOAD_OPTIONS.debug) {
191
+ window.preloaderDebug = {
192
+ stats: () => preloader.getStats(),
193
+ restart: () => preloader.start(),
194
+ check: (path) => preloader.isPreloaded(path),
195
+ help: () => console.log('\u{1F6E0}\uFE0F \u9884\u52A0\u8F7D\u8C03\u8BD5: stats() | restart() | check(path)')
196
+ }
197
+ console.log('\u{1F6E0}\uFE0F \u9884\u52A0\u8F7D\u8C03\u8BD5\u5DE5\u5177: window.preloaderDebug')
198
+ }
154
199
 
155
- // \u{1F6E0}\uFE0F \u5F00\u53D1\u73AF\u5883\u8C03\u8BD5\u5DE5\u5177
156
- if (import.meta.env.DEV && PRELOAD_OPTIONS.debug) {
157
- window.preloaderDebug = {
158
- stats: () => preloader.getStats(),
159
- restart: () => preloader.start(),
160
- check: (path) => preloader.isPreloaded(path),
161
- help: () => console.log('\u{1F6E0}\uFE0F \u9884\u52A0\u8F7D\u8C03\u8BD5: stats() | restart() | check(path)')
200
+ // \u{1F680} \u81EA\u52A8\u542F\u52A8 - \u7B49\u5F85 DOM \u52A0\u8F7D\u5B8C\u6210
201
+ function autoStart() {
202
+ if (document.readyState === 'loading') {
203
+ document.addEventListener('DOMContentLoaded', () => {
204
+ setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay)
205
+ })
206
+ } else {
207
+ setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay)
208
+ }
162
209
  }
163
- console.log('\u{1F6E0}\uFE0F \u9884\u52A0\u8F7D\u8C03\u8BD5\u5DE5\u5177: window.preloaderDebug')
164
- }
165
210
 
166
- // \u{1F3AF} \u5BFC\u51FA
167
- export const usePreloader = () => ({
168
- start: () => preloader.start(),
169
- isPreloaded: (path) => preloader.isPreloaded(path),
170
- StatusComponent: preloader.createStatusComponent()
171
- })
211
+ // \u7ACB\u5373\u6267\u884C\u81EA\u52A8\u542F\u52A8
212
+ autoStart()
172
213
 
173
- // \u{1F680} \u81EA\u52A8\u542F\u52A8
174
- if (typeof window !== 'undefined') {
175
- setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay || 2000)
176
- }`;
214
+ // \u5BFC\u51FA\u5230\u5168\u5C40\uFF08\u53EF\u9009\u4F7F\u7528\uFF09
215
+ window.usePreloader = () => ({
216
+ start: () => preloader.start(),
217
+ isPreloaded: (path) => preloader.isPreloaded(path),
218
+ getStats: () => preloader.getStats()
219
+ })
220
+
221
+ })();`;
177
222
 
178
223
  // src/generator.ts
179
224
  var CodeGenerator = class {
@@ -197,7 +242,7 @@ var CodeGenerator = class {
197
242
  const componentPath2 = this.inferComponentPath(route);
198
243
  return {
199
244
  path: route,
200
- component: `() => import('${componentPath2}')`,
245
+ component: componentPath2,
201
246
  reason: "\u81EA\u52A8\u63A8\u65AD\u7684\u9884\u52A0\u8F7D\u9875\u9762",
202
247
  priority: 2
203
248
  };
@@ -205,7 +250,7 @@ var CodeGenerator = class {
205
250
  const componentPath = route.component || this.inferComponentPath(route.path);
206
251
  return {
207
252
  path: route.path,
208
- component: `() => import('${componentPath}')`,
253
+ component: componentPath,
209
254
  reason: route.reason || "\u7528\u6237\u914D\u7F6E\u7684\u9884\u52A0\u8F7D\u9875\u9762",
210
255
  priority: route.priority || 2
211
256
  };
@@ -215,70 +260,77 @@ var CodeGenerator = class {
215
260
  * 处理选项配置
216
261
  */
217
262
  processOptions() {
263
+ const isDev = process.env.NODE_ENV !== "production";
218
264
  return {
219
- delay: this.options.delay || 2e3,
220
- showStatus: this.options.showStatus !== false,
221
- statusPosition: this.options.statusPosition || "bottom-right",
222
- debug: this.options.debug || false
265
+ delay: this.options.delay ?? 2e3,
266
+ // 默认2秒
267
+ showStatus: this.options.showStatus ?? true,
268
+ // 默认显示状态
269
+ statusPosition: this.options.statusPosition ?? "bottom-right",
270
+ // 默认右下角
271
+ debug: this.options.debug ?? isDev
272
+ // 开发环境默认开启调试,生产环境默认关闭
223
273
  };
224
274
  }
225
275
  /**
226
- * 推断组件路径
276
+ * 推断组件路径 - 使用 Vite 别名格式
227
277
  */
228
278
  inferComponentPath(routePath) {
229
- const cleanPath = routePath.replace(/^\//, "").replace(/\//g, "-");
230
- return `@/views/${cleanPath}/index.vue`;
279
+ const cleanPath = routePath.replace(/^\//, "");
280
+ if (cleanPath.startsWith("demo/")) {
281
+ return `@/views/${cleanPath}/index.vue`;
282
+ }
283
+ const pathSegments = cleanPath.split("/");
284
+ return `@/views/${pathSegments.join("/")}/index.vue`;
231
285
  }
232
286
  /**
233
- * 生成HTML注入代码
287
+ * 生成注入到 HTML 头部的脚本
234
288
  */
235
289
  generateHtmlInject() {
236
- if (this.options.showStatus === false) return "";
237
- return "<preloader-status></preloader-status>";
290
+ return `<script type="module">
291
+ ${this.generateRuntime()}
292
+ </script>`;
238
293
  }
239
294
  };
240
295
 
241
296
  // src/index.ts
242
- var VIRTUAL_MODULE_ID = "virtual:preloader";
243
- var RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
244
297
  function preloaderPlugin(options) {
245
298
  let generator;
299
+ const isDev = process.env.NODE_ENV !== "production";
300
+ const finalOptions = {
301
+ debug: isDev,
302
+ // 开发环境默认开启调试
303
+ delay: 2e3,
304
+ // 默认2秒
305
+ showStatus: true,
306
+ // 默认显示状态
307
+ statusPosition: "bottom-right",
308
+ // 默认右下角
309
+ ...options
310
+ // 用户配置覆盖默认配置
311
+ };
246
312
  return {
247
313
  name: "vite-plugin-preloader",
248
314
  // 🎯 设置插件执行顺序
249
315
  enforce: "post",
250
316
  configResolved() {
251
- generator = new CodeGenerator(options);
252
- console.log(`\u{1F680} \u9884\u52A0\u8F7D\u63D2\u4EF6\u5DF2\u542F\u7528\uFF0C\u914D\u7F6E\u4E86 ${options.routes.length} \u4E2A\u8DEF\u7531`);
253
- },
254
- resolveId(id) {
255
- if (id === VIRTUAL_MODULE_ID) {
256
- return RESOLVED_VIRTUAL_MODULE_ID;
257
- }
258
- return null;
259
- },
260
- load(id) {
261
- if (id === RESOLVED_VIRTUAL_MODULE_ID) {
262
- return generator.generateRuntime();
317
+ generator = new CodeGenerator(finalOptions);
318
+ if (finalOptions.debug) {
319
+ console.log(`\u{1F680} [\u9884\u52A0\u8F7D\u63D2\u4EF6] \u5DF2\u542F\u7528\uFF0C\u9884\u52A0\u8F7D ${finalOptions.routes.length} \u4E2A\u9875\u9762\uFF0C\u8BE6\u60C5\u8BF7\u67E5\u770B\u6D4F\u89C8\u5668\u63A7\u5236\u53F0`);
263
320
  }
264
- return null;
265
321
  },
266
- // 🎨 HTML 转换(修复类型错误)
322
+ // 🎨 HTML 转换 - 直接注入脚本到 HTML
267
323
  transformIndexHtml(html) {
268
324
  const inject = generator.generateHtmlInject();
269
- if (inject) {
270
- return html.replace(
271
- '<div id="app">',
272
- `<div id="app">
273
- ${inject}`
274
- );
275
- }
276
- return html;
325
+ return html.replace("</head>", `${inject}
326
+ </head>`);
277
327
  },
278
328
  // 🔥 HMR 支持
279
329
  handleHotUpdate(ctx) {
280
330
  if (ctx.file.includes("vite.config")) {
281
- console.log("\u{1F504} \u9884\u52A0\u8F7D\u914D\u7F6E\u5DF2\u66F4\u65B0");
331
+ if (finalOptions.debug) {
332
+ console.log("\u{1F504} [\u9884\u52A0\u8F7D\u63D2\u4EF6] \u914D\u7F6E\u5DF2\u66F4\u65B0");
333
+ }
282
334
  ctx.server.ws.send({
283
335
  type: "full-reload"
284
336
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/runtime.ts","../src/generator.ts"],"sourcesContent":["// ============================================================================\r\n// 🚀 src/index.ts - 主插件文件\r\n// ============================================================================\r\n\r\nimport type { Plugin } from 'vite'\r\nimport type { PreloaderOptions } from './types'\r\nimport { CodeGenerator } from './generator'\r\n\r\nconst VIRTUAL_MODULE_ID = 'virtual:preloader'\r\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0' + VIRTUAL_MODULE_ID\r\n\r\nexport default function preloaderPlugin(options: PreloaderOptions): Plugin {\r\n let generator: CodeGenerator\r\n\r\n return {\r\n name: 'vite-plugin-preloader',\r\n \r\n // 🎯 设置插件执行顺序\r\n enforce: 'post',\r\n \r\n configResolved() {\r\n generator = new CodeGenerator(options)\r\n console.log(`🚀 预加载插件已启用,配置了 ${options.routes.length} 个路由`)\r\n },\r\n\r\n resolveId(id) {\r\n if (id === VIRTUAL_MODULE_ID) {\r\n return RESOLVED_VIRTUAL_MODULE_ID\r\n }\r\n return null // 🔧 修复:明确返回 null\r\n },\r\n\r\n load(id) {\r\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\r\n return generator.generateRuntime()\r\n }\r\n return null // 🔧 修复:明确返回 null\r\n },\r\n\r\n // 🎨 HTML 转换(修复类型错误)\r\n transformIndexHtml(html) {\r\n const inject = generator.generateHtmlInject()\r\n if (inject) {\r\n return html.replace(\r\n '<div id=\"app\">',\r\n `<div id=\"app\">\\n ${inject}`\r\n )\r\n }\r\n return html // 🔧 修复:确保总是返回 html\r\n },\r\n\r\n // 🔥 HMR 支持\r\n handleHotUpdate(ctx) {\r\n if (ctx.file.includes('vite.config')) {\r\n console.log('🔄 预加载配置已更新')\r\n ctx.server.ws.send({\r\n type: 'full-reload'\r\n })\r\n return []\r\n }\r\n return undefined // 🔧 修复:明确返回 undefined\r\n }\r\n }\r\n}\r\n\r\n// 命名导出,支持多种导入方式\r\nexport { type PreloaderOptions, type PreloadRoute } from './types'","// ============================================================================\r\n// ⚡ src/runtime.ts - 运行时代码模板(字符串)\r\n// ============================================================================\r\n\r\nexport const runtimeTemplate = `// 🚀 Auto-generated by vite-plugin-preloader\r\nimport { ref, defineComponent, h, onMounted } from 'vue'\r\n\r\ninterface PreloadRoute {\r\n path: string\r\n component: () => Promise<any>\r\n reason: string\r\n priority: number\r\n}\r\n\r\ninterface PreloadStats {\r\n total: number\r\n completed: number\r\n failed: number\r\n startTime: number\r\n endTime: number\r\n}\r\n\r\n// 🎯 预加载配置(构建时注入)\r\nconst PRELOAD_ROUTES = __PRELOAD_ROUTES__\r\nconst PRELOAD_OPTIONS = __PRELOAD_OPTIONS__\r\n\r\nclass PreloaderManager {\r\n private preloadedRoutes = new Set()\r\n private isPreloading = ref(false)\r\n private stats = ref({\r\n total: 0, completed: 0, failed: 0, startTime: 0, endTime: 0\r\n })\r\n\r\n async start() {\r\n if (this.isPreloading.value) return\r\n\r\n this.isPreloading.value = true\r\n this.stats.value = {\r\n total: PRELOAD_ROUTES.length,\r\n completed: 0, failed: 0,\r\n startTime: Date.now(), endTime: 0\r\n }\r\n\r\n console.log(\\`🚀 [预加载] 开始预加载 \\${PRELOAD_ROUTES.length} 个页面\\`)\r\n\r\n const sortedRoutes = [...PRELOAD_ROUTES].sort((a, b) => a.priority - b.priority)\r\n \r\n for (const route of sortedRoutes) {\r\n await this.preloadSingle(route)\r\n await this.sleep(100)\r\n }\r\n\r\n this.stats.value.endTime = Date.now()\r\n this.isPreloading.value = false\r\n \r\n console.log(\\`🎉 [预加载] 完成! 耗时 \\${this.stats.value.endTime - this.stats.value.startTime}ms\\`)\r\n }\r\n\r\n async preloadSingle(route) {\r\n if (this.preloadedRoutes.has(route.path)) return\r\n\r\n try {\r\n const startTime = Date.now()\r\n await route.component()\r\n const loadTime = Date.now() - startTime\r\n \r\n this.preloadedRoutes.add(route.path)\r\n this.stats.value.completed++\r\n console.log(\\`✅ [预加载] \\${route.path} (\\${loadTime}ms) - \\${route.reason}\\`)\r\n } catch (error) {\r\n this.stats.value.failed++\r\n console.error(\\`❌ [预加载] \\${route.path} 失败:\\`, error)\r\n }\r\n }\r\n\r\n sleep(ms) {\r\n return new Promise(resolve => setTimeout(resolve, ms))\r\n }\r\n\r\n isPreloaded(path) {\r\n return this.preloadedRoutes.has(path)\r\n }\r\n\r\n getStats() {\r\n return {\r\n ...this.stats.value,\r\n preloadedPaths: Array.from(this.preloadedRoutes),\r\n isPreloading: this.isPreloading.value\r\n }\r\n }\r\n\r\n createStatusComponent() {\r\n const self = this\r\n return defineComponent({\r\n name: 'PreloadStatus',\r\n setup() {\r\n onMounted(() => {\r\n if (!document.getElementById('preloader-styles')) {\r\n const style = document.createElement('style')\r\n style.id = 'preloader-styles'\r\n const position = PRELOAD_OPTIONS.statusPosition.replace('-', ': 20px; ') + ': 20px;'\r\n style.textContent = \\`\r\n .preloader-status {\r\n position: fixed; \\${position}\r\n background: rgba(0,0,0,0.8); color: white; padding: 8px 16px;\r\n border-radius: 6px; font-size: 12px; z-index: 9999;\r\n pointer-events: none; font-family: system-ui;\r\n }\r\n \\`\r\n document.head.appendChild(style)\r\n }\r\n })\r\n\r\n return () => {\r\n if (!self.isPreloading.value || !import.meta.env.DEV || !PRELOAD_OPTIONS.showStatus) {\r\n return null\r\n }\r\n return h('div', { class: 'preloader-status' }, [\r\n '🔄 正在优化页面... ',\r\n \\`\\${self.stats.value.completed}/\\${self.stats.value.total}\\`\r\n ])\r\n }\r\n }\r\n })\r\n }\r\n}\r\n\r\n// 🚀 全局实例\r\nconst preloader = new PreloaderManager()\r\n\r\n// 🛠️ 开发环境调试工具\r\nif (import.meta.env.DEV && PRELOAD_OPTIONS.debug) {\r\n window.preloaderDebug = {\r\n stats: () => preloader.getStats(),\r\n restart: () => preloader.start(),\r\n check: (path) => preloader.isPreloaded(path),\r\n help: () => console.log('🛠️ 预加载调试: stats() | restart() | check(path)')\r\n }\r\n console.log('🛠️ 预加载调试工具: window.preloaderDebug')\r\n}\r\n\r\n// 🎯 导出\r\nexport const usePreloader = () => ({\r\n start: () => preloader.start(),\r\n isPreloaded: (path) => preloader.isPreloaded(path),\r\n StatusComponent: preloader.createStatusComponent()\r\n})\r\n\r\n// 🚀 自动启动\r\nif (typeof window !== 'undefined') {\r\n setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay || 2000)\r\n}`","// ============================================================================\r\n// 🛠️ src/generator.ts - 代码生成器\r\n// ============================================================================\r\n\r\nimport type { PreloaderOptions } from './types'\r\nimport { runtimeTemplate } from './runtime'\r\n\r\nexport class CodeGenerator {\r\n constructor(private options: PreloaderOptions) {}\r\n\r\n /**\r\n * 生成运行时代码\r\n */\r\n generateRuntime(): string {\r\n const routes = this.processRoutes()\r\n const options = this.processOptions()\r\n\r\n return runtimeTemplate\r\n .replace('__PRELOAD_ROUTES__', JSON.stringify(routes, null, 2))\r\n .replace('__PRELOAD_OPTIONS__', JSON.stringify(options, null, 2))\r\n }\r\n\r\n /**\r\n * 处理路由配置\r\n */\r\n private processRoutes(): any[] {\r\n return this.options.routes.map(route => {\r\n // 处理字符串输入\r\n if (typeof route === 'string') {\r\n const componentPath = this.inferComponentPath(route)\r\n return {\r\n path: route,\r\n component: `() => import('${componentPath}')`,\r\n reason: '自动推断的预加载页面',\r\n priority: 2\r\n }\r\n }\r\n \r\n // 处理对象输入\r\n const componentPath = route.component || this.inferComponentPath(route.path)\r\n return {\r\n path: route.path,\r\n component: `() => import('${componentPath}')`,\r\n reason: route.reason || '用户配置的预加载页面',\r\n priority: route.priority || 2\r\n }\r\n })\r\n }\r\n\r\n /**\r\n * 处理选项配置\r\n */\r\n private processOptions() {\r\n return {\r\n delay: this.options.delay || 2000,\r\n showStatus: this.options.showStatus !== false,\r\n statusPosition: this.options.statusPosition || 'bottom-right',\r\n debug: this.options.debug || false\r\n }\r\n }\r\n\r\n /**\r\n * 推断组件路径\r\n */\r\n private inferComponentPath(routePath: string): string {\r\n const cleanPath = routePath.replace(/^\\//, '').replace(/\\//g, '-')\r\n return `@/views/${cleanPath}/index.vue`\r\n }\r\n\r\n /**\r\n * 生成HTML注入代码\r\n */\r\n generateHtmlInject(): string {\r\n if (this.options.showStatus === false) return ''\r\n \r\n return '<preloader-status></preloader-status>'\r\n }\r\n}"],"mappings":"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","names":["componentPath"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/runtime.ts","../src/generator.ts"],"sourcesContent":["import type { Plugin } from 'vite'\r\nimport type { PreloaderOptions } from './types'\r\nimport { CodeGenerator } from './generator'\r\n\r\nexport default function preloaderPlugin(options: PreloaderOptions): Plugin {\r\n let generator: CodeGenerator\r\n const isDev = process.env.NODE_ENV !== 'production'\r\n \r\n // 智能默认配置\r\n const finalOptions = {\r\n debug: isDev, // 开发环境默认开启调试\r\n delay: 2000, // 默认2秒\r\n showStatus: true, // 默认显示状态\r\n statusPosition: 'bottom-right' as const, // 默认右下角\r\n ...options // 用户配置覆盖默认配置\r\n }\r\n\r\n return {\r\n name: 'vite-plugin-preloader',\r\n \r\n // 🎯 设置插件执行顺序\r\n enforce: 'post',\r\n \r\n configResolved() {\r\n generator = new CodeGenerator(finalOptions)\r\n \r\n if (finalOptions.debug) {\r\n console.log(`🚀 [预加载插件] 已启用,预加载 ${finalOptions.routes.length} 个页面,详情请查看浏览器控制台`)\r\n }\r\n },\r\n\r\n // 🎨 HTML 转换 - 直接注入脚本到 HTML\r\n transformIndexHtml(html) {\r\n const inject = generator.generateHtmlInject()\r\n \r\n // 注入到 head 标签末尾\r\n return html.replace('</head>', `${inject}\\n</head>`)\r\n },\r\n\r\n // 🔥 HMR 支持\r\n handleHotUpdate(ctx) {\r\n if (ctx.file.includes('vite.config')) {\r\n if (finalOptions.debug) {\r\n console.log('🔄 [预加载插件] 配置已更新')\r\n }\r\n ctx.server.ws.send({\r\n type: 'full-reload'\r\n })\r\n return []\r\n }\r\n return undefined\r\n }\r\n }\r\n}\r\n\r\n// 命名导出,支持多种导入方式\r\nexport { type PreloaderOptions, type PreloadRoute } from './types'","// ============================================================================\r\n// ⚡ src/runtime.ts - 运行时代码模板(字符串)\r\n// ============================================================================\r\nexport const runtimeTemplate = `// 🚀 Auto-generated by vite-plugin-preloader\r\n(function() {\r\n 'use strict';\r\n \r\n // 🎯 预加载配置(构建时注入)\r\n const PRELOAD_ROUTES = __PRELOAD_ROUTES__\r\n const PRELOAD_OPTIONS = __PRELOAD_OPTIONS__\r\n\r\n class PreloaderManager {\r\n constructor() {\r\n this.preloadedRoutes = new Set()\r\n this.isPreloading = false\r\n this.stats = {\r\n total: 0, completed: 0, failed: 0, startTime: 0, endTime: 0\r\n }\r\n this.statusElement = null\r\n }\r\n\r\n async start() {\r\n if (this.isPreloading) return\r\n\r\n this.isPreloading = true\r\n this.stats = {\r\n total: PRELOAD_ROUTES.length,\r\n completed: 0, failed: 0,\r\n startTime: Date.now(), endTime: 0\r\n }\r\n\r\n if (PRELOAD_OPTIONS.debug) {\r\n console.log(\\`🚀 [预加载] 开始预加载 \\${PRELOAD_ROUTES.length} 个页面\\`)\r\n }\r\n\r\n // 显示状态指示器\r\n this.showStatus()\r\n\r\n const sortedRoutes = [...PRELOAD_ROUTES].sort((a, b) => a.priority - b.priority)\r\n \r\n for (const route of sortedRoutes) {\r\n await this.preloadSingle(route)\r\n this.updateStatus()\r\n await this.sleep(100)\r\n }\r\n\r\n this.stats.endTime = Date.now()\r\n this.isPreloading = false\r\n \r\n if (PRELOAD_OPTIONS.debug) {\r\n console.log(\\`🎉 [预加载] 完成! 耗时 \\${this.stats.endTime - this.stats.startTime}ms\\`)\r\n }\r\n\r\n // 隐藏状态指示器\r\n this.hideStatus()\r\n }\r\n\r\n async preloadSingle(route) {\r\n if (this.preloadedRoutes.has(route.path)) return\r\n\r\n try {\r\n const startTime = Date.now()\r\n let componentPath = route.component\r\n \r\n // 在开发环境中,Vite 会处理模块解析\r\n // 我们需要使用正确的模块 ID\r\n if (componentPath.startsWith('@/')) {\r\n // 对于 Vite,@ 别名应该在构建时就被解析\r\n // 但在运行时我们需要使用实际的路径\r\n componentPath = componentPath.replace('@/', '/src/')\r\n }\r\n \r\n // 确保路径以 / 开头(相对于项目根目录)\r\n if (!componentPath.startsWith('/') && !componentPath.startsWith('./')) {\r\n componentPath = '/' + componentPath\r\n }\r\n \r\n if (PRELOAD_OPTIONS.debug) {\r\n console.log(\\`🔍 [预加载] 尝试加载: \\${componentPath}\\`)\r\n }\r\n \r\n const module = await import(/* @vite-ignore */ componentPath)\r\n const loadTime = Date.now() - startTime\r\n \r\n this.preloadedRoutes.add(route.path)\r\n this.stats.completed++\r\n \r\n if (PRELOAD_OPTIONS.debug) {\r\n console.log(\\`✅ [预加载] \\${route.path} (\\${loadTime}ms) - \\${route.reason}\\`)\r\n }\r\n } catch (error) {\r\n this.stats.failed++\r\n if (PRELOAD_OPTIONS.debug) {\r\n console.error(\\`❌ [预加载] \\${route.path} 失败:\\`, error)\r\n }\r\n }\r\n }\r\n\r\n showStatus() {\r\n if (!PRELOAD_OPTIONS.showStatus || !document.body) return\r\n\r\n // 添加样式\r\n if (!document.getElementById('preloader-styles')) {\r\n const style = document.createElement('style')\r\n style.id = 'preloader-styles'\r\n const position = PRELOAD_OPTIONS.statusPosition.replace('-', ': 20px; ') + ': 20px;'\r\n style.textContent = \\`\r\n .preloader-status {\r\n position: fixed; \\${position}\r\n background: rgba(0,0,0,0.8); color: white; padding: 8px 16px;\r\n border-radius: 6px; font-size: 12px; z-index: 9999;\r\n pointer-events: none; font-family: system-ui;\r\n transition: opacity 0.3s ease;\r\n }\r\n .preloader-status.fade-out {\r\n opacity: 0;\r\n }\r\n \\`\r\n document.head.appendChild(style)\r\n }\r\n\r\n // 创建状态元素\r\n this.statusElement = document.createElement('div')\r\n this.statusElement.className = 'preloader-status'\r\n this.updateStatus()\r\n document.body.appendChild(this.statusElement)\r\n }\r\n\r\n updateStatus() {\r\n if (!this.statusElement) return\r\n this.statusElement.textContent = \\`🔄 正在优化页面... \\${this.stats.completed}/\\${this.stats.total}\\`\r\n }\r\n\r\n hideStatus() {\r\n if (!this.statusElement) return\r\n this.statusElement.classList.add('fade-out')\r\n setTimeout(() => {\r\n if (this.statusElement && this.statusElement.parentNode) {\r\n this.statusElement.parentNode.removeChild(this.statusElement)\r\n }\r\n }, 300)\r\n }\r\n\r\n sleep(ms) {\r\n return new Promise(resolve => setTimeout(resolve, ms))\r\n }\r\n\r\n isPreloaded(path) {\r\n return this.preloadedRoutes.has(path)\r\n }\r\n\r\n getStats() {\r\n return {\r\n ...this.stats,\r\n preloadedPaths: Array.from(this.preloadedRoutes),\r\n isPreloading: this.isPreloading\r\n }\r\n }\r\n }\r\n\r\n // 🚀 全局实例\r\n const preloader = new PreloaderManager()\r\n\r\n // 🛠️ 开发环境调试工具\r\n if (PRELOAD_OPTIONS.debug) {\r\n window.preloaderDebug = {\r\n stats: () => preloader.getStats(),\r\n restart: () => preloader.start(),\r\n check: (path) => preloader.isPreloaded(path),\r\n help: () => console.log('🛠️ 预加载调试: stats() | restart() | check(path)')\r\n }\r\n console.log('🛠️ 预加载调试工具: window.preloaderDebug')\r\n }\r\n\r\n // 🚀 自动启动 - 等待 DOM 加载完成\r\n function autoStart() {\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', () => {\r\n setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay)\r\n })\r\n } else {\r\n setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay)\r\n }\r\n }\r\n\r\n // 立即执行自动启动\r\n autoStart()\r\n\r\n // 导出到全局(可选使用)\r\n window.usePreloader = () => ({\r\n start: () => preloader.start(),\r\n isPreloaded: (path) => preloader.isPreloaded(path),\r\n getStats: () => preloader.getStats()\r\n })\r\n\r\n})();`","// ============================================================================\r\n// 🛠️ src/generator.ts - 代码生成器\r\n// ============================================================================\r\nimport type { PreloaderOptions } from './types'\r\nimport { runtimeTemplate } from './runtime'\r\n\r\nexport class CodeGenerator {\r\n constructor(private options: PreloaderOptions) {}\r\n\r\n /**\r\n * 生成运行时代码\r\n */\r\n generateRuntime(): string {\r\n const routes = this.processRoutes();\r\n const options = this.processOptions();\r\n\r\n return runtimeTemplate\r\n .replace(\"__PRELOAD_ROUTES__\", JSON.stringify(routes, null, 2))\r\n .replace(\"__PRELOAD_OPTIONS__\", JSON.stringify(options, null, 2));\r\n }\r\n\r\n /**\r\n * 处理路由配置\r\n */\r\n private processRoutes(): any[] {\r\n return this.options.routes.map((route) => {\r\n // 处理字符串输入\r\n if (typeof route === \"string\") {\r\n const componentPath = this.inferComponentPath(route);\r\n return {\r\n path: route,\r\n component: componentPath,\r\n reason: \"自动推断的预加载页面\",\r\n priority: 2,\r\n };\r\n }\r\n\r\n // 处理对象输入\r\n const componentPath =\r\n route.component || this.inferComponentPath(route.path);\r\n return {\r\n path: route.path,\r\n component: componentPath,\r\n reason: route.reason || \"用户配置的预加载页面\",\r\n priority: route.priority || 2,\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * 处理选项配置\r\n */\r\n private processOptions() {\r\n // 智能默认配置\r\n const isDev = process.env.NODE_ENV !== \"production\";\r\n\r\n return {\r\n delay: this.options.delay ?? 2000, // 默认2秒\r\n showStatus: this.options.showStatus ?? true, // 默认显示状态\r\n statusPosition: this.options.statusPosition ?? \"bottom-right\", // 默认右下角\r\n debug: this.options.debug ?? isDev, // 开发环境默认开启调试,生产环境默认关闭\r\n };\r\n }\r\n\r\n /**\r\n * 推断组件路径 - 使用 Vite 别名格式\r\n */\r\n private inferComponentPath(routePath: string): string {\r\n const cleanPath = routePath.replace(/^\\//, \"\");\r\n\r\n // 直接使用 @ 别名,这在 Vite 构建后会被正确解析\r\n if (cleanPath.startsWith(\"demo/\")) {\r\n // /demo/13-calendar -> @/views/demo/13-calendar/index.vue\r\n return `@/views/${cleanPath}/index.vue`;\r\n }\r\n\r\n // 其他路径的处理\r\n const pathSegments = cleanPath.split(\"/\");\r\n return `@/views/${pathSegments.join(\"/\")}/index.vue`;\r\n }\r\n\r\n /**\r\n * 生成注入到 HTML 头部的脚本\r\n */\r\n generateHtmlInject(): string {\r\n return `<script type=\"module\">\r\n${this.generateRuntime()}\r\n</script>`;\r\n }\r\n}"],"mappings":"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","names":["componentPath"]}