mirror of
https://github.com/MatrixSeven/file-transfer-go.git
synced 2026-02-04 03:25:03 +08:00
416 lines
10 KiB
Bash
416 lines
10 KiB
Bash
#!/bin/bash
|
||
|
||
# =============================================================================
|
||
# Next.js SSG 静态导出构建脚本
|
||
#
|
||
# 功能:
|
||
# 1. 自动备份和移除 API 路由
|
||
# 2. 临时修改配置文件以支持静态导出
|
||
# 3. 执行静态构建
|
||
# 4. 恢复所有文件到原始状态
|
||
#
|
||
# 使用方法:
|
||
# ./build-ssg.sh [options]
|
||
#
|
||
# 选项:
|
||
# --clean 清理之前的构建文件
|
||
# --verbose 显示详细输出
|
||
# --help 显示帮助信息
|
||
# =============================================================================
|
||
|
||
set -e # 遇到错误立即退出
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 配置变量
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$SCRIPT_DIR"
|
||
BACKUP_DIR="/tmp/nextjs-ssg-backup-$(date +%s)"
|
||
API_DIR="$PROJECT_ROOT/src/app/api"
|
||
BUILD_DIR="$PROJECT_ROOT/.next"
|
||
OUT_DIR="$PROJECT_ROOT/out"
|
||
|
||
# 标志变量
|
||
VERBOSE=false
|
||
CLEAN=false
|
||
BACKUP_CREATED=false
|
||
|
||
# 函数:打印带颜色的消息
|
||
print_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
}
|
||
|
||
print_verbose() {
|
||
if [ "$VERBOSE" = true ]; then
|
||
echo -e "${BLUE}[VERBOSE]${NC} $1"
|
||
fi
|
||
}
|
||
|
||
# 函数:显示帮助信息
|
||
show_help() {
|
||
cat << EOF
|
||
Next.js SSG 静态导出构建脚本
|
||
|
||
使用方法:
|
||
$0 [选项]
|
||
|
||
选项:
|
||
--clean 清理之前的构建文件 (.next, out)
|
||
--verbose 显示详细输出信息
|
||
--help 显示此帮助信息
|
||
|
||
示例:
|
||
$0 # 标准静态构建
|
||
$0 --clean # 清理后构建
|
||
$0 --verbose # 详细模式构建
|
||
$0 --clean --verbose # 清理后详细模式构建
|
||
|
||
注意:
|
||
- 此脚本会临时移除 API 路由以支持静态导出
|
||
- 构建完成后会自动恢复所有文件
|
||
- 如果脚本被中断,请手动运行恢复函数
|
||
|
||
EOF
|
||
}
|
||
|
||
# 函数:解析命令行参数
|
||
parse_args() {
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--clean)
|
||
CLEAN=true
|
||
shift
|
||
;;
|
||
--verbose)
|
||
VERBOSE=true
|
||
shift
|
||
;;
|
||
--help)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
*)
|
||
print_error "未知选项: $1"
|
||
show_help
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# 函数:检查必要的工具
|
||
check_requirements() {
|
||
print_info "检查构建环境..."
|
||
|
||
# 检查 Node.js
|
||
if ! command -v node &> /dev/null; then
|
||
print_error "Node.js 未安装"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查 yarn
|
||
if ! command -v yarn &> /dev/null; then
|
||
print_error "Yarn 未安装"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查 package.json
|
||
if [ ! -f "$PROJECT_ROOT/package.json" ]; then
|
||
print_error "package.json 不存在"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查 next.config.js
|
||
if [ ! -f "$PROJECT_ROOT/next.config.js" ]; then
|
||
print_error "next.config.js 不存在"
|
||
exit 1
|
||
fi
|
||
|
||
print_verbose "Node.js 版本: $(node --version)"
|
||
print_verbose "Yarn 版本: $(yarn --version)"
|
||
print_success "环境检查通过"
|
||
}
|
||
|
||
# 函数:清理构建文件
|
||
clean_build() {
|
||
if [ "$CLEAN" = true ]; then
|
||
print_info "清理之前的构建文件..."
|
||
|
||
if [ -d "$BUILD_DIR" ]; then
|
||
rm -rf "$BUILD_DIR"
|
||
print_verbose "已删除 .next 目录"
|
||
fi
|
||
|
||
if [ -d "$OUT_DIR" ]; then
|
||
rm -rf "$OUT_DIR"
|
||
print_verbose "已删除 out 目录"
|
||
fi
|
||
|
||
print_success "构建文件清理完成"
|
||
fi
|
||
}
|
||
|
||
# 函数:创建备份目录
|
||
create_backup_dir() {
|
||
print_info "创建备份目录: $BACKUP_DIR"
|
||
mkdir -p "$BACKUP_DIR"
|
||
BACKUP_CREATED=true
|
||
print_verbose "备份目录创建成功"
|
||
}
|
||
|
||
# 函数:备份 API 路由
|
||
backup_api_routes() {
|
||
if [ -d "$API_DIR" ]; then
|
||
print_info "备份 API 路由..."
|
||
cp -r "$API_DIR" "$BACKUP_DIR/"
|
||
print_verbose "API 路由已备份到: $BACKUP_DIR/api"
|
||
|
||
# 移除原始 API 目录
|
||
rm -rf "$API_DIR"
|
||
print_verbose "已移除原始 API 目录"
|
||
print_success "API 路由备份完成"
|
||
else
|
||
print_warning "API 目录不存在,跳过备份"
|
||
fi
|
||
}
|
||
|
||
# 函数:备份并修改配置文件
|
||
backup_and_modify_config() {
|
||
print_info "处理配置文件..."
|
||
|
||
# 备份 next.config.js
|
||
if [ -f "$PROJECT_ROOT/next.config.js" ]; then
|
||
cp "$PROJECT_ROOT/next.config.js" "$BACKUP_DIR/next.config.js.backup"
|
||
print_verbose "已备份 next.config.js"
|
||
fi
|
||
|
||
# 备份 package.json
|
||
if [ -f "$PROJECT_ROOT/package.json" ]; then
|
||
cp "$PROJECT_ROOT/package.json" "$BACKUP_DIR/package.json.backup"
|
||
print_verbose "已备份 package.json"
|
||
fi
|
||
|
||
# 备份环境变量文件(如果存在)
|
||
for env_file in ".env" ".env.local" ".env.production"; do
|
||
if [ -f "$PROJECT_ROOT/$env_file" ]; then
|
||
cp "$PROJECT_ROOT/$env_file" "$BACKUP_DIR/$env_file.backup"
|
||
print_verbose "已备份 $env_file"
|
||
fi
|
||
done
|
||
|
||
print_success "配置文件备份完成"
|
||
}
|
||
|
||
# 函数:设置构建环境变量
|
||
set_build_env() {
|
||
print_info "设置静态导出环境变量..."
|
||
|
||
# 创建临时的环境变量文件
|
||
cat > "$PROJECT_ROOT/.env.ssg" << EOF
|
||
# SSG 构建临时环境变量
|
||
NEXT_EXPORT=true
|
||
NODE_ENV=production
|
||
|
||
# 后端连接配置(用于静态模式 - 使用相对路径)
|
||
NEXT_PUBLIC_GO_BACKEND_URL=
|
||
NEXT_PUBLIC_WS_URL=
|
||
NEXT_PUBLIC_API_BASE_URL=
|
||
EOF
|
||
|
||
print_verbose "已创建 .env.ssg 文件"
|
||
print_success "环境变量设置完成"
|
||
}
|
||
|
||
# 函数:执行静态构建
|
||
run_static_build() {
|
||
print_info "开始静态导出构建..."
|
||
|
||
cd "$PROJECT_ROOT"
|
||
|
||
# 加载静态导出环境变量
|
||
if [ -f ".env.static" ]; then
|
||
print_info "加载静态导出环境变量..."
|
||
export $(cat .env.static | grep -v '^#' | xargs)
|
||
fi
|
||
|
||
# 设置环境变量并执行构建
|
||
if [ "$VERBOSE" = true ]; then
|
||
NEXT_EXPORT=true NODE_ENV=production NEXT_PUBLIC_BACKEND_URL= yarn build
|
||
else
|
||
NEXT_EXPORT=true NODE_ENV=production NEXT_PUBLIC_BACKEND_URL= yarn build > build.log 2>&1
|
||
if [ $? -ne 0 ]; then
|
||
print_error "构建失败,查看 build.log 获取详细信息"
|
||
cat build.log
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
print_success "静态构建完成"
|
||
}
|
||
|
||
# 函数:验证构建结果
|
||
verify_build() {
|
||
print_info "验证构建结果..."
|
||
|
||
if [ ! -d "$OUT_DIR" ]; then
|
||
print_error "输出目录 'out' 不存在"
|
||
return 1
|
||
fi
|
||
|
||
if [ ! -f "$OUT_DIR/index.html" ]; then
|
||
print_error "index.html 文件未生成"
|
||
return 1
|
||
fi
|
||
|
||
# 计算文件数量
|
||
file_count=$(find "$OUT_DIR" -type f | wc -l)
|
||
dir_size=$(du -sh "$OUT_DIR" | cut -f1)
|
||
|
||
print_success "构建验证通过"
|
||
print_info "输出文件数量: $file_count"
|
||
print_info "输出目录大小: $dir_size"
|
||
|
||
if [ "$VERBOSE" = true ]; then
|
||
print_verbose "输出目录结构:"
|
||
ls -la "$OUT_DIR"
|
||
fi
|
||
}
|
||
|
||
# 函数:恢复所有文件
|
||
restore_files() {
|
||
if [ "$BACKUP_CREATED" = true ] && [ -d "$BACKUP_DIR" ]; then
|
||
print_info "恢复备份文件..."
|
||
|
||
# 恢复 API 路由
|
||
if [ -d "$BACKUP_DIR/api" ]; then
|
||
mkdir -p "$(dirname "$API_DIR")"
|
||
cp -r "$BACKUP_DIR/api" "$API_DIR"
|
||
print_verbose "已恢复 API 路由"
|
||
fi
|
||
|
||
# 恢复配置文件
|
||
if [ -f "$BACKUP_DIR/next.config.js.backup" ]; then
|
||
cp "$BACKUP_DIR/next.config.js.backup" "$PROJECT_ROOT/next.config.js"
|
||
print_verbose "已恢复 next.config.js"
|
||
fi
|
||
|
||
if [ -f "$BACKUP_DIR/package.json.backup" ]; then
|
||
cp "$BACKUP_DIR/package.json.backup" "$PROJECT_ROOT/package.json"
|
||
print_verbose "已恢复 package.json"
|
||
fi
|
||
|
||
# 恢复环境变量文件
|
||
for env_file in ".env" ".env.local" ".env.production"; do
|
||
if [ -f "$BACKUP_DIR/$env_file.backup" ]; then
|
||
cp "$BACKUP_DIR/$env_file.backup" "$PROJECT_ROOT/$env_file"
|
||
print_verbose "已恢复 $env_file"
|
||
fi
|
||
done
|
||
|
||
print_success "文件恢复完成"
|
||
fi
|
||
}
|
||
|
||
# 函数:清理临时文件
|
||
cleanup() {
|
||
print_info "清理临时文件..."
|
||
|
||
# 删除临时环境变量文件
|
||
if [ -f "$PROJECT_ROOT/.env.ssg" ]; then
|
||
rm -f "$PROJECT_ROOT/.env.ssg"
|
||
print_verbose "已删除 .env.ssg"
|
||
fi
|
||
|
||
# 删除构建日志
|
||
if [ -f "$PROJECT_ROOT/build.log" ]; then
|
||
rm -f "$PROJECT_ROOT/build.log"
|
||
print_verbose "已删除 build.log"
|
||
fi
|
||
|
||
# 删除备份目录
|
||
if [ -d "$BACKUP_DIR" ]; then
|
||
rm -rf "$BACKUP_DIR"
|
||
print_verbose "已删除备份目录: $BACKUP_DIR"
|
||
fi
|
||
|
||
print_success "临时文件清理完成"
|
||
}
|
||
|
||
# 函数:错误处理和清理
|
||
error_cleanup() {
|
||
print_error "构建过程中发生错误,正在恢复..."
|
||
restore_files
|
||
cleanup
|
||
exit 1
|
||
}
|
||
|
||
# 函数:显示构建摘要
|
||
show_summary() {
|
||
print_success "🎉 SSG 静态导出构建完成!"
|
||
echo ""
|
||
print_info "📁 输出目录: $OUT_DIR"
|
||
print_info "🚀 部署方法:"
|
||
echo " - 将 'out' 目录上传到静态托管服务"
|
||
echo " - 或者使用: npx serve out"
|
||
echo ""
|
||
print_info "📋 构建统计:"
|
||
if [ -d "$OUT_DIR" ]; then
|
||
file_count=$(find "$OUT_DIR" -type f | wc -l)
|
||
dir_size=$(du -sh "$OUT_DIR" | cut -f1)
|
||
echo " - 文件数量: $file_count"
|
||
echo " - 总大小: $dir_size"
|
||
fi
|
||
echo ""
|
||
print_warning "⚠️ 注意: 静态版本不包含 API 路由,前端将直接连接到 Go 后端"
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
print_info "启动 Next.js SSG 静态导出构建..."
|
||
|
||
# 设置错误处理
|
||
trap error_cleanup ERR INT TERM
|
||
|
||
# 解析命令行参数
|
||
parse_args "$@"
|
||
|
||
# 执行构建步骤
|
||
check_requirements
|
||
clean_build
|
||
create_backup_dir
|
||
backup_api_routes
|
||
backup_and_modify_config
|
||
set_build_env
|
||
run_static_build
|
||
verify_build
|
||
|
||
# 恢复和清理
|
||
restore_files
|
||
cleanup
|
||
|
||
# 显示摘要
|
||
show_summary
|
||
}
|
||
|
||
# 如果脚本被直接执行(而不是被 source)
|
||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||
main "$@"
|
||
fi
|