vite-plugin-preloader 1.0.0 → 1.1.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.js CHANGED
@@ -27,153 +27,181 @@ 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()
63
+
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
+ }
60
78
 
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
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
+ // \u4F7F\u7528 eval \u6765\u52A8\u6001\u6267\u884C\u5BFC\u5165\u51FD\u6570\u5B57\u7B26\u4E32
89
+ const importFn = eval('(' + route.component + ')')
90
+ await importFn()
91
+ const loadTime = Date.now() - startTime
92
+
93
+ this.preloadedRoutes.add(route.path)
94
+ this.stats.completed++
95
+
96
+ if (PRELOAD_OPTIONS.debug) {
97
+ console.log(\`\u2705 [\u9884\u52A0\u8F7D] \${route.path} (\${loadTime}ms) - \${route.reason}\`)
98
+ }
99
+ } catch (error) {
100
+ this.stats.failed++
101
+ if (PRELOAD_OPTIONS.debug) {
102
+ console.error(\`\u274C [\u9884\u52A0\u8F7D] \${route.path} \u5931\u8D25:\`, error)
103
+ }
104
+ }
75
105
  }
76
106
 
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
- }
107
+ showStatus() {
108
+ if (!PRELOAD_OPTIONS.showStatus || !document.body) return
82
109
 
83
- async preloadSingle(route) {
84
- if (this.preloadedRoutes.has(route.path)) return
110
+ // \u6DFB\u52A0\u6837\u5F0F
111
+ if (!document.getElementById('preloader-styles')) {
112
+ const style = document.createElement('style')
113
+ style.id = 'preloader-styles'
114
+ const position = PRELOAD_OPTIONS.statusPosition.replace('-', ': 20px; ') + ': 20px;'
115
+ style.textContent = \`
116
+ .preloader-status {
117
+ position: fixed; \${position}
118
+ background: rgba(0,0,0,0.8); color: white; padding: 8px 16px;
119
+ border-radius: 6px; font-size: 12px; z-index: 9999;
120
+ pointer-events: none; font-family: system-ui;
121
+ transition: opacity 0.3s ease;
122
+ }
123
+ .preloader-status.fade-out {
124
+ opacity: 0;
125
+ }
126
+ \`
127
+ document.head.appendChild(style)
128
+ }
85
129
 
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)
130
+ // \u521B\u5EFA\u72B6\u6001\u5143\u7D20
131
+ this.statusElement = document.createElement('div')
132
+ this.statusElement.className = 'preloader-status'
133
+ this.updateStatus()
134
+ document.body.appendChild(this.statusElement)
97
135
  }
98
- }
99
136
 
100
- sleep(ms) {
101
- return new Promise(resolve => setTimeout(resolve, ms))
102
- }
137
+ updateStatus() {
138
+ if (!this.statusElement) return
139
+ this.statusElement.textContent = \`\u{1F504} \u6B63\u5728\u4F18\u5316\u9875\u9762... \${this.stats.completed}/\${this.stats.total}\`
140
+ }
103
141
 
104
- isPreloaded(path) {
105
- return this.preloadedRoutes.has(path)
106
- }
142
+ hideStatus() {
143
+ if (!this.statusElement) return
144
+ this.statusElement.classList.add('fade-out')
145
+ setTimeout(() => {
146
+ if (this.statusElement && this.statusElement.parentNode) {
147
+ this.statusElement.parentNode.removeChild(this.statusElement)
148
+ }
149
+ }, 300)
150
+ }
107
151
 
108
- getStats() {
109
- return {
110
- ...this.stats.value,
111
- preloadedPaths: Array.from(this.preloadedRoutes),
112
- isPreloading: this.isPreloading.value
152
+ sleep(ms) {
153
+ return new Promise(resolve => setTimeout(resolve, ms))
113
154
  }
114
- }
115
155
 
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
- })
156
+ isPreloaded(path) {
157
+ return this.preloadedRoutes.has(path)
158
+ }
137
159
 
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
- }
160
+ getStats() {
161
+ return {
162
+ ...this.stats,
163
+ preloadedPaths: Array.from(this.preloadedRoutes),
164
+ isPreloading: this.isPreloading
147
165
  }
148
- })
166
+ }
149
167
  }
150
- }
151
168
 
152
- // \u{1F680} \u5168\u5C40\u5B9E\u4F8B
153
- const preloader = new PreloaderManager()
169
+ // \u{1F680} \u5168\u5C40\u5B9E\u4F8B
170
+ const preloader = new PreloaderManager()
154
171
 
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)')
172
+ // \u{1F6E0}\uFE0F \u5F00\u53D1\u73AF\u5883\u8C03\u8BD5\u5DE5\u5177
173
+ if (PRELOAD_OPTIONS.debug) {
174
+ window.preloaderDebug = {
175
+ stats: () => preloader.getStats(),
176
+ restart: () => preloader.start(),
177
+ check: (path) => preloader.isPreloaded(path),
178
+ help: () => console.log('\u{1F6E0}\uFE0F \u9884\u52A0\u8F7D\u8C03\u8BD5: stats() | restart() | check(path)')
179
+ }
180
+ console.log('\u{1F6E0}\uFE0F \u9884\u52A0\u8F7D\u8C03\u8BD5\u5DE5\u5177: window.preloaderDebug')
181
+ }
182
+
183
+ // \u{1F680} \u81EA\u52A8\u542F\u52A8 - \u7B49\u5F85 DOM \u52A0\u8F7D\u5B8C\u6210
184
+ function autoStart() {
185
+ if (document.readyState === 'loading') {
186
+ document.addEventListener('DOMContentLoaded', () => {
187
+ setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay)
188
+ })
189
+ } else {
190
+ setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay)
191
+ }
162
192
  }
163
- console.log('\u{1F6E0}\uFE0F \u9884\u52A0\u8F7D\u8C03\u8BD5\u5DE5\u5177: window.preloaderDebug')
164
- }
165
193
 
166
- // \u{1F3AF} \u5BFC\u51FA
167
- export const usePreloader = () => ({
168
- start: () => preloader.start(),
169
- isPreloaded: (path) => preloader.isPreloaded(path),
170
- StatusComponent: preloader.createStatusComponent()
171
- })
194
+ // \u7ACB\u5373\u6267\u884C\u81EA\u52A8\u542F\u52A8
195
+ autoStart()
196
+
197
+ // \u5BFC\u51FA\u5230\u5168\u5C40\uFF08\u53EF\u9009\u4F7F\u7528\uFF09
198
+ window.usePreloader = () => ({
199
+ start: () => preloader.start(),
200
+ isPreloaded: (path) => preloader.isPreloaded(path),
201
+ getStats: () => preloader.getStats()
202
+ })
172
203
 
173
- // \u{1F680} \u81EA\u52A8\u542F\u52A8
174
- if (typeof window !== 'undefined') {
175
- setTimeout(() => preloader.start(), PRELOAD_OPTIONS.delay || 2000)
176
- }`;
204
+ })();`;
177
205
 
178
206
  // src/generator.ts
179
207
  var CodeGenerator = class {
@@ -186,6 +214,9 @@ var CodeGenerator = class {
186
214
  generateRuntime() {
187
215
  const routes = this.processRoutes();
188
216
  const options = this.processOptions();
217
+ if (options.debug) {
218
+ console.log("\u{1F527} [\u9884\u52A0\u8F7D] \u751F\u6210\u8FD0\u884C\u65F6\u4EE3\u7801\uFF0C\u8DEF\u7531\u6570\u91CF:", routes.length);
219
+ }
189
220
  return runtimeTemplate.replace("__PRELOAD_ROUTES__", JSON.stringify(routes, null, 2)).replace("__PRELOAD_OPTIONS__", JSON.stringify(options, null, 2));
190
221
  }
191
222
  /**
@@ -193,6 +224,15 @@ var CodeGenerator = class {
193
224
  */
194
225
  processRoutes() {
195
226
  return this.options.routes.map((route) => {
227
+ if (typeof route === "string") {
228
+ const componentPath2 = this.inferComponentPath(route);
229
+ return {
230
+ path: route,
231
+ component: `() => import('${componentPath2}')`,
232
+ reason: "\u81EA\u52A8\u63A8\u65AD\u7684\u9884\u52A0\u8F7D\u9875\u9762",
233
+ priority: 2
234
+ };
235
+ }
196
236
  const componentPath = route.component || this.inferComponentPath(route.path);
197
237
  return {
198
238
  path: route.path,
@@ -206,70 +246,87 @@ var CodeGenerator = class {
206
246
  * 处理选项配置
207
247
  */
208
248
  processOptions() {
249
+ const isDev = process.env.NODE_ENV !== "production";
209
250
  return {
210
- delay: this.options.delay || 2e3,
211
- showStatus: this.options.showStatus !== false,
212
- statusPosition: this.options.statusPosition || "bottom-right",
213
- debug: this.options.debug || false
251
+ delay: this.options.delay ?? 2e3,
252
+ // 默认2秒
253
+ showStatus: this.options.showStatus ?? true,
254
+ // 默认显示状态
255
+ statusPosition: this.options.statusPosition ?? "bottom-right",
256
+ // 默认右下角
257
+ debug: this.options.debug ?? isDev
258
+ // 开发环境默认开启调试,生产环境默认关闭
214
259
  };
215
260
  }
216
261
  /**
217
262
  * 推断组件路径
218
263
  */
219
264
  inferComponentPath(routePath) {
220
- const cleanPath = routePath.replace(/^\//, "").replace(/\//g, "-");
221
- return `@/views/${cleanPath}/index.vue`;
265
+ const cleanPath = routePath.replace(/^\//, "");
266
+ if (cleanPath.startsWith("demo/")) {
267
+ return `@/views/${cleanPath}/index.vue`;
268
+ }
269
+ const pathSegments = cleanPath.split("/");
270
+ return `@/views/${pathSegments.join("/")}/index.vue`;
222
271
  }
223
272
  /**
224
- * 生成HTML注入代码
273
+ * 生成注入到 HTML 头部的脚本
225
274
  */
226
275
  generateHtmlInject() {
227
- if (this.options.showStatus === false) return "";
228
- return "<preloader-status></preloader-status>";
276
+ return `<script type="module">
277
+ ${this.generateRuntime()}
278
+ </script>`;
229
279
  }
230
280
  };
231
281
 
232
282
  // src/index.ts
233
- var VIRTUAL_MODULE_ID = "virtual:preloader";
234
- var RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
235
283
  function preloaderPlugin(options) {
236
284
  let generator;
285
+ const isDev = process.env.NODE_ENV !== "production";
286
+ const finalOptions = {
287
+ debug: isDev,
288
+ // 开发环境默认开启调试
289
+ delay: 2e3,
290
+ // 默认2秒
291
+ showStatus: true,
292
+ // 默认显示状态
293
+ statusPosition: "bottom-right",
294
+ // 默认右下角
295
+ ...options
296
+ // 用户配置覆盖默认配置
297
+ };
237
298
  return {
238
299
  name: "vite-plugin-preloader",
239
300
  // 🎯 设置插件执行顺序
240
301
  enforce: "post",
241
302
  configResolved() {
242
- generator = new CodeGenerator(options);
243
- console.log(`\u{1F680} \u9884\u52A0\u8F7D\u63D2\u4EF6\u5DF2\u542F\u7528\uFF0C\u914D\u7F6E\u4E86 ${options.routes.length} \u4E2A\u8DEF\u7531`);
244
- },
245
- resolveId(id) {
246
- if (id === VIRTUAL_MODULE_ID) {
247
- return RESOLVED_VIRTUAL_MODULE_ID;
248
- }
249
- return null;
250
- },
251
- load(id) {
252
- if (id === RESOLVED_VIRTUAL_MODULE_ID) {
253
- return generator.generateRuntime();
303
+ generator = new CodeGenerator(finalOptions);
304
+ if (finalOptions.debug) {
305
+ console.log(`\u{1F680} [\u9884\u52A0\u8F7D\u63D2\u4EF6] \u5DF2\u542F\u7528\uFF0C\u914D\u7F6E\u4E86 ${finalOptions.routes.length} \u4E2A\u8DEF\u7531`);
306
+ console.log("\u{1F4CB} [\u9884\u52A0\u8F7D\u63D2\u4EF6] \u8DEF\u7531\u5217\u8868:", finalOptions.routes);
307
+ console.log("\u2699\uFE0F [\u9884\u52A0\u8F7D\u63D2\u4EF6] \u914D\u7F6E\u9009\u9879:", {
308
+ delay: finalOptions.delay,
309
+ showStatus: finalOptions.showStatus,
310
+ statusPosition: finalOptions.statusPosition,
311
+ debug: finalOptions.debug
312
+ });
254
313
  }
255
- return null;
256
314
  },
257
- // 🎨 HTML 转换(修复类型错误)
315
+ // 🎨 HTML 转换 - 直接注入脚本到 HTML
258
316
  transformIndexHtml(html) {
259
317
  const inject = generator.generateHtmlInject();
260
- if (inject) {
261
- return html.replace(
262
- '<div id="app">',
263
- `<div id="app">
264
- ${inject}`
265
- );
318
+ if (finalOptions.debug) {
319
+ console.log("\u{1F3A8} [\u9884\u52A0\u8F7D\u63D2\u4EF6] \u6CE8\u5165\u9884\u52A0\u8F7D\u811A\u672C\u5230 HTML");
266
320
  }
267
- return html;
321
+ return html.replace("</head>", `${inject}
322
+ </head>`);
268
323
  },
269
324
  // 🔥 HMR 支持
270
325
  handleHotUpdate(ctx) {
271
326
  if (ctx.file.includes("vite.config")) {
272
- console.log("\u{1F504} \u9884\u52A0\u8F7D\u914D\u7F6E\u5DF2\u66F4\u65B0");
327
+ if (finalOptions.debug) {
328
+ console.log("\u{1F504} [\u9884\u52A0\u8F7D\u63D2\u4EF6] \u914D\u7F6E\u5DF2\u66F4\u65B0");
329
+ }
273
330
  ctx.server.ws.send({
274
331
  type: "full-reload"
275
332
  });
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, PreloadRoute } 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 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":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/runtime.ts","../src/generator.ts"],"sourcesContent":["// ============================================================================\r\n// 🚀 src/index.ts - 主插件文件\r\n// ============================================================================\r\nimport 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 console.log('📋 [预加载插件] 路由列表:', finalOptions.routes)\r\n console.log('⚙️ [预加载插件] 配置选项:', {\r\n delay: finalOptions.delay,\r\n showStatus: finalOptions.showStatus,\r\n statusPosition: finalOptions.statusPosition,\r\n debug: finalOptions.debug\r\n })\r\n }\r\n },\r\n\r\n // 🎨 HTML 转换 - 直接注入脚本到 HTML\r\n transformIndexHtml(html) {\r\n const inject = generator.generateHtmlInject()\r\n \r\n if (finalOptions.debug) {\r\n console.log('🎨 [预加载插件] 注入预加载脚本到 HTML')\r\n }\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 // 使用 eval 来动态执行导入函数字符串\r\n const importFn = eval('(' + route.component + ')')\r\n await importFn()\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 if (options.debug) {\r\n console.log('🔧 [预加载] 生成运行时代码,路由数量:', routes.length)\r\n }\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 // 智能默认配置\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 * 推断组件路径\r\n */\r\n private inferComponentPath(routePath: string): string {\r\n const cleanPath = routePath.replace(/^\\//, '')\r\n \r\n // 如果是 demo/ 开头的路径,保持原有结构\r\n if (cleanPath.startsWith('demo/')) {\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"]}