vite-add-cdn-script 0.0.7 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +5 -5
- package/dist/index.js +240 -188
- package/dist/index.umd.cjs +4 -4
- package/package.json +3 -3
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 |
|
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
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import
|
7
|
-
class
|
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
|
-
|
10
|
-
|
11
|
-
this.cdnCachePath =
|
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
|
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
|
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
|
46
|
+
await j.writeFileSync(this.cdnCachePath, JSON.stringify(this.cdnCache), "utf-8");
|
47
47
|
}
|
48
48
|
}
|
49
|
-
let
|
50
|
-
const
|
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
|
-
|
55
|
-
let
|
56
|
-
|
57
|
-
|
58
|
-
}),
|
59
|
-
t == null || t(
|
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 (
|
63
|
-
e == null || e(
|
101
|
+
} catch (c) {
|
102
|
+
e == null || e(c), s(c);
|
64
103
|
}
|
65
104
|
})
|
66
|
-
},
|
67
|
-
|
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
|
192
|
+
return JSON.parse(await w.get(e));
|
71
193
|
} else
|
72
194
|
throw new Error(`${n} 不是正确的url`);
|
73
|
-
},
|
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
|
-
},
|
77
|
-
|
78
|
-
|
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
|
168
|
-
throw
|
169
|
-
}),
|
170
|
-
if (!
|
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
|
173
|
-
},
|
174
|
-
var
|
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((
|
228
|
+
const r = ["runtime", "compiler", ".esm", ".cjs", "development"].filter((o) => !t.includes(o));
|
193
229
|
let s = "";
|
194
|
-
for (let
|
195
|
-
if (
|
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
|
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
|
206
|
-
const
|
207
|
-
if (
|
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 (
|
250
|
+
if (i < o)
|
210
251
|
return -1;
|
211
252
|
}
|
212
253
|
return 0;
|
213
254
|
}
|
214
|
-
function
|
255
|
+
function z(n, t) {
|
215
256
|
for (let e in t)
|
216
|
-
Object.prototype.hasOwnProperty.call(t, e) && (n[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
|
220
|
-
let s = [],
|
221
|
-
const
|
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 (
|
224
|
-
const a =
|
225
|
-
if (e[
|
264
|
+
n.map(async (o) => {
|
265
|
+
const a = q(t, o);
|
266
|
+
if (e[o])
|
226
267
|
return {
|
227
268
|
urls: [],
|
228
|
-
key:
|
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:
|
280
|
+
key: o
|
239
281
|
};
|
240
282
|
{
|
241
|
-
|
283
|
+
c = !0, console.log(`从网络获取${o}${a}的cdn地址`);
|
242
284
|
const d = {
|
243
285
|
urls: await Promise.all(
|
244
|
-
r.map(async (
|
286
|
+
r.map(async (C) => await H(o, a, C))
|
245
287
|
),
|
246
|
-
key:
|
288
|
+
key: o
|
247
289
|
};
|
248
|
-
return
|
290
|
+
return i.setCdnCache(o, a, d.urls), d;
|
249
291
|
}
|
250
292
|
})
|
251
|
-
).then((
|
252
|
-
urls:
|
293
|
+
).then((o) => (c && i.save(), {
|
294
|
+
urls: o,
|
253
295
|
noVersionPackages: s
|
254
296
|
}));
|
255
297
|
}
|
256
|
-
function
|
257
|
-
const { customScript: t = {}, retryTimes: e
|
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
|
-
|
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 =
|
313
|
+
const o = J.resolve(process.cwd(), "package.json");
|
270
314
|
try {
|
271
|
-
const
|
272
|
-
let
|
273
|
-
const { urls:
|
274
|
-
external:
|
275
|
-
packageData:
|
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 (
|
280
|
-
const
|
323
|
+
if (S.length > 0) {
|
324
|
+
const m = { dependencies: {} };
|
281
325
|
await Promise.all(
|
282
|
-
|
283
|
-
if (!
|
326
|
+
k.map(async (u) => {
|
327
|
+
if (!u)
|
284
328
|
return;
|
285
|
-
const { key:
|
286
|
-
if (!
|
329
|
+
const { key: x, urls: _ } = u, g = t[x] || _[0];
|
330
|
+
if (!g)
|
287
331
|
return;
|
288
|
-
const
|
289
|
-
|
332
|
+
const $ = await Q(g);
|
333
|
+
z(m.dependencies, $.dependencies);
|
290
334
|
})
|
291
|
-
)
|
292
|
-
|
293
|
-
|
294
|
-
|
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 (
|
299
|
-
|
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
|
302
|
-
if (!
|
353
|
+
return k.forEach((m) => {
|
354
|
+
if (!m)
|
303
355
|
return;
|
304
|
-
const { urls:
|
305
|
-
if (t[
|
306
|
-
|
356
|
+
const { urls: P, key: h } = m;
|
357
|
+
if (t[h])
|
358
|
+
p += t[h];
|
307
359
|
else {
|
308
|
-
|
309
|
-
const
|
310
|
-
|
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
|
-
}),
|
365
|
+
}), p = `<script>
|
314
366
|
function errorCDN(e) {
|
315
|
-
const packNameUrl = JSON.parse('${JSON.stringify(
|
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>` +
|
336
|
-
} catch (
|
337
|
-
console.error("获取dependencies出错:",
|
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
|
-
|
395
|
+
tt as default
|
344
396
|
};
|
package/dist/index.umd.cjs
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
(function(d,
|
2
|
-
`}}),
|
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(
|
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>`+
|
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.
|
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.
|
46
|
-
"react-dom": "^18.
|
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",
|