next框架打包.next文件夹部署

前端小小白,刚开始使用AI辅助编程前端项目,使用的是React框架,让AI实现功能的时候它使用到了动态路由,我目前的理解就是将一个单传的前端项目变成了全栈前后端一体的项目,导致npm build执行完之后并没有生成期望的dist文件夹或output文件夹,而是将所有内容打包到了.next文件夹中,并且不只是单纯的路径变化,这种打包方式没有生成静态页面入口,而是打出来了一个server.js文件作为入口,连静态页面都没部署过的我,真的被难死了。还好,claude大法好,我不断提问和测试,终究还是解决了,记录一下解决方案。

部署方案:使用 standalone 模式

第一步:本地构建

在你的本地项目目录执行:

bash 复制代码
npm run build

构建完成后,你会看到:

javascript 复制代码
✓ Compiled successfully
✓ Linting and checking validity of types
✓ Collecting page data
✓ Generating static pages
✓ Finalizing page optimization

并且项目路径下会有.next文件夹

第二步:准备部署文件

构建成功后,需要准备以下文件:

javascript 复制代码
部署包结构:
├── server.js              # 来自 .next/standalone/server.js
├── package.json           # 来自 .next/standalone/package.json  
├── .next/
│   └── server/           # 来自 .next/server/
│   └── static/           # 来自 .next/static/
│   └── xxx               # 来自 .next下其他文件
└── public/               # 来自根目录的 public/

第三步:打包上传

使用 PowerShell 脚本

创建 package-deploy.ps1

powershell 复制代码
Write-Host "正在打包部署文件..." -ForegroundColor Green

# 创建临时目录
if (Test-Path deploy-temp) { Remove-Item -Recurse -Force deploy-temp }
New-Item -ItemType Directory -Path deploy-temp | Out-Null

# 复制文件
Write-Host "复制 standalone 文件..." -ForegroundColor Yellow
Copy-Item -Path ".next/standalone/*" -Destination "deploy-temp/" -Recurse -Force

Write-Host "复制 static 文件..." -ForegroundColor Yellow
New-Item -ItemType Directory -Path "deploy-temp/.next" -Force | Out-Null
Copy-Item -Path ".next/static" -Destination "deploy-temp/.next/" -Recurse -Force

Write-Host "复制 public 文件..." -ForegroundColor Yellow
Copy-Item -Path "public" -Destination "deploy-temp/" -Recurse -Force

# 创建压缩包
Write-Host "创建 deploy.zip..." -ForegroundColor Yellow
Compress-Archive -Path "deploy-temp/*" -DestinationPath "deploy.zip" -Force

# 清理
Remove-Item -Recurse -Force deploy-temp

Write-Host "打包完成!文件: deploy.zip" -ForegroundColor Green
Write-Host "文件大小: $((Get-Item deploy.zip).Length / 1MB) MB" -ForegroundColor Cyan

运行:

bash 复制代码
powershell -ExecutionPolicy Bypass -File package-deploy.ps1

第四步:服务器部署

1. 上传文件到服务器
bash 复制代码
# 使用 scp 上传(Linux/Mac)
scp deploy.zip user@your-server:/path/to/app/

# 或使用 WinSCP、FileZilla 等工具
2. 在服务器上解压并运行
bash 复制代码
# SSH 登录服务器
ssh user@your-server

# 进入应用目录
cd /path/to/app

# 解压文件
unzip deploy.zip

# 查看文件结构(确认正确)
ls -la
# 应该看到:server.js, package.json, .next/, public/

# 直接运行(测试)
HOSTNAME=0.0.0.0 PORT=3889 node server.js

# 或使用 PM2(生产环境推荐)
HOSTNAME=0.0.0.0 PORT=3889 pm2 start server.js --name your-app
pm2 save
pm2 startup

直接运行成功显示如下: 使用 PM2 运行成功显示如下: 成功后可以使用pm2 status查看状态:

PM命令

  • 停止并删除错误的进程
bash 复制代码
pm2 stop your-app
pm2 delete your-app
  • 查看 PM2 状态
shell 复制代码
pm2 status
  • 查看错误日志
