vite-add-cdn-script 0.0.7 → 0.0.9

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/README.md CHANGED
@@ -77,13 +77,13 @@ export default defineConfig({
77
77
 
78
78
  options
79
79
 
80
- | 参数 | 解析 | 类型 | 默认值 |
81
- | ------------ | ------------------- | --------------------------- | --------------------- |
82
- | customScript | 自定义 cdn 脚本 | { [*key*: string]: string } | 无 |
83
- | retryTimes | 重试次数 | number | 3 |
80
+ | 参数 | 解析 | 类型 | 默认值 |
81
+ | ------------ | ------------------- | --------------------------- | --------------------------------------- |
82
+ | customScript | 自定义 cdn 脚本 | { [*key*: string]: string } | 无 |
83
+ | retryTimes | 换源重试次数 | number | defaultCdns.length - 1 |
84
84
  | defaultCdns | 默认使用 cdn 的顺序 | string[] | ["jsdelivr", "unpkg"] |
85
85
 
86
86
  ## 注意事项
87
87
 
88
88
  - 接入了各大 cdn 的 api 接口进行请求,默认会保存一份 cdn 的缓存在你的根目录中`.cdn-cache.json`。如果发现缓存的资源有问题可以删除该文件,然后重新执行打包流程。
89
- - 按顺序添加cdn,如react-router-dom需要依赖react、@remix-run/router、react-router,因此需要放在最后。
89
+ - 按顺序添加 cdn,如 react-router-dom 需要依赖 react、@remix-run/router、react-router,因此需要放在最后。
package/dist/index.js CHANGED
@@ -1,22 +1,22 @@
1
1
  var D = Object.defineProperty;
2
2
  var F = (n, t, e) => t in n ? D(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
3
- var y = (n, t, e) => (F(n, typeof t != "symbol" ? t + "" : t, e), e);
4
- import U from "node:path";
5
- import w from "node:fs";
6
- import b from "node:https";
7
- class E {
3
+ var f = (n, t, e) => (F(n, typeof t != "symbol" ? t + "" : t, e), e);
4
+ import J from "node:path";
5
+ import j from "node:fs";
6
+ import E from "node:https";
7
+ class L {
8
8
  constructor() {
9
- y(this, "cdnCache", {});
10
- y(this, "cdnCachePath", "");
11
- this.cdnCachePath = U.resolve(process.cwd(), "./.cdn-cache.json");
9
+ f(this, "cdnCache", {});
10
+ f(this, "cdnCachePath", "");
11
+ this.cdnCachePath = J.resolve(process.cwd(), "./.cdn-cache.json");
12
12
  }
13
13
  // 初始化cdn缓存
14
14
  async init() {
15
15
  try {
16
- const t = await w.readFileSync(this.cdnCachePath, "utf-8");
16
+ const t = await j.readFileSync(this.cdnCachePath, "utf-8");
17
17
  this.cdnCache = JSON.parse(t);
18
18
  } catch {
19
- console.log("cdn缓存文件不存在,创建缓存文件"), this.cdnCache = {}, await w.writeFileSync(this.cdnCachePath, "", "utf-8");
19
+ console.log("cdn缓存文件不存在,创建缓存文件"), this.cdnCache = {}, await j.writeFileSync(this.cdnCachePath, "", "utf-8");
20
20
  }
21
21
  }
22
22
  /**
@@ -43,135 +43,171 @@ class E {
43
43
  * 更新cdn缓存
44
44
  */
45
45
  async save() {
46
- await w.writeFileSync(this.cdnCachePath, JSON.stringify(this.cdnCache), "utf-8");
46
+ await j.writeFileSync(this.cdnCachePath, JSON.stringify(this.cdnCache), "utf-8");
47
47
  }
48
48
  }
49
- let $;
50
- const L = async () => ($ || ($ = new E(), await $.init()), $), f = {
49
+ let y;
50
+ const I = async () => (y || (y = new L(), await y.init()), y);
51
+ class N {
52
+ constructor(t) {
53
+ f(this, "_max");
54
+ f(this, "_count");
55
+ f(this, "_taskQueue");
56
+ this._max = t || 5, this._count = 0, this._taskQueue = [];
57
+ }
58
+ /**
59
+ * 请求封装
60
+ * @param caller 请求函数
61
+ * @param args 请求参数
62
+ * @returns {Promise<any>} 返回一个promise
63
+ */
64
+ call(t, ...e) {
65
+ return new Promise((r, s) => {
66
+ const c = this._createTask(t, e, r, s);
67
+ this._count >= this._max ? this._taskQueue.push(c) : c();
68
+ });
69
+ }
70
+ /**
71
+ * 创建一个任务
72
+ * @param caller 实际执行的函数
73
+ * @param args 执行函数的参数
74
+ * @param resolve
75
+ * @param reject
76
+ * @returns {Function} 返回一个任务函数
77
+ * @private
78
+ */
79
+ _createTask(t, e, r, s) {
80
+ return () => {
81
+ t(...e).then(r).catch(s).finally(() => {
82
+ this._count--, this._taskQueue.length && this._taskQueue.shift()();
83
+ }), this._count++;
84
+ };
85
+ }
86
+ }
87
+ const U = new N(5), R = {
51
88
  //get请求封装
52
89
  get: (n, t, e) => new Promise((r, s) => {
53
90
  try {
54
- b.get(n, (i) => {
55
- let o = "";
56
- i.on("data", (c) => {
57
- o += c;
58
- }), i.on("end", () => {
59
- t == null || t(o), r(o);
91
+ E.get(n, (c) => {
92
+ let i = "";
93
+ c.on("data", (o) => {
94
+ i += o;
95
+ }), c.on("end", () => {
96
+ t == null || t(i), r(i);
60
97
  });
98
+ }).on("error", function(c) {
99
+ e == null || e(c), s(c);
61
100
  });
62
- } catch (i) {
63
- e == null || e(i), s(i);
101
+ } catch (c) {
102
+ e == null || e(c), s(c);
64
103
  }
65
104
  })
66
- }, N = async (n) => {
67
- const t = /^(https:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;
105
+ }, w = {
106
+ get: U.call.bind(U, R.get)
107
+ }, A = {
108
+ getFileList: (n, t) => new Promise((e, r) => {
109
+ w.get(
110
+ `https://api.bootcdn.cn/libraries/${n}`,
111
+ (s) => {
112
+ const c = JSON.parse(s);
113
+ if (c.length === 0) {
114
+ r(new Error(`${n} not found in bootcdn`));
115
+ return;
116
+ }
117
+ const i = c[0], a = i.assets.find((d) => d.version === t);
118
+ if (!a) {
119
+ r(new Error(`${n}@${t} not found in ${i.name}`));
120
+ return;
121
+ }
122
+ const l = a.files.map((d) => ({
123
+ name: "/" + d
124
+ }));
125
+ e({ fileList: l, recommendFileName: i.filename });
126
+ },
127
+ (s) => {
128
+ r(s);
129
+ }
130
+ );
131
+ }),
132
+ getUrl: (n, t, e) => `https://cdn.bootcdn.net/ajax/libs/${n}/${t}${e}`
133
+ }, M = {
134
+ getFileList: (n, t) => new Promise((e, r) => {
135
+ w.get(
136
+ `https://api.cdnjs.com/libraries/${n}/${t}`,
137
+ (s) => {
138
+ const c = JSON.parse(s);
139
+ if (c.error) {
140
+ r(new Error(`cdnjs: ${n}@${t} not found`));
141
+ return;
142
+ }
143
+ e({
144
+ fileList: c.rawFiles.map((i) => ({
145
+ name: "/" + i
146
+ }))
147
+ });
148
+ },
149
+ (s) => {
150
+ r(s);
151
+ }
152
+ );
153
+ }),
154
+ getUrl: (n, t, e) => `https://cdnjs.cloudflare.com/ajax/libs/${n}/${t}${e}`
155
+ }, V = {
156
+ getFileList: (n, t) => new Promise((e, r) => {
157
+ w.get(
158
+ `https://data.jsdelivr.com/v1/stats/packages/npm/${n}@${t}/files`,
159
+ (s) => {
160
+ const c = JSON.parse(s);
161
+ if (c.length === 0) {
162
+ r(new Error(`${n}@${t} not found`));
163
+ return;
164
+ }
165
+ e({ fileList: c });
166
+ },
167
+ (s) => {
168
+ r(s);
169
+ }
170
+ );
171
+ }),
172
+ // 拼接url
173
+ getUrl: (n, t, e) => `https://cdn.jsdelivr.net/npm/${n}@${t}${e}`
174
+ }, b = (n) => n.reduce((t, e) => (e.type === "file" ? t.push({ name: e.path }) : e.files && t.push(...b(e.files)), t), []), T = {
175
+ getFileList: (n, t) => new Promise((e, r) => {
176
+ w.get(
177
+ `https://unpkg.com/${n}@${t}/?meta`,
178
+ (s) => {
179
+ const c = JSON.parse(s);
180
+ e({ fileList: b(c.files || []) });
181
+ },
182
+ (s) => {
183
+ r(s);
184
+ }
185
+ );
186
+ }),
187
+ getUrl: (n, t, e) => `https://unpkg.com/${n}@${t}${e}`
188
+ }, Q = async (n) => {
189
+ const t = /^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;
68
190
  if (t.test(n)) {
69
191
  const e = n.replace(t, (r, s) => `${s}package.json`);
70
- return JSON.parse(await f.get(e));
192
+ return JSON.parse(await w.get(e));
71
193
  } else
72
194
  throw new Error(`${n} 不是正确的url`);
73
- }, I = (n, t) => {
195
+ }, q = (n, t) => {
74
196
  var e, r;
75
197
  return ((e = n.dependencies) == null ? void 0 : e[t]) || ((r = n.devDependencies) == null ? void 0 : r[t]);
76
- }, k = (n) => n.reduce((t, e) => (e.type === "file" ? t.push({ name: e.path }) : e.files && t.push(...k(e.files)), t), []), x = {
77
- jsdelivr: {
78
- getFileList: (n, t) => new Promise((e, r) => {
79
- f.get(
80
- `https://data.jsdelivr.com/v1/stats/packages/npm/${n}@${t}/files`,
81
- (s) => {
82
- const i = JSON.parse(s);
83
- if (i.length === 0) {
84
- r(new Error(`${n}@${t} not found`));
85
- return;
86
- }
87
- e({ fileList: i });
88
- },
89
- (s) => {
90
- r(s);
91
- }
92
- );
93
- }),
94
- // 拼接url
95
- getUrl: (n, t, e) => `https://cdn.jsdelivr.net/npm/${n}@${t}${e}`
96
- },
97
- unpkg: {
98
- getFileList: (n, t) => new Promise((e, r) => {
99
- f.get(
100
- `https://unpkg.com/${n}@${t}/?meta`,
101
- (s) => {
102
- const i = JSON.parse(s);
103
- e({ fileList: k(i.files || []) });
104
- },
105
- (s) => {
106
- r(s);
107
- }
108
- );
109
- }),
110
- getUrl: (n, t, e) => `https://unpkg.com/${n}@${t}${e}`
111
- },
112
- bootcdn: {
113
- getFileList: (n, t) => new Promise((e, r) => {
114
- f.get(
115
- `https://api.bootcdn.cn/libraries/${n}`,
116
- (s) => {
117
- const i = JSON.parse(s);
118
- if (i.length === 0) {
119
- r(new Error(`${n} not found in bootcdn`));
120
- return;
121
- }
122
- const o = i[0], a = o.assets.find((d) => d.version === t);
123
- if (!a) {
124
- r(new Error(`${n}@${t} not found in ${o.name}`));
125
- return;
126
- }
127
- const l = a.files.map((d) => ({
128
- name: "/" + d
129
- }));
130
- e({ fileList: l, recommendFileName: o.filename });
131
- },
132
- (s) => {
133
- r(s);
134
- }
135
- );
136
- }),
137
- getUrl: (n, t, e) => `https://cdn.bootcdn.net/ajax/libs/${n}/${t}${e}`
138
- },
139
- cdnjs: {
140
- getFileList: (n, t) => new Promise((e, r) => {
141
- f.get(
142
- `https://api.cdnjs.com/libraries/${n}/${t}`,
143
- (s) => {
144
- const i = JSON.parse(s);
145
- if (i.error) {
146
- r(new Error(`cdnjs: ${n}@${t} not found`));
147
- return;
148
- }
149
- e({
150
- fileList: i.rawFiles.map((o) => ({
151
- name: "/" + o
152
- }))
153
- });
154
- },
155
- (s) => {
156
- r(s);
157
- }
158
- );
159
- }),
160
- getUrl: (n, t, e) => `https://cdnjs.cloudflare.com/ajax/libs/${n}/${t}${e}`
161
- }
162
- }, R = async (n, t, e) => {
163
- var o;
164
- const r = (o = t.match(/\d+(.\d+)?(.\d+)?/)) == null ? void 0 : o[0];
198
+ }, H = async (n, t, e) => {
199
+ var i;
200
+ const r = (i = t.match(/\d+(.\d+)?(.\d+)?/)) == null ? void 0 : i[0];
165
201
  if (!r)
166
202
  throw new Error(`${n} version ${t} is not valid`);
167
- const s = await x[e].getFileList(n, r).catch((c) => {
168
- throw c;
169
- }), i = A(s, n);
170
- if (!i)
203
+ const s = await v[e].getFileList(n, r).catch((o) => {
204
+ throw console.log(o), new Error(`${n} ${t} ${e} API 请求失败`);
205
+ }), c = B(s, n);
206
+ if (!c)
171
207
  throw new Error(`在 ${e} 中找不到 ${n}@${r} 文件,请检查包名或版本号`);
172
- return x[e].getUrl(n, r, i);
173
- }, A = ({ fileList: n }, t) => {
174
- var i, o;
208
+ return v[e].getUrl(n, r, c);
209
+ }, B = ({ fileList: n }, t) => {
210
+ var c, i;
175
211
  let e = [
176
212
  `umd/${t}.production.min.js`,
177
213
  /umd\/.+?\.production\.min\.js$/,
@@ -189,130 +225,146 @@ const L = async () => ($ || ($ = new E(), await $.init()), $), f = {
189
225
  /\.min\.js$/,
190
226
  /\.js$/
191
227
  ];
192
- const r = ["runtime", "compiler", ".esm", ".cjs", "development"].filter((c) => !t.includes(c));
228
+ const r = ["runtime", "compiler", ".esm", ".cjs", "development"].filter((o) => !t.includes(o));
193
229
  let s = "";
194
- for (let c of e)
195
- if (c instanceof RegExp ? s = ((i = n.find((a) => c.test(a.name) && !r.some((l) => a.name.includes(l)))) == null ? void 0 : i.name) || "" : s = ((o = n.find((a) => a.name.includes(c) && !r.some((l) => a.name.includes(l)))) == null ? void 0 : o.name) || "", s)
230
+ for (let o of e)
231
+ if (o instanceof RegExp ? s = ((c = n.find((a) => o.test(a.name) && !r.some((l) => a.name.includes(l)))) == null ? void 0 : c.name) || "" : s = ((i = n.find((a) => a.name.includes(o) && !r.some((l) => a.name.includes(l)))) == null ? void 0 : i.name) || "", s)
196
232
  break;
197
233
  return s;
234
+ }, v = {
235
+ jsdelivr: V,
236
+ bootcdn: A,
237
+ cdnjs: M,
238
+ unpkg: T
198
239
  };
199
- function M(n, t) {
240
+ function G(n, t) {
200
241
  const e = n.replace(/^\D/, "").split("."), r = t.replace(/^\D/, "").split("."), s = Math.max(e.length, r.length);
201
242
  for (; e.length < s; )
202
243
  e.push("0");
203
244
  for (; r.length < s; )
204
245
  r.push("0");
205
- for (let i = 0; i < s; i++) {
206
- const o = parseInt(e[i], 10), c = parseInt(r[i], 10);
207
- if (o > c)
246
+ for (let c = 0; c < s; c++) {
247
+ const i = parseInt(e[c], 10), o = parseInt(r[c], 10);
248
+ if (i > o)
208
249
  return 1;
209
- if (o < c)
250
+ if (i < o)
210
251
  return -1;
211
252
  }
212
253
  return 0;
213
254
  }
214
- function V(n, t) {
255
+ function z(n, t) {
215
256
  for (let e in t)
216
- Object.prototype.hasOwnProperty.call(t, e) && (n[e] ? M(n[e], t[e]) === -1 && (n[e] = t[e]) : n[e] = t[e]);
257
+ Object.prototype.hasOwnProperty.call(t, e) && (n[e] ? G(n[e], t[e]) === -1 && (n[e] = t[e]) : n[e] = t[e]);
217
258
  return n;
218
259
  }
219
- async function S({ external: n, packageData: t, customScript: e, defaultCdns: r }) {
220
- let s = [], i = !1;
221
- const o = await L();
260
+ async function O({ external: n, packageData: t, customScript: e, defaultCdns: r }) {
261
+ let s = [], c = !1;
262
+ const i = await I();
222
263
  return await Promise.all(
223
- n.map(async (c) => {
224
- const a = I(t, c);
225
- if (e[c])
264
+ n.map(async (o) => {
265
+ const a = q(t, o);
266
+ if (e[o])
226
267
  return {
227
268
  urls: [],
228
- key: c
269
+ key: o
270
+ };
271
+ const l = i.getCdnCache(o, a);
272
+ if (!a && !l)
273
+ return s.push(o), {
274
+ urls: [],
275
+ key: o
229
276
  };
230
- if (!a) {
231
- s.push(c);
232
- return;
233
- }
234
- const l = o.getCdnCache(c, a);
235
277
  if (l)
236
278
  return {
237
279
  urls: l,
238
- key: c
280
+ key: o
239
281
  };
240
282
  {
241
- i = !0;
283
+ c = !0, console.log(`从网络获取${o}${a}的cdn地址`);
242
284
  const d = {
243
285
  urls: await Promise.all(
244
- r.map(async (h) => await R(c, a, h))
286
+ r.map(async (C) => await H(o, a, C))
245
287
  ),
246
- key: c
288
+ key: o
247
289
  };
248
- return o.setCdnCache(c, a, d.urls), d;
290
+ return i.setCdnCache(o, a, d.urls), d;
249
291
  }
250
292
  })
251
- ).then((c) => (i && o.save(), {
252
- urls: c,
293
+ ).then((o) => (c && i.save(), {
294
+ urls: o,
253
295
  noVersionPackages: s
254
296
  }));
255
297
  }
256
- function q(n) {
257
- const { customScript: t = {}, retryTimes: e = 1, defaultCdns: r = ["jsdelivr", "unpkg"] } = n;
258
- let s;
298
+ function tt(n) {
299
+ const { customScript: t = {}, retryTimes: e, defaultCdns: r = ["jsdelivr", "unpkg", "cdnjs"] } = n;
300
+ let s = e;
301
+ s || (s = r.length - 1);
302
+ let c;
259
303
  return {
260
304
  name: "vite-add-cdn-script",
261
305
  enforce: "pre",
262
306
  apply: "build",
263
307
  config(i) {
264
- s = i;
308
+ c = i;
265
309
  },
266
310
  async transformIndexHtml(i) {
267
311
  if (!r || r.length === 0)
268
312
  throw new Error("defaultCdns不能为空");
269
- const o = U.resolve(process.cwd(), "package.json");
313
+ const o = J.resolve(process.cwd(), "package.json");
270
314
  try {
271
- const c = w.readFileSync(o, "utf-8"), a = JSON.parse(c), l = s.build.rollupOptions.external, d = {};
272
- let h = "";
273
- const { urls: C, noVersionPackages: P } = await S({
274
- external: l,
275
- packageData: a,
315
+ const a = j.readFileSync(o, "utf-8"), l = JSON.parse(a), d = c.build.rollupOptions.external, C = {};
316
+ let p = "";
317
+ const { urls: k, noVersionPackages: S } = await O({
318
+ external: d,
319
+ packageData: l,
276
320
  customScript: t,
277
321
  defaultCdns: r
278
322
  });
279
- if (P.length > 0) {
280
- const p = { dependencies: {} };
323
+ if (S.length > 0) {
324
+ const m = { dependencies: {} };
281
325
  await Promise.all(
282
- C.map(async (g) => {
283
- if (!g)
326
+ k.map(async (u) => {
327
+ if (!u)
284
328
  return;
285
- const { key: v, urls: O } = g, j = t[v] || O[0];
286
- if (!j)
329
+ const { key: x, urls: _ } = u, g = t[x] || _[0];
330
+ if (!g)
287
331
  return;
288
- const J = await N(j);
289
- V(p.dependencies, J.dependencies);
332
+ const $ = await Q(g);
333
+ z(m.dependencies, $.dependencies);
290
334
  })
291
- );
292
- const { urls: m, noVersionPackages: u } = await S({
293
- external: P,
294
- packageData: p,
335
+ ).catch((u) => {
336
+ console.log("err", u);
337
+ });
338
+ const { urls: P, noVersionPackages: h } = await O({
339
+ external: S,
340
+ packageData: m,
295
341
  customScript: t,
296
342
  defaultCdns: r
297
343
  });
298
- if (C.push(...m), u.length > 0)
299
- throw console.error(`找不到${u.join(",")}的版本`), new Error(`找不到${u.join(",")}的版本`);
344
+ if (P.map((u) => {
345
+ var g;
346
+ if (!u)
347
+ return;
348
+ const { urls: x, key: _ } = u;
349
+ (g = k.find(($) => ($ == null ? void 0 : $.key) === _)) == null || g.urls.push(...x);
350
+ }), h.length > 0)
351
+ throw console.error(`找不到${h.join(",")}的版本`), new Error(`找不到${h.join(",")}的版本`);
300
352
  }
301
- return C.forEach((p) => {
302
- if (!p)
353
+ return k.forEach((m) => {
354
+ if (!m)
303
355
  return;
304
- const { urls: m, key: u } = p;
305
- if (t[u])
306
- h += t[u];
356
+ const { urls: P, key: h } = m;
357
+ if (t[h])
358
+ p += t[h];
307
359
  else {
308
- d[u] = m;
309
- const g = m[0];
310
- h += `<script src="${g}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${u}"><\/script>
360
+ C[h] = P;
361
+ const u = P[0];
362
+ p += `<script src="${u}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${h}"><\/script>
311
363
  `;
312
364
  }
313
- }), h = `<script>
365
+ }), p = `<script>
314
366
  function errorCDN(e) {
315
- const packNameUrl = JSON.parse('${JSON.stringify(d)}');
367
+ const packNameUrl = JSON.parse('${JSON.stringify(C)}');
316
368
  const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
317
369
  if(nextCur>${e}){return;}
318
370
 
@@ -332,13 +384,13 @@ function q(n) {
332
384
  document.head.appendChild(cdnDOM);
333
385
  e.remove();
334
386
  }
335
- <\/script>` + h, i = i.replace("</head>", `${h}</head>`), i;
336
- } catch (c) {
337
- console.error("获取dependencies出错:", c);
387
+ <\/script>` + p, i = i.replace("</head>", `${p}</head>`), i;
388
+ } catch (a) {
389
+ console.error("获取dependencies出错:", a);
338
390
  }
339
391
  }
340
392
  };
341
393
  }
342
394
  export {
343
- q as default
395
+ tt as default
344
396
  };
@@ -1,7 +1,7 @@
1
- (function(d,a){typeof exports=="object"&&typeof module<"u"?module.exports=a(require("node:path"),require("node:fs"),require("node:https")):typeof define=="function"&&define.amd?define(["node:path","node:fs","node:https"],a):(d=typeof globalThis<"u"?globalThis:d||self,d.index=a(d.path,d.fs,d.https))})(this,function(d,a,f){"use strict";var V=Object.defineProperty;var T=(d,a,f)=>a in d?V(d,a,{enumerable:!0,configurable:!0,writable:!0,value:f}):d[a]=f;var P=(d,a,f)=>(T(d,typeof a!="symbol"?a+"":a,f),f);class O{constructor(){P(this,"cdnCache",{});P(this,"cdnCachePath","");this.cdnCachePath=d.resolve(process.cwd(),"./.cdn-cache.json")}async init(){try{const e=await a.readFileSync(this.cdnCachePath,"utf-8");this.cdnCache=JSON.parse(e)}catch{console.log("cdn缓存文件不存在,创建缓存文件"),this.cdnCache={},await a.writeFileSync(this.cdnCachePath,"","utf-8")}}getCdnCache(e,t){var r;return(r=this.cdnCache[e])==null?void 0:r[t]}setCdnCache(e,t,r){this.cdnCache[e]?this.cdnCache[e][t]=r:this.cdnCache[e]={[t]:r}}async save(){await a.writeFileSync(this.cdnCachePath,JSON.stringify(this.cdnCache),"utf-8")}}let w;const J=async()=>(w||(w=new O,await w.init()),w),g={get:(n,e,t)=>new Promise((r,s)=>{try{f.get(n,i=>{let o="";i.on("data",c=>{o+=c}),i.on("end",()=>{e==null||e(o),r(o)})})}catch(i){t==null||t(i),s(i)}})},D=async n=>{const e=/^(https:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;if(e.test(n)){const t=n.replace(e,(r,s)=>`${s}package.json`);return JSON.parse(await g.get(t))}else throw new Error(`${n} 不是正确的url`)},F=(n,e)=>{var t,r;return((t=n.dependencies)==null?void 0:t[e])||((r=n.devDependencies)==null?void 0:r[e])},x=n=>n.reduce((e,t)=>(t.type==="file"?e.push({name:t.path}):t.files&&e.push(...x(t.files)),e),[]),S={jsdelivr:{getFileList:(n,e)=>new Promise((t,r)=>{g.get(`https://data.jsdelivr.com/v1/stats/packages/npm/${n}@${e}/files`,s=>{const i=JSON.parse(s);if(i.length===0){r(new Error(`${n}@${e} not found`));return}t({fileList:i})},s=>{r(s)})}),getUrl:(n,e,t)=>`https://cdn.jsdelivr.net/npm/${n}@${e}${t}`},unpkg:{getFileList:(n,e)=>new Promise((t,r)=>{g.get(`https://unpkg.com/${n}@${e}/?meta`,s=>{const i=JSON.parse(s);t({fileList:x(i.files||[])})},s=>{r(s)})}),getUrl:(n,e,t)=>`https://unpkg.com/${n}@${e}${t}`},bootcdn:{getFileList:(n,e)=>new Promise((t,r)=>{g.get(`https://api.bootcdn.cn/libraries/${n}`,s=>{const i=JSON.parse(s);if(i.length===0){r(new Error(`${n} not found in bootcdn`));return}const o=i[0],u=o.assets.find(h=>h.version===e);if(!u){r(new Error(`${n}@${e} not found in ${o.name}`));return}const l=u.files.map(h=>({name:"/"+h}));t({fileList:l,recommendFileName:o.filename})},s=>{r(s)})}),getUrl:(n,e,t)=>`https://cdn.bootcdn.net/ajax/libs/${n}/${e}${t}`},cdnjs:{getFileList:(n,e)=>new Promise((t,r)=>{g.get(`https://api.cdnjs.com/libraries/${n}/${e}`,s=>{const i=JSON.parse(s);if(i.error){r(new Error(`cdnjs: ${n}@${e} not found`));return}t({fileList:i.rawFiles.map(o=>({name:"/"+o}))})},s=>{r(s)})}),getUrl:(n,e,t)=>`https://cdnjs.cloudflare.com/ajax/libs/${n}/${e}${t}`}},E=async(n,e,t)=>{var o;const r=(o=e.match(/\d+(.\d+)?(.\d+)?/))==null?void 0:o[0];if(!r)throw new Error(`${n} version ${e} is not valid`);const s=await S[t].getFileList(n,r).catch(c=>{throw c}),i=L(s,n);if(!i)throw new Error(`在 ${t} 中找不到 ${n}@${r} 文件,请检查包名或版本号`);return S[t].getUrl(n,r,i)},L=({fileList:n},e)=>{var i,o;let t=[`umd/${e}.production.min.js`,/umd\/.+?\.production\.min\.js$/,/dist\/.+?\.production\.min\.js$/,/dist\/.+?\.umd\.min\.js$/,`dist/${e}.prod.min.js`,/dist\/.+?\.global.prod.min.js/,`dist/${e}.min.js`,/.+?\.global.prod.min.js/,/.+?.global.prod.js/,/lib\/.+?\.min\.js$/,/dist\/.+?\.min\.js$/,/index\.min\.js$/,/index\.js$/,/\.min\.js$/,/\.js$/];const r=["runtime","compiler",".esm",".cjs","development"].filter(c=>!e.includes(c));let s="";for(let c of t)if(c instanceof RegExp?s=((i=n.find(u=>c.test(u.name)&&!r.some(l=>u.name.includes(l))))==null?void 0:i.name)||"":s=((o=n.find(u=>u.name.includes(c)&&!r.some(l=>u.name.includes(l))))==null?void 0:o.name)||"",s)break;return s};function b(n,e){const t=n.replace(/^\D/,"").split("."),r=e.replace(/^\D/,"").split("."),s=Math.max(t.length,r.length);for(;t.length<s;)t.push("0");for(;r.length<s;)r.push("0");for(let i=0;i<s;i++){const o=parseInt(t[i],10),c=parseInt(r[i],10);if(o>c)return 1;if(o<c)return-1}return 0}function N(n,e){for(let t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]?b(n[t],e[t])===-1&&(n[t]=e[t]):n[t]=e[t]);return n}async function U({external:n,packageData:e,customScript:t,defaultCdns:r}){let s=[],i=!1;const o=await J();return await Promise.all(n.map(async c=>{const u=F(e,c);if(t[c])return{urls:[],key:c};if(!u){s.push(c);return}const l=o.getCdnCache(c,u);if(l)return{urls:l,key:c};{i=!0;const h={urls:await Promise.all(r.map(async m=>await E(c,u,m))),key:c};return o.setCdnCache(c,u,h.urls),h}})).then(c=>(i&&o.save(),{urls:c,noVersionPackages:s}))}function I(n){const{customScript:e={},retryTimes:t=1,defaultCdns:r=["jsdelivr","unpkg"]}=n;let s;return{name:"vite-add-cdn-script",enforce:"pre",apply:"build",config(i){s=i},async transformIndexHtml(i){if(!r||r.length===0)throw new Error("defaultCdns不能为空");const o=d.resolve(process.cwd(),"package.json");try{const c=a.readFileSync(o,"utf-8"),u=JSON.parse(c),l=s.build.rollupOptions.external,h={};let m="";const{urls:j,noVersionPackages:k}=await U({external:l,packageData:u,customScript:e,defaultCdns:r});if(k.length>0){const $={dependencies:{}};await Promise.all(j.map(async y=>{if(!y)return;const{key:R,urls:A}=y,v=e[R]||A[0];if(!v)return;const M=await D(v);N($.dependencies,M.dependencies)}));const{urls:C,noVersionPackages:p}=await U({external:k,packageData:$,customScript:e,defaultCdns:r});if(j.push(...C),p.length>0)throw console.error(`找不到${p.join(",")}的版本`),new Error(`找不到${p.join(",")}的版本`)}return j.forEach($=>{if(!$)return;const{urls:C,key:p}=$;if(e[p])m+=e[p];else{h[p]=C;const y=C[0];m+=`<script src="${y}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${p}"><\/script>
2
- `}}),m=`<script>
1
+ (function(d,u){typeof exports=="object"&&typeof module<"u"?module.exports=u(require("node:path"),require("node:fs"),require("node:https")):typeof define=="function"&&define.amd?define(["node:path","node:fs","node:https"],u):(d=typeof globalThis<"u"?globalThis:d||self,d.index=u(d.path,d.fs,d.https))})(this,function(d,u,m){"use strict";var z=Object.defineProperty;var K=(d,u,m)=>u in d?z(d,u,{enumerable:!0,configurable:!0,writable:!0,value:m}):d[u]=m;var $=(d,u,m)=>(K(d,typeof u!="symbol"?u+"":u,m),m);class E{constructor(){$(this,"cdnCache",{});$(this,"cdnCachePath","");this.cdnCachePath=d.resolve(process.cwd(),"./.cdn-cache.json")}async init(){try{const e=await u.readFileSync(this.cdnCachePath,"utf-8");this.cdnCache=JSON.parse(e)}catch{console.log("cdn缓存文件不存在,创建缓存文件"),this.cdnCache={},await u.writeFileSync(this.cdnCachePath,"","utf-8")}}getCdnCache(e,t){var r;return(r=this.cdnCache[e])==null?void 0:r[t]}setCdnCache(e,t,r){this.cdnCache[e]?this.cdnCache[e][t]=r:this.cdnCache[e]={[t]:r}}async save(){await u.writeFileSync(this.cdnCachePath,JSON.stringify(this.cdnCache),"utf-8")}}let j;const L=async()=>(j||(j=new E,await j.init()),j);class b{constructor(e){$(this,"_max");$(this,"_count");$(this,"_taskQueue");this._max=e||5,this._count=0,this._taskQueue=[]}call(e,...t){return new Promise((r,s)=>{const c=this._createTask(e,t,r,s);this._count>=this._max?this._taskQueue.push(c):c()})}_createTask(e,t,r,s){return()=>{e(...t).then(r).catch(s).finally(()=>{this._count--,this._taskQueue.length&&this._taskQueue.shift()()}),this._count++}}}const v=new b(5),I={get:(n,e,t)=>new Promise((r,s)=>{try{m.get(n,c=>{let i="";c.on("data",o=>{i+=o}),c.on("end",()=>{e==null||e(i),r(i)})}).on("error",function(c){t==null||t(c),s(c)})}catch(c){t==null||t(c),s(c)}})},w={get:v.call.bind(v,I.get)},N={getFileList:(n,e)=>new Promise((t,r)=>{w.get(`https://api.bootcdn.cn/libraries/${n}`,s=>{const c=JSON.parse(s);if(c.length===0){r(new Error(`${n} not found in bootcdn`));return}const i=c[0],a=i.assets.find(p=>p.version===e);if(!a){r(new Error(`${n}@${e} not found in ${i.name}`));return}const l=a.files.map(p=>({name:"/"+p}));t({fileList:l,recommendFileName:i.filename})},s=>{r(s)})}),getUrl:(n,e,t)=>`https://cdn.bootcdn.net/ajax/libs/${n}/${e}${t}`},R={getFileList:(n,e)=>new Promise((t,r)=>{w.get(`https://api.cdnjs.com/libraries/${n}/${e}`,s=>{const c=JSON.parse(s);if(c.error){r(new Error(`cdnjs: ${n}@${e} not found`));return}t({fileList:c.rawFiles.map(i=>({name:"/"+i}))})},s=>{r(s)})}),getUrl:(n,e,t)=>`https://cdnjs.cloudflare.com/ajax/libs/${n}/${e}${t}`},A={getFileList:(n,e)=>new Promise((t,r)=>{w.get(`https://data.jsdelivr.com/v1/stats/packages/npm/${n}@${e}/files`,s=>{const c=JSON.parse(s);if(c.length===0){r(new Error(`${n}@${e} not found`));return}t({fileList:c})},s=>{r(s)})}),getUrl:(n,e,t)=>`https://cdn.jsdelivr.net/npm/${n}@${e}${t}`},O=n=>n.reduce((e,t)=>(t.type==="file"?e.push({name:t.path}):t.files&&e.push(...O(t.files)),e),[]),T={getFileList:(n,e)=>new Promise((t,r)=>{w.get(`https://unpkg.com/${n}@${e}/?meta`,s=>{const c=JSON.parse(s);t({fileList:O(c.files||[])})},s=>{r(s)})}),getUrl:(n,e,t)=>`https://unpkg.com/${n}@${e}${t}`},M=async n=>{const e=/^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;if(e.test(n)){const t=n.replace(e,(r,s)=>`${s}package.json`);return JSON.parse(await w.get(t))}else throw new Error(`${n} 不是正确的url`)},V=(n,e)=>{var t,r;return((t=n.dependencies)==null?void 0:t[e])||((r=n.devDependencies)==null?void 0:r[e])},q=async(n,e,t)=>{var i;const r=(i=e.match(/\d+(.\d+)?(.\d+)?/))==null?void 0:i[0];if(!r)throw new Error(`${n} version ${e} is not valid`);const s=await J[t].getFileList(n,r).catch(o=>{throw console.log(o),new Error(`${n} ${e} ${t} API 请求失败`)}),c=Q(s,n);if(!c)throw new Error(`在 ${t} 中找不到 ${n}@${r} 文件,请检查包名或版本号`);return J[t].getUrl(n,r,c)},Q=({fileList:n},e)=>{var c,i;let t=[`umd/${e}.production.min.js`,/umd\/.+?\.production\.min\.js$/,/dist\/.+?\.production\.min\.js$/,/dist\/.+?\.umd\.min\.js$/,`dist/${e}.prod.min.js`,/dist\/.+?\.global.prod.min.js/,`dist/${e}.min.js`,/.+?\.global.prod.min.js/,/.+?.global.prod.js/,/lib\/.+?\.min\.js$/,/dist\/.+?\.min\.js$/,/index\.min\.js$/,/index\.js$/,/\.min\.js$/,/\.js$/];const r=["runtime","compiler",".esm",".cjs","development"].filter(o=>!e.includes(o));let s="";for(let o of t)if(o instanceof RegExp?s=((c=n.find(a=>o.test(a.name)&&!r.some(l=>a.name.includes(l))))==null?void 0:c.name)||"":s=((i=n.find(a=>a.name.includes(o)&&!r.some(l=>a.name.includes(l))))==null?void 0:i.name)||"",s)break;return s},J={jsdelivr:A,bootcdn:N,cdnjs:R,unpkg:T};function H(n,e){const t=n.replace(/^\D/,"").split("."),r=e.replace(/^\D/,"").split("."),s=Math.max(t.length,r.length);for(;t.length<s;)t.push("0");for(;r.length<s;)r.push("0");for(let c=0;c<s;c++){const i=parseInt(t[c],10),o=parseInt(r[c],10);if(i>o)return 1;if(i<o)return-1}return 0}function B(n,e){for(let t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]?H(n[t],e[t])===-1&&(n[t]=e[t]):n[t]=e[t]);return n}async function D({external:n,packageData:e,customScript:t,defaultCdns:r}){let s=[],c=!1;const i=await L();return await Promise.all(n.map(async o=>{const a=V(e,o);if(t[o])return{urls:[],key:o};const l=i.getCdnCache(o,a);if(!a&&!l)return s.push(o),{urls:[],key:o};if(l)return{urls:l,key:o};{c=!0,console.log(`从网络获取${o}${a}的cdn地址`);const p={urls:await Promise.all(r.map(async k=>await q(o,a,k))),key:o};return i.setCdnCache(o,a,p.urls),p}})).then(o=>(c&&i.save(),{urls:o,noVersionPackages:s}))}function G(n){const{customScript:e={},retryTimes:t,defaultCdns:r=["jsdelivr","unpkg","cdnjs"]}=n;let s=t;s||(s=r.length-1);let c;return{name:"vite-add-cdn-script",enforce:"pre",apply:"build",config(i){c=i},async transformIndexHtml(i){if(!r||r.length===0)throw new Error("defaultCdns不能为空");const o=d.resolve(process.cwd(),"package.json");try{const a=u.readFileSync(o,"utf-8"),l=JSON.parse(a),p=c.build.rollupOptions.external,k={};let g="";const{urls:_,noVersionPackages:F}=await D({external:p,packageData:l,customScript:e,defaultCdns:r});if(F.length>0){const C={dependencies:{}};await Promise.all(_.map(async h=>{if(!h)return;const{key:S,urls:U}=h,P=e[S]||U[0];if(!P)return;const y=await M(P);B(C.dependencies,y.dependencies)})).catch(h=>{console.log("err",h)});const{urls:x,noVersionPackages:f}=await D({external:F,packageData:C,customScript:e,defaultCdns:r});if(x.map(h=>{var P;if(!h)return;const{urls:S,key:U}=h;(P=_.find(y=>(y==null?void 0:y.key)===U))==null||P.urls.push(...S)}),f.length>0)throw console.error(`找不到${f.join(",")}的版本`),new Error(`找不到${f.join(",")}的版本`)}return _.forEach(C=>{if(!C)return;const{urls:x,key:f}=C;if(e[f])g+=e[f];else{k[f]=x;const h=x[0];g+=`<script src="${h}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${f}"><\/script>
2
+ `}}),g=`<script>
3
3
  function errorCDN(e) {
4
- const packNameUrl = JSON.parse('${JSON.stringify(h)}');
4
+ const packNameUrl = JSON.parse('${JSON.stringify(k)}');
5
5
  const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
6
6
  if(nextCur>${t}){return;}
7
7
 
@@ -21,4 +21,4 @@
21
21
  document.head.appendChild(cdnDOM);
22
22
  e.remove();
23
23
  }
24
- <\/script>`+m,i=i.replace("</head>",`${m}</head>`),i}catch(c){console.error("获取dependencies出错:",c)}}}}return I});
24
+ <\/script>`+g,i=i.replace("</head>",`${g}</head>`),i}catch(a){console.error("获取dependencies出错:",a)}}}}return G});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-add-cdn-script",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "keywords": [
5
5
  "vite",
6
6
  "cdn",
@@ -42,8 +42,8 @@
42
42
  "@vitejs/plugin-react": "^4.2.1",
43
43
  "cross-env": "^7.0.3",
44
44
  "jest": "^29.7.0",
45
- "react": "^18.3.1",
46
- "react-dom": "^18.3.1",
45
+ "react": "^18.2.0",
46
+ "react-dom": "^18.2.0",
47
47
  "react-router-dom": "^6.23.1",
48
48
  "rollup-plugin-external-globals": "^0.10.0",
49
49
  "rollup-plugin-node-externals": "^7.1.2",