@steedos/unpkg 3.0.13-beta.5 → 3.0.13-beta.7
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 +62 -0
- package/package.json +2 -2
- package/preload-unpkg.js +191 -0
- package/unpkg-resources.json +21 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# UNPKG 资源预加载
|
|
2
|
+
|
|
3
|
+
在 Docker 镜像构建时预加载指定的 npm 包到本地缓存,提高运行时性能。
|
|
4
|
+
|
|
5
|
+
## 配置文件
|
|
6
|
+
|
|
7
|
+
编辑 `unpkg-resources.json` 配置要预加载的包:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
[
|
|
11
|
+
"lodash@4.17.21",
|
|
12
|
+
"marked@0.3.19",
|
|
13
|
+
"@steedos-builder/sdk@1.0.0"
|
|
14
|
+
]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
格式说明:
|
|
18
|
+
- 标准包: `package@version`
|
|
19
|
+
- Scoped 包: `@scope/package@version`
|
|
20
|
+
|
|
21
|
+
## 缓存格式
|
|
22
|
+
|
|
23
|
+
遵循 `@steedos/ee_unpkg` 官方文档约定:
|
|
24
|
+
|
|
25
|
+
- 元数据文件: `{packageName}.json` (Scoped 包中 `/` 替换为 `_`)
|
|
26
|
+
- Tarball 文件: `{packageName}-{version}.tgz`
|
|
27
|
+
|
|
28
|
+
示例:
|
|
29
|
+
```
|
|
30
|
+
/caches/
|
|
31
|
+
├── lodash.json
|
|
32
|
+
├── lodash-4.17.21.tgz
|
|
33
|
+
├── @steedos-builder_sdk.json
|
|
34
|
+
└── @steedos-builder_sdk-1.0.0.tgz
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 使用方法
|
|
38
|
+
|
|
39
|
+
### Docker 构建时预加载
|
|
40
|
+
|
|
41
|
+
在 Dockerfile 中添加:
|
|
42
|
+
|
|
43
|
+
```dockerfile
|
|
44
|
+
RUN mkdir -p /steedos-storage/unpkg \
|
|
45
|
+
&& export NPM_CACHE_FOLDER=/steedos-storage/unpkg \
|
|
46
|
+
&& node /app/services/unpkg/preload-unpkg.js
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 本地测试
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cd services/unpkg
|
|
53
|
+
mkdir -p /tmp/unpkg-cache
|
|
54
|
+
export NPM_CACHE_FOLDER=/tmp/unpkg-cache
|
|
55
|
+
node preload-unpkg.js
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 环境变量
|
|
59
|
+
|
|
60
|
+
- `NPM_CACHE_FOLDER`: 缓存目录路径(默认: `$B6_STORAGE_DIR/unpkg`)
|
|
61
|
+
- `NPM_REGISTRY`: NPM Registry URL(默认: `https://registry.npmjs.org`)
|
|
62
|
+
- `B6_STORAGE_DIR`: 存储根目录(默认: `/steedos-storage`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steedos/unpkg",
|
|
3
|
-
"version": "3.0.13-beta.
|
|
3
|
+
"version": "3.0.13-beta.7",
|
|
4
4
|
"main": "package.service.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@steedos/ee_unpkg": "^3.0.2"
|
|
11
11
|
},
|
|
12
|
-
"gitHead": "
|
|
12
|
+
"gitHead": "18501bc46697ccffd912fb039324d89a6369362b"
|
|
13
13
|
}
|
package/preload-unpkg.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UNPKG 资源预加载脚本
|
|
3
|
+
* 在 Docker 镜像构建时预加载指定的 npm 包到本地缓存
|
|
4
|
+
*
|
|
5
|
+
* 缓存格式遵循 @steedos/ee_unpkg 官方文档:
|
|
6
|
+
* - Package metadata: {packageName}.json
|
|
7
|
+
* - Package tarball: {packageName}-{version}.tgz
|
|
8
|
+
* - Scoped packages: @org/pkg → @org_pkg (将 / 替换为 _)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const https = require('https');
|
|
12
|
+
const http = require('http');
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const url = require('url');
|
|
16
|
+
|
|
17
|
+
// 读取配置文件
|
|
18
|
+
const configPath = path.join(__dirname, 'unpkg-resources.json');
|
|
19
|
+
const packages = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
20
|
+
|
|
21
|
+
// 获取缓存文件夹路径
|
|
22
|
+
const NPM_CACHE_FOLDER = process.env.NPM_CACHE_FOLDER ||
|
|
23
|
+
path.join(process.env.B6_STORAGE_DIR || '/steedos-storage', 'unpkg');
|
|
24
|
+
|
|
25
|
+
// NPM Registry URL
|
|
26
|
+
const NPM_REGISTRY = process.env.NPM_REGISTRY || 'https://registry.npmjs.org';
|
|
27
|
+
|
|
28
|
+
// 确保缓存目录存在
|
|
29
|
+
if (!fs.existsSync(NPM_CACHE_FOLDER)) {
|
|
30
|
+
fs.mkdirSync(NPM_CACHE_FOLDER, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 解析包名和版本
|
|
35
|
+
* @param {string} packageSpec - 格式: "package@version" 或 "@scope/package@version"
|
|
36
|
+
* @returns {{name: string, version: string}}
|
|
37
|
+
*/
|
|
38
|
+
function parsePackageSpec(packageSpec) {
|
|
39
|
+
// 处理 scoped package: @scope/package@version
|
|
40
|
+
const match = packageSpec.match(/^(@?[^@]+)@(.+)$/);
|
|
41
|
+
if (!match) {
|
|
42
|
+
throw new Error(`Invalid package spec: ${packageSpec}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
name: match[1],
|
|
47
|
+
version: match[2]
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 转换包名为缓存文件名(将 / 替换为 _)
|
|
53
|
+
* @param {string} packageName - 原始包名
|
|
54
|
+
* @returns {string}
|
|
55
|
+
*/
|
|
56
|
+
function toCacheFileName(packageName) {
|
|
57
|
+
return packageName.replace(/\//g, '_');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 下载文件
|
|
62
|
+
* @param {string} fileUrl - 文件 URL
|
|
63
|
+
* @param {string} destPath - 目标路径
|
|
64
|
+
* @returns {Promise<void>}
|
|
65
|
+
*/
|
|
66
|
+
function downloadFile(fileUrl, destPath) {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const parsedUrl = url.parse(fileUrl);
|
|
69
|
+
const client = parsedUrl.protocol === 'https:' ? https : http;
|
|
70
|
+
|
|
71
|
+
client.get(fileUrl, (response) => {
|
|
72
|
+
// 处理重定向
|
|
73
|
+
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
74
|
+
const redirectUrl = response.headers.location;
|
|
75
|
+
console.log(` 重定向到: ${redirectUrl}`);
|
|
76
|
+
return downloadFile(redirectUrl, destPath).then(resolve).catch(reject);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (response.statusCode !== 200) {
|
|
80
|
+
reject(new Error(`HTTP ${response.statusCode}: ${fileUrl}`));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const fileStream = fs.createWriteStream(destPath);
|
|
85
|
+
response.pipe(fileStream);
|
|
86
|
+
|
|
87
|
+
fileStream.on('finish', () => {
|
|
88
|
+
fileStream.close();
|
|
89
|
+
resolve();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
fileStream.on('error', (err) => {
|
|
93
|
+
fs.unlink(destPath, () => {});
|
|
94
|
+
reject(err);
|
|
95
|
+
});
|
|
96
|
+
}).on('error', reject);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 预加载单个包
|
|
102
|
+
* @param {string} packageSpec - 格式: "package@version"
|
|
103
|
+
*/
|
|
104
|
+
async function preloadPackage(packageSpec) {
|
|
105
|
+
const { name, version } = parsePackageSpec(packageSpec);
|
|
106
|
+
const cacheFileName = toCacheFileName(name);
|
|
107
|
+
|
|
108
|
+
console.log(`\n预加载: ${packageSpec}`);
|
|
109
|
+
console.log(` 包名: ${name}`);
|
|
110
|
+
console.log(` 版本: ${version}`);
|
|
111
|
+
console.log(` 缓存名: ${cacheFileName}`);
|
|
112
|
+
|
|
113
|
+
// 1. 下载 package.json 元数据
|
|
114
|
+
const metadataUrl = `${NPM_REGISTRY}/${name}`;
|
|
115
|
+
const metadataPath = path.join(NPM_CACHE_FOLDER, `${cacheFileName}.json`);
|
|
116
|
+
|
|
117
|
+
if (fs.existsSync(metadataPath)) {
|
|
118
|
+
console.log(` ✓ 元数据已存在: ${cacheFileName}.json`);
|
|
119
|
+
} else {
|
|
120
|
+
console.log(` 下载元数据: ${metadataUrl}`);
|
|
121
|
+
await downloadFile(metadataUrl, metadataPath);
|
|
122
|
+
console.log(` ✓ 元数据已保存: ${cacheFileName}.json`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 2. 读取元数据获取 tarball URL
|
|
126
|
+
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf-8'));
|
|
127
|
+
const versionData = metadata.versions && metadata.versions[version];
|
|
128
|
+
|
|
129
|
+
if (!versionData || !versionData.dist || !versionData.dist.tarball) {
|
|
130
|
+
throw new Error(`版本 ${version} 不存在或缺少 tarball 信息`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const tarballUrl = versionData.dist.tarball;
|
|
134
|
+
const tarballPath = path.join(NPM_CACHE_FOLDER, `${cacheFileName}-${version}.tgz`);
|
|
135
|
+
|
|
136
|
+
if (fs.existsSync(tarballPath)) {
|
|
137
|
+
console.log(` ✓ Tarball 已存在: ${cacheFileName}-${version}.tgz`);
|
|
138
|
+
} else {
|
|
139
|
+
console.log(` 下载 tarball: ${tarballUrl}`);
|
|
140
|
+
await downloadFile(tarballUrl, tarballPath);
|
|
141
|
+
console.log(` ✓ Tarball 已保存: ${cacheFileName}-${version}.tgz`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log(`✓ 完成: ${packageSpec}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 主函数
|
|
149
|
+
*/
|
|
150
|
+
async function main() {
|
|
151
|
+
console.log('========================================');
|
|
152
|
+
console.log('UNPKG 资源预加载');
|
|
153
|
+
console.log('========================================');
|
|
154
|
+
console.log(`缓存目录: ${NPM_CACHE_FOLDER}`);
|
|
155
|
+
console.log(`Registry: ${NPM_REGISTRY}`);
|
|
156
|
+
console.log(`包数量: ${packages.length}`);
|
|
157
|
+
console.log('========================================');
|
|
158
|
+
|
|
159
|
+
let successCount = 0;
|
|
160
|
+
let failCount = 0;
|
|
161
|
+
|
|
162
|
+
for (const packageSpec of packages) {
|
|
163
|
+
try {
|
|
164
|
+
await preloadPackage(packageSpec);
|
|
165
|
+
successCount++;
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error(`✗ 失败: ${packageSpec}`);
|
|
168
|
+
console.error(` 错误: ${error.message}`);
|
|
169
|
+
failCount++;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log('\n========================================');
|
|
174
|
+
console.log('预加载完成');
|
|
175
|
+
console.log(`成功: ${successCount} / 失败: ${failCount}`);
|
|
176
|
+
console.log('========================================');
|
|
177
|
+
|
|
178
|
+
if (failCount > 0) {
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 运行
|
|
184
|
+
if (require.main === module) {
|
|
185
|
+
main().catch((error) => {
|
|
186
|
+
console.error('预加载失败:', error);
|
|
187
|
+
process.exit(1);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
module.exports = { preloadPackage, parsePackageSpec, toCacheFileName };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[
|
|
2
|
+
"@fortawesome/fontawesome-free@6.2.0",
|
|
3
|
+
"@salesforce-ux/design-system@2.28.1",
|
|
4
|
+
"@steedos-builder/fiddle@0.0.5",
|
|
5
|
+
"@steedos-widgets/amis-object@6.10.52-beta.3",
|
|
6
|
+
"@steedos-widgets/amis@6.3.0-patch.8",
|
|
7
|
+
"@steedos-widgets/antd@6.10.52-beta.3",
|
|
8
|
+
"@steedos-widgets/fullcalendar-scheduler@6.10.52-beta.3",
|
|
9
|
+
"@steedos-widgets/liveblocks@6.10.52-beta.3",
|
|
10
|
+
"antd@5.29.2",
|
|
11
|
+
"axios@0.26.1",
|
|
12
|
+
"crypto-js@4.1.1",
|
|
13
|
+
"dayjs@1.11.19",
|
|
14
|
+
"flowbite@2.3.0",
|
|
15
|
+
"fullcalendar-scheduler@5.11.4",
|
|
16
|
+
"i18next@24.2.2",
|
|
17
|
+
"jquery@3.7.1",
|
|
18
|
+
"liquidjs@10.24.0",
|
|
19
|
+
"lodash@4.17.21",
|
|
20
|
+
"sortablejs@1.15.6"
|
|
21
|
+
]
|