mirror of
https://github.com/Silentely/eSIM-Tools.git
synced 2026-09-03 06:24:20 +08:00
docs(deployment): 添加 Netlify 部署配置和优化指南
- 新增 DEPLOYMENT.md 文件,详细说明 Netlify 部署配置和优化策略 - 更新 .netlifyignore 文件,排除非必要文件以提高部署效率 - 修改 netlify.toml 文件,启用资源压缩和缓存控制 - 添加部署分析脚本,生成部署清单和统计信息 - 优化 package.json,增加部署相关命令
This commit is contained in:
@@ -1,40 +1,87 @@
|
||||
# Netlify部署时忽略的文件
|
||||
# 这些文件会保留在Git仓库中,但不会部署到Netlify
|
||||
# 开发工具和配置文件
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.npm
|
||||
.yarn-integrity
|
||||
|
||||
# PHP文件(Netlify不支持PHP)
|
||||
*.php
|
||||
# 构建工具配置
|
||||
webpack.config.js
|
||||
postcss.config.js
|
||||
.babelrc
|
||||
.browserslistrc
|
||||
.eslintrc*
|
||||
.prettierrc*
|
||||
.editorconfig
|
||||
|
||||
# 开发相关文件
|
||||
*.md
|
||||
docs/
|
||||
tests/
|
||||
# 开发脚本
|
||||
scripts/
|
||||
*.config.js
|
||||
*.config.json
|
||||
|
||||
# 版本控制文件
|
||||
# 测试文件
|
||||
tests/
|
||||
test-*.html
|
||||
*.test.js
|
||||
*.spec.js
|
||||
coverage/
|
||||
.nyc_output/
|
||||
|
||||
# 文档和说明文件
|
||||
docs/
|
||||
*.md
|
||||
!README.md
|
||||
LICENSE
|
||||
license
|
||||
|
||||
# 环境配置
|
||||
.env*
|
||||
env.example
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# 版本控制
|
||||
.git/
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# IDE和编辑器文件
|
||||
# IDE和编辑器
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# 系统文件
|
||||
# 操作系统
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# 日志文件
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# 临时文件
|
||||
tmp/
|
||||
temp/
|
||||
*.tmp
|
||||
*.temp
|
||||
*.log
|
||||
*.cache
|
||||
|
||||
# 备份文件
|
||||
# 构建产物(如果不需要)
|
||||
dist/
|
||||
build/
|
||||
out/
|
||||
|
||||
# 开发服务器
|
||||
.python-version
|
||||
.venv/
|
||||
venv/
|
||||
env/
|
||||
|
||||
# 其他非必要文件
|
||||
*.bak
|
||||
*.backup
|
||||
*.backup
|
||||
*.old
|
||||
189
deployment-manifest.json
Normal file
189
deployment-manifest.json
Normal file
@@ -0,0 +1,189 @@
|
||||
{
|
||||
"timestamp": "2025-08-05T16:37:47.462Z",
|
||||
"files": [
|
||||
{
|
||||
"path": ".gitignore",
|
||||
"size": 1162,
|
||||
"sizeFormatted": "1.13 KB"
|
||||
},
|
||||
{
|
||||
"path": ".netlifyignore",
|
||||
"size": 913,
|
||||
"sizeFormatted": "913 Bytes"
|
||||
},
|
||||
{
|
||||
"path": "DEPLOYMENT.md",
|
||||
"size": 3559,
|
||||
"sizeFormatted": "3.48 KB"
|
||||
},
|
||||
{
|
||||
"path": "LICENSE",
|
||||
"size": 1065,
|
||||
"sizeFormatted": "1.04 KB"
|
||||
},
|
||||
{
|
||||
"path": "README.md",
|
||||
"size": 12547,
|
||||
"sizeFormatted": "12.25 KB"
|
||||
},
|
||||
{
|
||||
"path": "index.html",
|
||||
"size": 18430,
|
||||
"sizeFormatted": "18 KB"
|
||||
},
|
||||
{
|
||||
"path": "netlify/functions/auto-activate-esim.js",
|
||||
"size": 7590,
|
||||
"sizeFormatted": "7.41 KB"
|
||||
},
|
||||
{
|
||||
"path": "netlify/functions/giffgaff-graphql.js",
|
||||
"size": 4254,
|
||||
"sizeFormatted": "4.15 KB"
|
||||
},
|
||||
{
|
||||
"path": "netlify/functions/giffgaff-mfa-challenge.js",
|
||||
"size": 3582,
|
||||
"sizeFormatted": "3.5 KB"
|
||||
},
|
||||
{
|
||||
"path": "netlify/functions/giffgaff-mfa-validation.js",
|
||||
"size": 3558,
|
||||
"sizeFormatted": "3.47 KB"
|
||||
},
|
||||
{
|
||||
"path": "netlify/functions/verify-cookie.js",
|
||||
"size": 9755,
|
||||
"sizeFormatted": "9.53 KB"
|
||||
},
|
||||
{
|
||||
"path": "netlify.toml",
|
||||
"size": 2122,
|
||||
"sizeFormatted": "2.07 KB"
|
||||
},
|
||||
{
|
||||
"path": "package-lock.json",
|
||||
"size": 929042,
|
||||
"sizeFormatted": "907.27 KB"
|
||||
},
|
||||
{
|
||||
"path": "package.json",
|
||||
"size": 2286,
|
||||
"sizeFormatted": "2.23 KB"
|
||||
},
|
||||
{
|
||||
"path": "postman/Giffgaff-swap-esim.json",
|
||||
"size": 13290,
|
||||
"sizeFormatted": "12.98 KB"
|
||||
},
|
||||
{
|
||||
"path": "postman/Simyo-swap-esim.json",
|
||||
"size": 6843,
|
||||
"sizeFormatted": "6.68 KB"
|
||||
},
|
||||
{
|
||||
"path": "postman/giffgaff.html",
|
||||
"size": 43880,
|
||||
"sizeFormatted": "42.85 KB"
|
||||
},
|
||||
{
|
||||
"path": "postman/simyo.html",
|
||||
"size": 15154,
|
||||
"sizeFormatted": "14.8 KB"
|
||||
},
|
||||
{
|
||||
"path": "server.js",
|
||||
"size": 6148,
|
||||
"sizeFormatted": "6 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/assets/fontawesome/all.min.css",
|
||||
"size": 102809,
|
||||
"sizeFormatted": "100.4 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/assets/fontawesome/fa-brands-400.woff2",
|
||||
"size": 117852,
|
||||
"sizeFormatted": "115.09 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/assets/fontawesome/fa-regular-400.woff2",
|
||||
"size": 25392,
|
||||
"sizeFormatted": "24.8 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/assets/fontawesome/fa-solid-900.woff2",
|
||||
"size": 156400,
|
||||
"sizeFormatted": "152.73 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/assets/images/example.txt",
|
||||
"size": 51,
|
||||
"sizeFormatted": "51 Bytes"
|
||||
},
|
||||
{
|
||||
"path": "src/giffgaff/giffgaff_complete_esim.html",
|
||||
"size": 114747,
|
||||
"sizeFormatted": "112.06 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/js/giffgaff.js",
|
||||
"size": 189,
|
||||
"sizeFormatted": "189 Bytes"
|
||||
},
|
||||
{
|
||||
"path": "src/js/main.js",
|
||||
"size": 183,
|
||||
"sizeFormatted": "183 Bytes"
|
||||
},
|
||||
{
|
||||
"path": "src/js/performance.js",
|
||||
"size": 8276,
|
||||
"sizeFormatted": "8.08 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/js/simyo.js",
|
||||
"size": 183,
|
||||
"sizeFormatted": "183 Bytes"
|
||||
},
|
||||
{
|
||||
"path": "src/simyo/simyo_complete_esim.html",
|
||||
"size": 80118,
|
||||
"sizeFormatted": "78.24 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/simyo/simyo_proxy_server.js",
|
||||
"size": 14720,
|
||||
"sizeFormatted": "14.38 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/styles/animations.css",
|
||||
"size": 4789,
|
||||
"sizeFormatted": "4.68 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/styles/design-system.css",
|
||||
"size": 7630,
|
||||
"sizeFormatted": "7.45 KB"
|
||||
},
|
||||
{
|
||||
"path": "src/sw.js",
|
||||
"size": 3786,
|
||||
"sizeFormatted": "3.7 KB"
|
||||
},
|
||||
{
|
||||
"path": "test-icons.html",
|
||||
"size": 5896,
|
||||
"sizeFormatted": "5.76 KB"
|
||||
},
|
||||
{
|
||||
"path": "verify_cookie.php",
|
||||
"size": 8209,
|
||||
"sizeFormatted": "8.02 KB"
|
||||
}
|
||||
],
|
||||
"stats": {
|
||||
"totalFiles": 36,
|
||||
"totalSize": 1736410
|
||||
}
|
||||
}
|
||||
147
docs/DEPLOYMENT.md
Normal file
147
docs/DEPLOYMENT.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Netlify部署配置
|
||||
|
||||
## 概述
|
||||
|
||||
本项目已配置为在Netlify上进行高效部署,通过排除非必要文件来减少部署大小和提高部署速度。
|
||||
|
||||
## 配置文件
|
||||
|
||||
### 1. `.netlifyignore`
|
||||
排除以下非必要文件:
|
||||
- 开发工具和配置文件 (`node_modules/`, `webpack.config.js`, `.babelrc` 等)
|
||||
- 测试文件 (`tests/`, `*.test.js`)
|
||||
- 文档文件 (`docs/`, `*.md`)
|
||||
- 环境配置 (`.env*`, `env.example`)
|
||||
- IDE和编辑器文件 (`.vscode/`, `.idea/`)
|
||||
- 系统文件 (`.DS_Store`, `Thumbs.db`)
|
||||
- 临时文件 (`*.log`, `*.tmp`, `*.cache`)
|
||||
|
||||
### 2. `netlify.toml`
|
||||
主要配置:
|
||||
- **发布目录**: `.` (当前目录)
|
||||
- **构建处理**: 启用HTML、CSS、JS、图片优化
|
||||
- **缓存控制**: 静态资源长期缓存,HTML文件不缓存
|
||||
- **安全头部**: XSS保护、内容类型检查等
|
||||
- **内容安全策略**: 限制资源加载来源
|
||||
|
||||
## 部署流程
|
||||
|
||||
### 1. 自动部署
|
||||
```bash
|
||||
# 推送到GitHub后,Netlify会自动部署
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### 2. 手动部署
|
||||
```bash
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 分析部署文件
|
||||
npm run deploy-analyze
|
||||
|
||||
# 部署到Netlify
|
||||
npm run deploy
|
||||
```
|
||||
|
||||
### 3. 本地测试
|
||||
```bash
|
||||
# 启动Netlify本地开发服务器
|
||||
npm run netlify-dev
|
||||
```
|
||||
|
||||
## 部署优化
|
||||
|
||||
### 文件排除策略
|
||||
- **保留文件**: `index.html`, `src/`, `sw.js`, `README.md`
|
||||
- **排除文件**: `node_modules/`, `scripts/`, `tests/`, `docs/`
|
||||
- **构建产物**: 如果不需要,排除 `dist/`, `build/`
|
||||
|
||||
### 性能优化
|
||||
1. **资源压缩**: CSS、JS、图片自动压缩
|
||||
2. **缓存策略**: 静态资源长期缓存
|
||||
3. **CDN加速**: 全球CDN分发
|
||||
4. **HTTP/2**: 自动启用HTTP/2协议
|
||||
|
||||
### 安全配置
|
||||
1. **内容安全策略**: 限制资源加载
|
||||
2. **安全头部**: XSS保护、点击劫持防护
|
||||
3. **HTTPS**: 强制HTTPS访问
|
||||
4. **CORS**: 配置跨域访问策略
|
||||
|
||||
## 部署分析
|
||||
|
||||
运行部署分析脚本查看文件统计:
|
||||
```bash
|
||||
npm run deploy-analyze
|
||||
```
|
||||
|
||||
输出示例:
|
||||
```
|
||||
📊 分析部署文件...
|
||||
✅ 保留: index.html (2.1 KB)
|
||||
✅ 保留: src/giffgaff/giffgaff_complete_esim.html (45.2 KB)
|
||||
❌ 排除: node_modules/axios/package.json (1.2 KB)
|
||||
❌ 排除: scripts/deploy-prepare.js (3.4 KB)
|
||||
|
||||
📈 部署统计:
|
||||
总文件数: 1,234
|
||||
总大小: 156.7 MB
|
||||
保留文件数: 45
|
||||
保留大小: 2.3 MB
|
||||
排除文件数: 1,189
|
||||
排除大小: 154.4 MB
|
||||
压缩率: 98.53%
|
||||
```
|
||||
|
||||
## 部署清单
|
||||
|
||||
部署时会生成 `deployment-manifest.json` 文件,包含:
|
||||
- 部署时间戳
|
||||
- 所有部署文件的列表
|
||||
- 文件大小统计
|
||||
- 部署统计信息
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **部署失败**
|
||||
- 检查 `.netlifyignore` 配置
|
||||
- 确保必要文件未被排除
|
||||
- 查看Netlify构建日志
|
||||
|
||||
2. **文件缺失**
|
||||
- 检查 `netlify.toml` 中的发布目录配置
|
||||
- 确认文件路径正确
|
||||
|
||||
3. **性能问题**
|
||||
- 运行 `npm run deploy-analyze` 检查文件大小
|
||||
- 优化图片和资源文件
|
||||
- 检查缓存配置
|
||||
|
||||
### 调试命令
|
||||
```bash
|
||||
# 检查部署文件
|
||||
npm run deploy-prepare
|
||||
|
||||
# 本地测试
|
||||
npm run netlify-dev
|
||||
|
||||
# 安全检查
|
||||
npm run security-check
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **定期清理**: 删除不必要的文件和依赖
|
||||
2. **监控部署**: 关注部署时间和文件大小
|
||||
3. **版本控制**: 使用Git标签管理版本
|
||||
4. **备份配置**: 备份重要的配置文件
|
||||
5. **测试部署**: 在部署前进行本地测试
|
||||
|
||||
## 相关链接
|
||||
|
||||
- [Netlify文档](https://docs.netlify.com/)
|
||||
- [部署配置参考](https://docs.netlify.com/configure-builds/file-based-configuration/)
|
||||
- [性能优化指南](https://docs.netlify.com/optimize/overview/)
|
||||
121
netlify.toml
121
netlify.toml
@@ -1,73 +1,88 @@
|
||||
[build]
|
||||
# 构建命令
|
||||
command = "npm install"
|
||||
# 发布目录
|
||||
# 发布目录(静态文件所在目录)
|
||||
publish = "."
|
||||
# Functions目录
|
||||
functions = "netlify/functions"
|
||||
|
||||
# 重定向和重写规则
|
||||
[[redirects]]
|
||||
# Giffgaff eSIM页面
|
||||
from = "/giffgaff"
|
||||
to = "/src/giffgaff/giffgaff_complete_esim.html"
|
||||
status = 200
|
||||
# 构建命令(如果需要构建)
|
||||
# command = "npm run build"
|
||||
|
||||
# 环境变量
|
||||
[build.environment]
|
||||
NODE_VERSION = "18"
|
||||
NPM_VERSION = "9"
|
||||
|
||||
[[redirects]]
|
||||
# Simyo eSIM页面
|
||||
from = "/simyo"
|
||||
to = "/src/simyo/simyo_complete_esim.html"
|
||||
status = 200
|
||||
[build.processing]
|
||||
# 启用HTML处理
|
||||
html = true
|
||||
# 启用CSS处理
|
||||
css = true
|
||||
# 启用JS处理
|
||||
js = true
|
||||
# 启用图片处理
|
||||
images = true
|
||||
|
||||
[build.processing.html]
|
||||
# HTML压缩
|
||||
pretty_urls = true
|
||||
|
||||
[build.processing.css]
|
||||
# CSS压缩
|
||||
bundle = true
|
||||
# 自动添加浏览器前缀
|
||||
autoprefixer = true
|
||||
|
||||
[[redirects]]
|
||||
# 根路径重定向到选择页面
|
||||
from = "/"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
[build.processing.js]
|
||||
# JS压缩
|
||||
bundle = true
|
||||
# 代码分割
|
||||
split_bundles = true
|
||||
|
||||
# API代理重定向(用于解决CORS问题)
|
||||
[[redirects]]
|
||||
from = "/api/simyo/*"
|
||||
to = "https://appapi.simyo.nl/simyoapi/api/v1/:splat"
|
||||
status = 200
|
||||
force = true
|
||||
headers = {X-Forwarded-Host = "appapi.simyo.nl"}
|
||||
[build.processing.images]
|
||||
# 图片优化
|
||||
compress = true
|
||||
|
||||
[[redirects]]
|
||||
from = "/api/giffgaff/*"
|
||||
to = "https://api.giffgaff.com/:splat"
|
||||
status = 200
|
||||
force = true
|
||||
headers = {X-Forwarded-Host = "api.giffgaff.com"}
|
||||
|
||||
[[redirects]]
|
||||
from = "/api/giffgaff-id/*"
|
||||
to = "https://id.giffgaff.com/:splat"
|
||||
status = 200
|
||||
force = true
|
||||
headers = {X-Forwarded-Host = "id.giffgaff.com"}
|
||||
|
||||
[[redirects]]
|
||||
from = "/api/giffgaff-public/*"
|
||||
to = "https://publicapi.giffgaff.com/:splat"
|
||||
status = 200
|
||||
force = true
|
||||
headers = {X-Forwarded-Host = "publicapi.giffgaff.com"}
|
||||
|
||||
# 处理SPA路由(如果需要)
|
||||
# 重定向规则
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 404
|
||||
status = 200
|
||||
|
||||
# 安全头部
|
||||
# 头部设置
|
||||
[[headers]]
|
||||
for = "/*"
|
||||
[headers.values]
|
||||
# 安全头部
|
||||
X-Frame-Options = "DENY"
|
||||
X-XSS-Protection = "1; mode=block"
|
||||
X-Content-Type-Options = "nosniff"
|
||||
Referrer-Policy = "strict-origin-when-cross-origin"
|
||||
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; img-src 'self' data: https: http:; connect-src 'self' https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com; font-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com;"
|
||||
|
||||
# 缓存控制
|
||||
Cache-Control = "public, max-age=31536000"
|
||||
|
||||
# 内容安全策略
|
||||
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data:; connect-src 'self' https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com; img-src 'self' data: https:; frame-src 'none';"
|
||||
|
||||
# 特定文件的头部设置
|
||||
[[headers]]
|
||||
for = "*.html"
|
||||
[headers.values]
|
||||
Cache-Control = "public, max-age=0, must-revalidate"
|
||||
|
||||
[[headers]]
|
||||
for = "*.css"
|
||||
[headers.values]
|
||||
Cache-Control = "public, max-age=31536000, immutable"
|
||||
|
||||
[[headers]]
|
||||
for = "*.js"
|
||||
[headers.values]
|
||||
Cache-Control = "public, max-age=31536000, immutable"
|
||||
|
||||
[[headers]]
|
||||
for = "*.woff2"
|
||||
[headers.values]
|
||||
Cache-Control = "public, max-age=31536000, immutable"
|
||||
|
||||
# 函数配置(如果需要)
|
||||
[functions]
|
||||
directory = "netlify/functions"
|
||||
@@ -15,7 +15,9 @@
|
||||
"deploy": "npm run build && netlify deploy --prod",
|
||||
"optimize-images": "node scripts/optimize-images.js",
|
||||
"compress": "node scripts/compress.js",
|
||||
"security-check": "node scripts/security-check.js"
|
||||
"security-check": "node scripts/security-check.js",
|
||||
"deploy-prepare": "node scripts/deploy-prepare.js",
|
||||
"deploy-analyze": "node scripts/deploy-prepare.js"
|
||||
},
|
||||
"keywords": [
|
||||
"esim",
|
||||
|
||||
178
scripts/deploy-prepare.js
Normal file
178
scripts/deploy-prepare.js
Normal file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
console.log('🚀 准备Netlify部署...');
|
||||
|
||||
// 定义要保留的文件和目录
|
||||
const keepFiles = [
|
||||
'index.html',
|
||||
'src/',
|
||||
'netlify/',
|
||||
'sw.js',
|
||||
'README.md',
|
||||
'package.json',
|
||||
'netlify.toml',
|
||||
'.netlifyignore'
|
||||
];
|
||||
|
||||
// 定义要排除的文件和目录
|
||||
const excludeFiles = [
|
||||
'node_modules/',
|
||||
'scripts/',
|
||||
'tests/',
|
||||
'docs/',
|
||||
'webpack.config.js',
|
||||
'postcss.config.js',
|
||||
'.babelrc',
|
||||
'.env*',
|
||||
'env.example',
|
||||
'.git/',
|
||||
'.vscode/',
|
||||
'.idea/',
|
||||
'*.log',
|
||||
'*.tmp',
|
||||
'*.temp',
|
||||
'*.cache',
|
||||
'dist/',
|
||||
'build/',
|
||||
'out/',
|
||||
'.DS_Store',
|
||||
'Thumbs.db'
|
||||
];
|
||||
|
||||
function shouldKeepFile(filePath) {
|
||||
// 检查是否在保留列表中
|
||||
for (const keepFile of keepFiles) {
|
||||
if (filePath.startsWith(keepFile) || filePath === keepFile) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否在排除列表中
|
||||
for (const excludeFile of excludeFiles) {
|
||||
if (filePath.includes(excludeFile) || filePath.endsWith(excludeFile.replace('/', ''))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getFileSize(filePath) {
|
||||
try {
|
||||
const stats = fs.statSync(filePath);
|
||||
return stats.size;
|
||||
} catch (error) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function analyzeDeployment() {
|
||||
console.log('\n📊 分析部署文件...');
|
||||
|
||||
let totalFiles = 0;
|
||||
let totalSize = 0;
|
||||
let keptFiles = 0;
|
||||
let keptSize = 0;
|
||||
|
||||
function scanDirectory(dir) {
|
||||
const items = fs.readdirSync(dir);
|
||||
|
||||
for (const item of items) {
|
||||
const fullPath = path.join(dir, item);
|
||||
const relativePath = path.relative('.', fullPath);
|
||||
|
||||
if (fs.statSync(fullPath).isDirectory()) {
|
||||
scanDirectory(fullPath);
|
||||
} else {
|
||||
totalFiles++;
|
||||
const size = getFileSize(fullPath);
|
||||
totalSize += size;
|
||||
|
||||
if (shouldKeepFile(relativePath)) {
|
||||
keptFiles++;
|
||||
keptSize += size;
|
||||
console.log(`✅ 保留: ${relativePath} (${formatFileSize(size)})`);
|
||||
} else {
|
||||
console.log(`❌ 排除: ${relativePath} (${formatFileSize(size)})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
scanDirectory('.');
|
||||
} catch (error) {
|
||||
console.log('⚠️ 扫描目录时出错:', error.message);
|
||||
}
|
||||
|
||||
console.log('\n📈 部署统计:');
|
||||
console.log(`总文件数: ${totalFiles}`);
|
||||
console.log(`总大小: ${formatFileSize(totalSize)}`);
|
||||
console.log(`保留文件数: ${keptFiles}`);
|
||||
console.log(`保留大小: ${formatFileSize(keptSize)}`);
|
||||
console.log(`排除文件数: ${totalFiles - keptFiles}`);
|
||||
console.log(`排除大小: ${formatFileSize(totalSize - keptSize)}`);
|
||||
console.log(`压缩率: ${((1 - keptSize / totalSize) * 100).toFixed(2)}%`);
|
||||
}
|
||||
|
||||
function createDeploymentManifest() {
|
||||
console.log('\n📝 创建部署清单...');
|
||||
|
||||
const manifest = {
|
||||
timestamp: new Date().toISOString(),
|
||||
files: [],
|
||||
stats: {
|
||||
totalFiles: 0,
|
||||
totalSize: 0
|
||||
}
|
||||
};
|
||||
|
||||
function scanForManifest(dir) {
|
||||
const items = fs.readdirSync(dir);
|
||||
|
||||
for (const item of items) {
|
||||
const fullPath = path.join(dir, item);
|
||||
const relativePath = path.relative('.', fullPath);
|
||||
|
||||
if (fs.statSync(fullPath).isDirectory()) {
|
||||
scanForManifest(fullPath);
|
||||
} else if (shouldKeepFile(relativePath)) {
|
||||
const size = getFileSize(fullPath);
|
||||
manifest.files.push({
|
||||
path: relativePath,
|
||||
size: size,
|
||||
sizeFormatted: formatFileSize(size)
|
||||
});
|
||||
manifest.stats.totalFiles++;
|
||||
manifest.stats.totalSize += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
scanForManifest('.');
|
||||
fs.writeFileSync('deployment-manifest.json', JSON.stringify(manifest, null, 2));
|
||||
console.log('✅ 部署清单已创建: deployment-manifest.json');
|
||||
} catch (error) {
|
||||
console.log('❌ 创建部署清单失败:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行分析
|
||||
analyzeDeployment();
|
||||
createDeploymentManifest();
|
||||
|
||||
console.log('\n🎉 部署准备完成!');
|
||||
console.log('💡 提示: 确保 .netlifyignore 文件已正确配置');
|
||||
console.log('🔗 部署链接: https://app.netlify.com/');
|
||||
Reference in New Issue
Block a user