shell 复制代码
pm2 logs your-app --err --lines 50
  • 查看所有日志
shell 复制代码
pm2 logs wps-app --lines 50
  • 查看进程详情
shell 复制代码
pm2 show your-app

全自动,解放双手

按照目前的部署方式,每次都有一步步手动操作,麻烦且容易出错,所以编写一个自动化脚本,保证不出错情况下解放双手!

  • 创建部署应用相关配置文件deploy-config.json

    json 复制代码
    {
      "server": {
        "host": "192.168.41.11",
        "user": "root",
        "port": 22,
        "deployPath": "/opt/module/wps/test3"
      },
      "app": {
        "name": "your-app",
        "port": 3889,
        "pm2Name": "your-app"
      },
      "build": {
        "command": "npm run build",
        "outputDir": ".next"
      }
    }
  • 打包部署脚本 该脚本是powershell脚本,在windows环境运行,xxx.ps1,脚本执行需要依赖deploy-config.json

    shell 复制代码
    # ====================================
    # Next.js Standalone Auto Deploy Script (Windows PowerShell)
    # ====================================
    
    # Stop on error
    $ErrorActionPreference = "Stop"
    
    # Read configuration file
    Write-Host "=====================================" -ForegroundColor Cyan
    Write-Host "  Next.js Auto Deploy Script" -ForegroundColor Cyan
    Write-Host "=====================================" -ForegroundColor Cyan
    Write-Host ""
    
    if (-not (Test-Path "deploy-config.json")) {
        Write-Host "Error: deploy-config.json not found" -ForegroundColor Red
        Write-Host "Please create configuration file first" -ForegroundColor Yellow
        exit 1
    }
    
    $config = Get-Content "deploy-config.json" | ConvertFrom-Json
    
    Write-Host "Deploy Configuration:" -ForegroundColor Green
    Write-Host "  Server: $($config.server.user)@$($config.server.host)" -ForegroundColor White
    Write-Host "  Path: $($config.server.deployPath)" -ForegroundColor White
    Write-Host "  Port: $($config.app.port)" -ForegroundColor White
    Write-Host ""
    
    # Confirm deployment
    $confirm = Read-Host "Continue with deployment? (y/n)"
    if ($confirm -ne "y" -and $confirm -ne "Y") {
        Write-Host "Deployment cancelled" -ForegroundColor Yellow
        exit 0
    }
    
    Write-Host ""
    
    # ====================================
    # Step 1: Build Project
    # ====================================
    Write-Host "=====================================" -ForegroundColor Cyan
    Write-Host "Step 1/5: Build Project" -ForegroundColor Cyan
    Write-Host "=====================================" -ForegroundColor Cyan
    
    try {
        Write-Host "Executing: $($config.build.command)" -ForegroundColor Yellow
        Invoke-Expression $config.build.command
        
        if ($LASTEXITCODE -ne 0) {
            throw "Build failed"
        }
        
        Write-Host "Build successful" -ForegroundColor Green
        Write-Host ""
    } catch {
        Write-Host "Build failed: $_" -ForegroundColor Red
        exit 1
    }
    
    # ====================================
    # Step 2: Package Files
    # ====================================
    Write-Host "=====================================" -ForegroundColor Cyan
    Write-Host "Step 2/5: Package Files" -ForegroundColor Cyan
    Write-Host "=====================================" -ForegroundColor Cyan
    
    try {
        # Create temp directory
        $tempDir = "deploy-temp"
        if (Test-Path $tempDir) {
            Remove-Item -Recurse -Force $tempDir
        }
        New-Item -ItemType Directory -Path $tempDir | Out-Null
        
        # Copy standalone files
        Write-Host "Copying standalone files..." -ForegroundColor Yellow
        $standalonePath = ".next/standalone"
        if (-not (Test-Path $standalonePath)) {
            throw "Cannot find .next/standalone directory. Please ensure next.config.ts has output: 'standalone'"
        }
        Copy-Item -Path "$standalonePath/*" -Destination $tempDir -Recurse -Force
        
        # Copy static files
        Write-Host "Copying static files..." -ForegroundColor Yellow
        $staticPath = ".next/static"
        if (Test-Path $staticPath) {
            $nextDir = Join-Path $tempDir ".next"
            if (-not (Test-Path $nextDir)) {
                New-Item -ItemType Directory -Path $nextDir | Out-Null
            }
            Copy-Item -Path $staticPath -Destination $nextDir -Recurse -Force
        }
        
        # Copy public files
        Write-Host "Copying public files..." -ForegroundColor Yellow
        if (Test-Path "public") {
            Copy-Item -Path "public" -Destination $tempDir -Recurse -Force
        }
        
        # Create archive
        Write-Host "Creating deploy.zip..." -ForegroundColor Yellow
        $zipPath = "deploy.zip"
        if (Test-Path $zipPath) {
            Remove-Item -Force $zipPath
        }
        Compress-Archive -Path "$tempDir/*" -DestinationPath $zipPath -Force
        
        $zipSize = [math]::Round((Get-Item $zipPath).Length / 1MB, 2)
        Write-Host "Package successful (Size: $zipSize MB)" -ForegroundColor Green
        Write-Host ""
        
        # Cleanup temp directory
        Remove-Item -Recurse -Force $tempDir
    } catch {
        Write-Host "Package failed: $_" -ForegroundColor Red
        if (Test-Path $tempDir) {
            Remove-Item -Recurse -Force $tempDir
        }
        exit 1
    }
    
    # ====================================
    # Step 3: Upload to Server
    # ====================================
    Write-Host "=====================================" -ForegroundColor Cyan
    Write-Host "Step 3/5: Upload to Server" -ForegroundColor Cyan
    Write-Host "=====================================" -ForegroundColor Cyan
    
    # Check if scp is available
    $scpTest = Get-Command scp -ErrorAction SilentlyContinue
    if (-not $scpTest) {
        Write-Host "Error: scp command not found. Please install OpenSSH client." -ForegroundColor Red
        exit 1
    }
    
    $uploadSuccess = $false
    $maxRetries = 3
    $retryCount = 0
    
    while (-not $uploadSuccess -and $retryCount -lt $maxRetries) {
        try {
            if ($retryCount -gt 0) {
                Write-Host ""
                Write-Host "Retry attempt $retryCount of $($maxRetries - 1)..." -ForegroundColor Yellow
            }
            
            Write-Host "Uploading to $($config.server.host)..." -ForegroundColor Yellow
            
            $scpTarget = "$($config.server.user)@$($config.server.host):$($config.server.deployPath)/deploy.zip"
            
            # Upload file
            & scp -P $config.server.port deploy.zip $scpTarget
            
            if ($LASTEXITCODE -eq 0) {
                $uploadSuccess = $true
                Write-Host "Upload successful" -ForegroundColor Green
                Write-Host ""
            } else {
                $retryCount++
                if ($retryCount -lt $maxRetries) {
                    Write-Host "Upload failed. Please check password and try again." -ForegroundColor Yellow
                }
            }
        } catch {
            $retryCount++
            if ($retryCount -lt $maxRetries) {
                Write-Host "Upload failed: $_" -ForegroundColor Red
                Write-Host "Please try again..." -ForegroundColor Yellow
            }
        }
    }
    
    if (-not $uploadSuccess) {
        Write-Host ""
        Write-Host "Upload failed after $maxRetries attempts" -ForegroundColor Red
        Write-Host ""
        Write-Host "Tips:" -ForegroundColor Yellow
        Write-Host "  1. Check if server address and port are correct" -ForegroundColor Yellow
        Write-Host "  2. Verify your password" -ForegroundColor Yellow
        Write-Host "  3. Consider setting up SSH key authentication" -ForegroundColor Yellow
        exit 1
    }
    
    # ====================================
    # Step 4: Extract Files
    # ====================================
    Write-Host "=====================================" -ForegroundColor Cyan
    Write-Host "Step 4/5: Extract Files" -ForegroundColor Cyan
    Write-Host "=====================================" -ForegroundColor Cyan
    
    Write-Host "Extracting files on server..." -ForegroundColor Yellow
    
    $sshTarget = "$($config.server.user)@$($config.server.host)"
    $deployPath = $config.server.deployPath
    $pm2Name = $config.app.pm2Name
    $port = $config.app.port
    
    # Step 1: Extract files
    & ssh -p $config.server.port $sshTarget "cd $deployPath && unzip -o deploy.zip && rm deploy.zip"
    Write-Host "Files extracted" -ForegroundColor Green
    Write-Host ""
    
    # ====================================
    # Step 5: Start Application
    # ====================================
    Write-Host "=====================================" -ForegroundColor Cyan
    Write-Host "Step 5/5: Start Application" -ForegroundColor Cyan
    Write-Host "=====================================" -ForegroundColor Cyan
    
    Write-Host "Starting application with PM2..." -ForegroundColor Yellow
    
    # Step 2: Stop old process
    & ssh -p $config.server.port $sshTarget "pm2 stop $pm2Name 2>/dev/null; pm2 delete $pm2Name 2>/dev/null; true"
    
    # Step 3: Start new process with HOSTNAME=0.0.0.0 to fix IPv6 listening issue
    & ssh -p $config.server.port $sshTarget "cd $deployPath && HOSTNAME=0.0.0.0 PORT=$port pm2 start server.js --name $pm2Name"
    
    # Step 4: Save PM2 config
    & ssh -p $config.server.port $sshTarget "pm2 save"
    
    Write-Host ""
    Write-Host "Verifying application status..." -ForegroundColor Yellow
    
    # Verify deployment
    & ssh -p $config.server.port $sshTarget "pm2 list"
    
    Write-Host ""
    Write-Host "Application started" -ForegroundColor Green
    Write-Host ""
    
    # ====================================
    # Complete
    # ====================================
    Write-Host "=====================================" -ForegroundColor Green
    Write-Host "  Deployment Successful!" -ForegroundColor Green
    Write-Host "=====================================" -ForegroundColor Green
    Write-Host ""
    Write-Host "Application Info:" -ForegroundColor Cyan
    Write-Host "  URL: http://$($config.server.host):$($config.app.port)" -ForegroundColor White
    Write-Host "  PM2 Name: $($config.app.pm2Name)" -ForegroundColor White
    Write-Host ""
    Write-Host "Common Commands:" -ForegroundColor Cyan
    Write-Host "  View logs: ssh $($config.server.user)@$($config.server.host) 'pm2 logs $($config.app.pm2Name)'" -ForegroundColor White
    Write-Host "  View status: ssh $($config.server.user)@$($config.server.host) 'pm2 status'" -ForegroundColor White
    Write-Host "  Restart app: ssh $($config.server.user)@$($config.server.host) 'pm2 restart $($config.app.pm2Name)'" -ForegroundColor White
    Write-Host ""
    
    # Cleanup local files
    if (Test-Path "deploy.zip") {
        Remove-Item -Force "deploy.zip"
    }
    
    Write-Host "Press any key to exit..."
    $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')

圆满,大功告成!

相关推荐
程序猿小蒜2 小时前
基于springboot的校园社团信息管理系统开发与设计
java·前端·spring boot·后端·spring
一叶难遮天2 小时前
开启RN之旅——前端基础
前端·javascript·promise·js基础·es6/ts·npm/nrm
申阳2 小时前
Day 4:02. 基于Nuxt开发博客项目-整合 Inspira UI
前端·后端·程序员
程序猿_极客2 小时前
【期末网页设计作业】HTML+CSS+JavaScript 猫咪主题网站开发(附源码与效果演示)
前端·css·html·课程设计·网页设计作业
IT古董2 小时前
【前端】从零开始搭建现代前端框架:React 19、Vite、Tailwind CSS、ShadCN UI 完整实战教程-第1章:项目概述与技术栈介绍
前端·react.js·前端框架
有点笨的蛋2 小时前
从零搭建小程序首页:新手也能看懂的结构解析与实战指南
前端·微信小程序
爱宇阳2 小时前
Vue3 前端项目 Docker 容器化部署教程
前端·docker·容器
Irene19912 小时前
前端缓存技术和使用场景
前端·缓存
是你的小橘呀3 小时前
深入解析 JavaScript 引擎与作用域机制
前端·javascript