earthsdk3-assets 3.0.15 → 3.0.17
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 +3 -1
- package/package.json +2 -1
- package/src/core/copyAssets.cjs +41 -0
- package/src/core/downloadAssets.cjs +291 -0
- package/src/index.cjs +2 -1
- package/src/index.d.ts +47 -0
- package/src/index.js +2 -2
- package/src/plugins/rspack.js +3 -19
- package/src/plugins/webpack.js +3 -23
package/README.md
CHANGED
|
@@ -134,11 +134,13 @@ earthsdk3-assets/
|
|
|
134
134
|
|
|
135
135
|
1. **Vite** - 检查 `vite` 依赖或 `vite.config.*` 文件
|
|
136
136
|
2. **Rspack** - 检查 `@rspack/core` 依赖或 `rspack.config.*` 文件
|
|
137
|
-
3. **
|
|
137
|
+
3. **Vue CLI** - 检查 `@vue/cli-service` 依赖(基于 Webpack 5)
|
|
138
|
+
4. **Webpack** - 检查 `webpack` 依赖或 `webpack.config.*` 文件
|
|
138
139
|
|
|
139
140
|
## 注意事项
|
|
140
141
|
|
|
141
142
|
- Webpack/Rspack 项目需要安装 `html-webpack-plugin` 或 `@rspack/plugin-html` 以支持 HTML 脚本注入
|
|
143
|
+
- Vue CLI 项目内置 `html-webpack-plugin`,无需额外安装
|
|
142
144
|
- 所有构建工具插件均为可选依赖,未使用的构建工具不会引起报错
|
|
143
145
|
|
|
144
146
|
## 许可证
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "earthsdk3-assets",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.17",
|
|
4
4
|
"description": "地球可视化实验室 (EarthSDK&CesiumLab) https://www.bjxbsj.cn",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./src/index.js",
|
|
8
|
+
"types": "./src/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
10
11
|
"import": "./src/index.js",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const IGNORE_FILES = new Set(['.assets-version', '.assets-manifest.json']);
|
|
5
|
+
|
|
6
|
+
function copyAssetsToDest(assetsDir, rootDir, outDir) {
|
|
7
|
+
const dest = path.join(outDir, 'js');
|
|
8
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
9
|
+
|
|
10
|
+
if (fs.existsSync(assetsDir)) {
|
|
11
|
+
fs.cpSync(assetsDir, path.join(dest, 'assets'), {
|
|
12
|
+
recursive: true,
|
|
13
|
+
filter(src) {
|
|
14
|
+
const baseName = path.basename(src);
|
|
15
|
+
if (IGNORE_FILES.has(baseName)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (baseName.endsWith('.download') || baseName.endsWith('.tmp')) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const sdkSrc = path.join(rootDir, 'earthsdk3-assets.js');
|
|
27
|
+
if (fs.existsSync(sdkSrc)) {
|
|
28
|
+
fs.cpSync(sdkSrc, path.join(dest, 'earthsdk3-assets.js'));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log('[earthsdk-assets] 资源已拷贝到:', dest);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getAssetsPaths(rootDir) {
|
|
35
|
+
const assetsDir = path.resolve(rootDir, 'assets');
|
|
36
|
+
const cacheFile = path.resolve(assetsDir, '.assets-version');
|
|
37
|
+
const manifestCacheFile = path.resolve(assetsDir, '.assets-manifest.json');
|
|
38
|
+
return { assetsDir, cacheFile, manifestCacheFile };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = { copyAssetsToDest, getAssetsPaths };
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const http = require('http');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const MANIFEST_URL = "https://114.242.26.126:1000/EarthSDK/earthsdk3-assets/assets-list.json";
|
|
8
|
+
const BASE_URL = MANIFEST_URL.substring(0, MANIFEST_URL.lastIndexOf('/'));
|
|
9
|
+
const CONCURRENCY = 6;
|
|
10
|
+
const MAX_RETRIES = 3;
|
|
11
|
+
|
|
12
|
+
const agent = new https.Agent({
|
|
13
|
+
rejectUnauthorized: false
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function getProtocol(url) {
|
|
17
|
+
if (url.startsWith('https://')) {
|
|
18
|
+
return https;
|
|
19
|
+
}
|
|
20
|
+
if (url.startsWith('http://')) {
|
|
21
|
+
return http;
|
|
22
|
+
}
|
|
23
|
+
throw new Error('不支持的协议: ' + url);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function stableStringify(obj) {
|
|
27
|
+
if (Array.isArray(obj)) {
|
|
28
|
+
return `[${obj.map(stableStringify).join(',')}]`;
|
|
29
|
+
}
|
|
30
|
+
if (obj && typeof obj === 'object') {
|
|
31
|
+
return `{${Object.keys(obj).sort().map(
|
|
32
|
+
k => `"${k}":${stableStringify(obj[k])}`
|
|
33
|
+
).join(',')}}`;
|
|
34
|
+
}
|
|
35
|
+
return JSON.stringify(obj);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function fetchJson(url) {
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
const request = getProtocol(url).get(url, { agent }, (response) => {
|
|
41
|
+
if (response.statusCode !== 200) {
|
|
42
|
+
reject(new Error(`HTTP ${response.statusCode}: ${url}`));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
let data = '';
|
|
46
|
+
response.on('data', chunk => {
|
|
47
|
+
data += chunk;
|
|
48
|
+
});
|
|
49
|
+
response.on('end', () => {
|
|
50
|
+
try {
|
|
51
|
+
resolve(JSON.parse(data));
|
|
52
|
+
} catch {
|
|
53
|
+
reject(new Error(`JSON 解析失败: ${url}`));
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
response.on('error', reject);
|
|
57
|
+
});
|
|
58
|
+
request.setTimeout(15000, () => {
|
|
59
|
+
request.destroy(new Error('请求超时'));
|
|
60
|
+
});
|
|
61
|
+
request.on('error', reject);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function collectTasks(node, currentPath, tasks, outDir) {
|
|
66
|
+
for (const key in node) {
|
|
67
|
+
if (!Object.hasOwn(node, key)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const value = node[key];
|
|
71
|
+
const nextPath = path.join(currentPath, key);
|
|
72
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
73
|
+
if (typeof value.size === 'number' && typeof value.md5 === 'string') {
|
|
74
|
+
const filePath = nextPath.replaceAll('\\', '/');
|
|
75
|
+
pushTask(filePath, tasks, outDir);
|
|
76
|
+
} else {
|
|
77
|
+
collectTasks(value, nextPath, tasks, outDir);
|
|
78
|
+
}
|
|
79
|
+
} else if (Array.isArray(value)) {
|
|
80
|
+
for (const fileName of value) {
|
|
81
|
+
const filePath = path.join(nextPath, fileName).replaceAll('\\', '/');
|
|
82
|
+
pushTask(filePath, tasks, outDir);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function collectFilePaths(node, currentPath, fileSet) {
|
|
89
|
+
for (const key in node) {
|
|
90
|
+
if (!Object.hasOwn(node, key)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const value = node[key];
|
|
94
|
+
const nextPath = path.join(currentPath, key);
|
|
95
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
96
|
+
if (typeof value.size === 'number' && typeof value.md5 === 'string') {
|
|
97
|
+
fileSet.add(nextPath.replaceAll('\\', '/'));
|
|
98
|
+
} else {
|
|
99
|
+
collectFilePaths(value, nextPath, fileSet);
|
|
100
|
+
}
|
|
101
|
+
} else if (Array.isArray(value)) {
|
|
102
|
+
for (const fileName of value) {
|
|
103
|
+
fileSet.add(path.join(nextPath, fileName).replaceAll('\\', '/'));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function collectDownloadTasks(newNode, oldNode, currentPath, tasks, outDir) {
|
|
110
|
+
for (const key in newNode) {
|
|
111
|
+
if (!Object.hasOwn(newNode, key)) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const newValue = newNode[key];
|
|
115
|
+
const oldValue = oldNode && Object.hasOwn(oldNode, key) ? oldNode[key] : null;
|
|
116
|
+
const nextPath = path.join(currentPath, key);
|
|
117
|
+
if (newValue && typeof newValue === 'object' && !Array.isArray(newValue)) {
|
|
118
|
+
if (typeof newValue.size === 'number' && typeof newValue.md5 === 'string') {
|
|
119
|
+
const filePath = nextPath.replaceAll('\\', '/');
|
|
120
|
+
if (!oldValue || typeof oldValue !== 'object' || oldValue.size !== newValue.size || oldValue.md5 !== newValue.md5) {
|
|
121
|
+
pushTask(filePath, tasks, outDir);
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
collectDownloadTasks(newValue, oldValue, nextPath, tasks, outDir);
|
|
125
|
+
}
|
|
126
|
+
} else if (Array.isArray(newValue)) {
|
|
127
|
+
for (const fileName of newValue) {
|
|
128
|
+
const filePath = path.join(nextPath, fileName).replaceAll('\\', '/');
|
|
129
|
+
const oldArray = Array.isArray(oldValue) ? oldValue : [];
|
|
130
|
+
if (!oldArray.includes(fileName)) {
|
|
131
|
+
pushTask(filePath, tasks, outDir);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function pushTask(filePath, tasks, outDir) {
|
|
139
|
+
const outputPath = path.join(outDir, filePath);
|
|
140
|
+
tasks.push({
|
|
141
|
+
url: `${BASE_URL}/${filePath}`,
|
|
142
|
+
outputPath
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function downloadFile(url, outputPath) {
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
149
|
+
const tempPath = outputPath + '.download';
|
|
150
|
+
const file = fs.createWriteStream(tempPath);
|
|
151
|
+
const request = getProtocol(url).get(url, { agent }, (response) => {
|
|
152
|
+
if (response.statusCode !== 200) {
|
|
153
|
+
file.close();
|
|
154
|
+
try {
|
|
155
|
+
fs.unlinkSync(tempPath);
|
|
156
|
+
} catch { }
|
|
157
|
+
reject(new Error(`HTTP ${response.statusCode}: ${url}`));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
response.pipe(file);
|
|
161
|
+
file.on('finish', () => {
|
|
162
|
+
file.close(() => {
|
|
163
|
+
fs.rmSync(outputPath, { force: true });
|
|
164
|
+
fs.renameSync(tempPath, outputPath);
|
|
165
|
+
resolve();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
file.on('error', (err) => {
|
|
169
|
+
try {
|
|
170
|
+
fs.unlinkSync(tempPath);
|
|
171
|
+
} catch { }
|
|
172
|
+
reject(err);
|
|
173
|
+
});
|
|
174
|
+
response.on('error', (err) => {
|
|
175
|
+
try {
|
|
176
|
+
fs.unlinkSync(tempPath);
|
|
177
|
+
} catch { }
|
|
178
|
+
reject(err);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
request.setTimeout(15000, () => {
|
|
182
|
+
request.destroy(new Error('请求超时'));
|
|
183
|
+
});
|
|
184
|
+
request.on('error', (err) => {
|
|
185
|
+
try {
|
|
186
|
+
fs.unlinkSync(tempPath);
|
|
187
|
+
} catch { }
|
|
188
|
+
reject(err);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function downloadWithRetry(url, outputPath, retries) {
|
|
194
|
+
for (let i = 0; i < retries; i++) {
|
|
195
|
+
try {
|
|
196
|
+
await downloadFile(url, outputPath);
|
|
197
|
+
return;
|
|
198
|
+
} catch (err) {
|
|
199
|
+
if (i === retries - 1) {
|
|
200
|
+
console.error(`[assets] 下载失败(已重试${retries}次): ${url}`);
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
203
|
+
console.warn(`[assets] 重试(${i + 1}/${retries}): ${url}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function downloadWithConcurrency(tasks, limit) {
|
|
209
|
+
const queue = [...tasks];
|
|
210
|
+
const workers = new Array(limit).fill(null).map(async () => {
|
|
211
|
+
while (queue.length) {
|
|
212
|
+
const task = queue.shift();
|
|
213
|
+
if (!task) {
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
await downloadWithRetry(task.url, task.outputPath, MAX_RETRIES);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
await Promise.all(workers);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async function downloadAssets(assetsDir, cacheFile, manifestCacheFile, ignoreFiles) {
|
|
223
|
+
try {
|
|
224
|
+
const newAssetsList = await fetchJson(MANIFEST_URL);
|
|
225
|
+
const newHash = crypto.createHash('md5').update(
|
|
226
|
+
stableStringify(newAssetsList)
|
|
227
|
+
).digest('hex');
|
|
228
|
+
|
|
229
|
+
let oldAssetsList = null;
|
|
230
|
+
if (fs.existsSync(manifestCacheFile)) {
|
|
231
|
+
try {
|
|
232
|
+
oldAssetsList = JSON.parse(fs.readFileSync(manifestCacheFile, 'utf-8'));
|
|
233
|
+
} catch {
|
|
234
|
+
oldAssetsList = null;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (fs.existsSync(cacheFile) && fs.readFileSync(cacheFile, 'utf-8').trim() === newHash) {
|
|
239
|
+
console.log('[assets] 资源未变化,跳过下载');
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const downloadTasks = [];
|
|
244
|
+
const deletePaths = [];
|
|
245
|
+
|
|
246
|
+
if (oldAssetsList && fs.existsSync(assetsDir)) {
|
|
247
|
+
const newFiles = new Set();
|
|
248
|
+
const oldFiles = new Set();
|
|
249
|
+
collectFilePaths(newAssetsList, '', newFiles);
|
|
250
|
+
collectFilePaths(oldAssetsList, '', oldFiles);
|
|
251
|
+
|
|
252
|
+
for (const filePath of oldFiles) {
|
|
253
|
+
if (!newFiles.has(filePath)) {
|
|
254
|
+
deletePaths.push(filePath);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
collectDownloadTasks(newAssetsList, oldAssetsList, '', downloadTasks, assetsDir);
|
|
258
|
+
} else {
|
|
259
|
+
collectTasks(newAssetsList, '', downloadTasks, assetsDir);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (deletePaths.length > 0) {
|
|
263
|
+
console.log(`[assets] 删除 ${deletePaths.length} 个文件...`);
|
|
264
|
+
for (const filePath of deletePaths) {
|
|
265
|
+
const fullPath = path.join(assetsDir, filePath);
|
|
266
|
+
try {
|
|
267
|
+
fs.rmSync(fullPath, { force: true });
|
|
268
|
+
} catch (err) {
|
|
269
|
+
console.warn(`[assets] 删除文件失败: ${fullPath}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (downloadTasks.length > 0) {
|
|
275
|
+
console.log(`[assets] 共 ${downloadTasks.length} 个文件需要下载...`);
|
|
276
|
+
await downloadWithConcurrency(downloadTasks, CONCURRENCY);
|
|
277
|
+
} else {
|
|
278
|
+
console.log('[assets] 无需下载新文件');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
fs.mkdirSync(assetsDir, { recursive: true });
|
|
282
|
+
fs.writeFileSync(cacheFile, newHash, 'utf-8');
|
|
283
|
+
fs.writeFileSync(manifestCacheFile, JSON.stringify(newAssetsList, null, 2), 'utf-8');
|
|
284
|
+
console.log('[assets] 下载完成');
|
|
285
|
+
} catch (err) {
|
|
286
|
+
console.error('[assets] 下载失败:', err.message);
|
|
287
|
+
throw err;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
module.exports = { downloadAssets, MANIFEST_URL, BASE_URL, CONCURRENCY, MAX_RETRIES };
|
package/src/index.cjs
CHANGED
|
@@ -20,9 +20,10 @@ function detectBuildTool() {
|
|
|
20
20
|
...pkg.devDependencies
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
// 优先级:Vite > Rspack > Webpack
|
|
23
|
+
// 优先级:Vite > Rspack > Vue CLI > Webpack
|
|
24
24
|
if (allDeps.vite) return 'vite';
|
|
25
25
|
if (allDeps['@rspack/core'] || allDeps.rspack) return 'rspack';
|
|
26
|
+
if (allDeps['@vue/cli-service']) return 'webpack';
|
|
26
27
|
if (allDeps.webpack || allDeps['html-webpack-plugin']) return 'webpack';
|
|
27
28
|
|
|
28
29
|
// 检测配置文件
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
declare module 'earthsdk3-assets' {
|
|
2
|
+
export interface EarthsdkAssetsOptions {
|
|
3
|
+
forceTool?: 'vite' | 'webpack' | 'rspack' | 'vue-cli';
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface EarthsdkAssetsPlugin {
|
|
7
|
+
name: string;
|
|
8
|
+
transformIndexHtml?: () => Array<{
|
|
9
|
+
tag: string;
|
|
10
|
+
attrs: Record<string, string>;
|
|
11
|
+
injectTo: 'head' | 'body';
|
|
12
|
+
}>;
|
|
13
|
+
configResolved?: (config: any) => void;
|
|
14
|
+
configureServer?: (server: any) => Promise<void>;
|
|
15
|
+
closeBundle?: () => Promise<void>;
|
|
16
|
+
apply?: (compiler: any) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function detectBuildTool(): 'vite' | 'webpack' | 'rspack' | null;
|
|
20
|
+
|
|
21
|
+
export function vitePlugin(options?: EarthsdkAssetsOptions): EarthsdkAssetsPlugin;
|
|
22
|
+
export function webpackPlugin(options?: EarthsdkAssetsOptions): any;
|
|
23
|
+
export function rspackPlugin(options?: EarthsdkAssetsOptions): any;
|
|
24
|
+
|
|
25
|
+
export default function earthsdkAssets(options?: EarthsdkAssetsOptions): Promise<EarthsdkAssetsPlugin> | any;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare module 'earthsdk3-assets/vite' {
|
|
29
|
+
import type { EarthsdkAssetsOptions, EarthsdkAssetsPlugin } from 'earthsdk3-assets';
|
|
30
|
+
export default function vitePlugin(options?: EarthsdkAssetsOptions): EarthsdkAssetsPlugin;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare module 'earthsdk3-assets/webpack' {
|
|
34
|
+
import type { EarthsdkAssetsOptions } from 'earthsdk3-assets';
|
|
35
|
+
export default class EarthsdkAssetsWebpackPlugin {
|
|
36
|
+
constructor(options?: EarthsdkAssetsOptions);
|
|
37
|
+
apply(compiler: any): void;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare module 'earthsdk3-assets/rspack' {
|
|
42
|
+
import type { EarthsdkAssetsOptions } from 'earthsdk3-assets';
|
|
43
|
+
export default class EarthsdkAssetsRspackPlugin {
|
|
44
|
+
constructor(options?: EarthsdkAssetsOptions);
|
|
45
|
+
apply(compiler: any): void;
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/index.js
CHANGED
|
@@ -24,10 +24,10 @@ function detectBuildTool() {
|
|
|
24
24
|
...pkg.devDependencies
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
// 优先级:Vite > Rspack > Webpack
|
|
28
|
-
// Rspack 需要优先于 Webpack 检测,因为 Rspack 项目通常也依赖 @rspack/core
|
|
27
|
+
// 优先级:Vite > Rspack > Vue CLI > Webpack
|
|
29
28
|
if (allDeps.vite) return 'vite';
|
|
30
29
|
if (allDeps['@rspack/core'] || allDeps.rspack) return 'rspack';
|
|
30
|
+
if (allDeps['@vue/cli-service']) return 'webpack';
|
|
31
31
|
if (allDeps.webpack || allDeps['html-webpack-plugin']) return 'webpack';
|
|
32
32
|
|
|
33
33
|
// 检测配置文件
|
package/src/plugins/rspack.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// 但为了清晰,单独提供 Rspack 入口
|
|
6
|
-
|
|
7
|
-
async function loadCore() {
|
|
8
|
-
const { downloadAssets } = await import('../core/downloadAssets.js');
|
|
9
|
-
const { copyAssetsToDest, getAssetsPaths } = await import('../core/copyAssets.js');
|
|
10
|
-
return { downloadAssets, copyAssetsToDest, getAssetsPaths };
|
|
11
|
-
}
|
|
3
|
+
const { downloadAssets } = require('../core/downloadAssets.cjs');
|
|
4
|
+
const { copyAssetsToDest, getAssetsPaths } = require('../core/copyAssets.cjs');
|
|
12
5
|
|
|
13
6
|
const ROOT_DIR = path.resolve(__dirname, '../..');
|
|
14
7
|
let hasDownloaded = false;
|
|
@@ -18,7 +11,6 @@ async function ensureAssets(assetsDir, cacheFile, manifestCacheFile) {
|
|
|
18
11
|
return;
|
|
19
12
|
}
|
|
20
13
|
hasDownloaded = true;
|
|
21
|
-
const { downloadAssets } = await loadCore();
|
|
22
14
|
await downloadAssets(assetsDir, cacheFile, manifestCacheFile);
|
|
23
15
|
}
|
|
24
16
|
|
|
@@ -29,10 +21,8 @@ class EarthsdkAssetsRspackPlugin {
|
|
|
29
21
|
}
|
|
30
22
|
|
|
31
23
|
apply(compiler) {
|
|
32
|
-
const { getAssetsPaths } = require('../core/copyAssets.js');
|
|
33
24
|
const { assetsDir, cacheFile, manifestCacheFile } = getAssetsPaths(ROOT_DIR);
|
|
34
25
|
|
|
35
|
-
// 1. 下载资源(编译前)
|
|
36
26
|
compiler.hooks.beforeRun.tapPromise('EarthsdkAssetsRspackPlugin', async () => {
|
|
37
27
|
await ensureAssets(assetsDir, cacheFile, manifestCacheFile);
|
|
38
28
|
});
|
|
@@ -41,14 +31,11 @@ class EarthsdkAssetsRspackPlugin {
|
|
|
41
31
|
await ensureAssets(assetsDir, cacheFile, manifestCacheFile);
|
|
42
32
|
});
|
|
43
33
|
|
|
44
|
-
// 2. 获取输出目录
|
|
45
34
|
compiler.hooks.afterEnvironment.tap('EarthsdkAssetsRspackPlugin', () => {
|
|
46
35
|
this.outDir = compiler.options.output.path || 'dist';
|
|
47
36
|
});
|
|
48
37
|
|
|
49
|
-
// 3. 注入 HTML(需要 @rspack/plugin-html 或 html-webpack-plugin)
|
|
50
38
|
compiler.hooks.compilation.tap('EarthsdkAssetsRspackPlugin', (compilation) => {
|
|
51
|
-
// Rspack 内置 html 插件或兼容 html-webpack-plugin
|
|
52
39
|
let HtmlPlugin;
|
|
53
40
|
try {
|
|
54
41
|
HtmlPlugin = require('@rspack/plugin-html');
|
|
@@ -79,13 +66,10 @@ class EarthsdkAssetsRspackPlugin {
|
|
|
79
66
|
}
|
|
80
67
|
});
|
|
81
68
|
|
|
82
|
-
// 4. 拷贝资源到产物目录
|
|
83
69
|
compiler.hooks.afterEmit.tapPromise('EarthsdkAssetsRspackPlugin', async () => {
|
|
84
|
-
const { copyAssetsToDest } = await loadCore();
|
|
85
70
|
copyAssetsToDest(assetsDir, ROOT_DIR, this.outDir);
|
|
86
71
|
});
|
|
87
72
|
|
|
88
|
-
// 5. Dev Server 中间件(@rspack/dev-server)
|
|
89
73
|
compiler.hooks.afterEnvironment.tap('EarthsdkAssetsRspackPlugin', () => {
|
|
90
74
|
const devServer = compiler.options.devServer;
|
|
91
75
|
if (devServer) {
|
|
@@ -127,4 +111,4 @@ class EarthsdkAssetsRspackPlugin {
|
|
|
127
111
|
}
|
|
128
112
|
|
|
129
113
|
module.exports = EarthsdkAssetsRspackPlugin;
|
|
130
|
-
module.exports.default = EarthsdkAssetsRspackPlugin;
|
|
114
|
+
module.exports.default = EarthsdkAssetsRspackPlugin;
|
package/src/plugins/webpack.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
async function loadCore() {
|
|
6
|
-
const { downloadAssets } = await import('../core/downloadAssets.js');
|
|
7
|
-
const { copyAssetsToDest, getAssetsPaths } = await import('../core/copyAssets.js');
|
|
8
|
-
return { downloadAssets, copyAssetsToDest, getAssetsPaths };
|
|
9
|
-
}
|
|
3
|
+
const { downloadAssets } = require('../core/downloadAssets.cjs');
|
|
4
|
+
const { copyAssetsToDest, getAssetsPaths } = require('../core/copyAssets.cjs');
|
|
10
5
|
|
|
11
6
|
const ROOT_DIR = path.resolve(__dirname, '../..');
|
|
12
7
|
let hasDownloaded = false;
|
|
@@ -16,7 +11,6 @@ async function ensureAssets(assetsDir, cacheFile, manifestCacheFile) {
|
|
|
16
11
|
return;
|
|
17
12
|
}
|
|
18
13
|
hasDownloaded = true;
|
|
19
|
-
const { downloadAssets } = await loadCore();
|
|
20
14
|
await downloadAssets(assetsDir, cacheFile, manifestCacheFile);
|
|
21
15
|
}
|
|
22
16
|
|
|
@@ -29,7 +23,6 @@ class EarthsdkAssetsWebpackPlugin {
|
|
|
29
23
|
apply(compiler) {
|
|
30
24
|
const { assetsDir, cacheFile, manifestCacheFile } = getAssetsPaths(ROOT_DIR);
|
|
31
25
|
|
|
32
|
-
// 1. 下载资源(编译前)
|
|
33
26
|
compiler.hooks.beforeRun.tapPromise('EarthsdkAssetsWebpackPlugin', async () => {
|
|
34
27
|
await ensureAssets(assetsDir, cacheFile, manifestCacheFile);
|
|
35
28
|
});
|
|
@@ -38,12 +31,10 @@ class EarthsdkAssetsWebpackPlugin {
|
|
|
38
31
|
await ensureAssets(assetsDir, cacheFile, manifestCacheFile);
|
|
39
32
|
});
|
|
40
33
|
|
|
41
|
-
// 2. 获取输出目录
|
|
42
34
|
compiler.hooks.afterEnvironment.tap('EarthsdkAssetsWebpackPlugin', () => {
|
|
43
35
|
this.outDir = compiler.options.output.path || 'dist';
|
|
44
36
|
});
|
|
45
37
|
|
|
46
|
-
// 3. 注入 HTML(需要 html-webpack-plugin)
|
|
47
38
|
compiler.hooks.compilation.tap('EarthsdkAssetsWebpackPlugin', (compilation) => {
|
|
48
39
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
49
40
|
|
|
@@ -65,19 +56,15 @@ class EarthsdkAssetsWebpackPlugin {
|
|
|
65
56
|
}
|
|
66
57
|
});
|
|
67
58
|
|
|
68
|
-
// 4. 拷贝资源到产物目录
|
|
69
59
|
compiler.hooks.afterEmit.tapPromise('EarthsdkAssetsWebpackPlugin', async () => {
|
|
70
|
-
const { copyAssetsToDest } = await loadCore();
|
|
71
60
|
copyAssetsToDest(assetsDir, ROOT_DIR, this.outDir);
|
|
72
61
|
});
|
|
73
62
|
|
|
74
|
-
// 5. Dev Server 中间件(webpack-dev-server)
|
|
75
63
|
compiler.hooks.afterEnvironment.tap('EarthsdkAssetsWebpackPlugin', () => {
|
|
76
64
|
const devServer = compiler.options.devServer;
|
|
77
65
|
if (devServer) {
|
|
78
66
|
const originalSetup = devServer.setupMiddlewares;
|
|
79
67
|
devServer.setupMiddlewares = (middlewares, devServer) => {
|
|
80
|
-
// 添加 earthsdk-assets 中间件
|
|
81
68
|
devServer.app.use('/js', (req, res, next) => {
|
|
82
69
|
try {
|
|
83
70
|
const filePath = path.resolve(ROOT_DIR, '.' + decodeURIComponent(req.url));
|
|
@@ -113,12 +100,5 @@ class EarthsdkAssetsWebpackPlugin {
|
|
|
113
100
|
}
|
|
114
101
|
}
|
|
115
102
|
|
|
116
|
-
function getAssetsPaths(rootDir) {
|
|
117
|
-
const assetsDir = path.resolve(rootDir, 'assets');
|
|
118
|
-
const cacheFile = path.resolve(assetsDir, '.assets-version');
|
|
119
|
-
const manifestCacheFile = path.resolve(assetsDir, '.assets-manifest.json');
|
|
120
|
-
return { assetsDir, cacheFile, manifestCacheFile };
|
|
121
|
-
}
|
|
122
|
-
|
|
123
103
|
module.exports = EarthsdkAssetsWebpackPlugin;
|
|
124
|
-
module.exports.default = EarthsdkAssetsWebpackPlugin;
|
|
104
|
+
module.exports.default = EarthsdkAssetsWebpackPlugin;
|