106 lines
4.2 KiB
PowerShell
106 lines
4.2 KiB
PowerShell
# GERP 前端部署脚本:全量编译并同步产物到生产目录(TempLate/GERP)
|
||
#
|
||
# 用途:
|
||
# 1. 清理旧构建产物(dist 与 TempLate/GERP/assets),保证无 hash 残留
|
||
# 2. 全量重新构建(vue-tsc 类型检查 + vite build)
|
||
# 3. 同步 dist 产物到 TempLate/GERP(index.html + assets)
|
||
# 4. 校验 TempLate 与 dist 完全一致
|
||
#
|
||
# 用法:
|
||
# PowerShell 中执行: .\deploy.ps1
|
||
# (若报执行策略限制: Set-ExecutionPolicy -Scope Process Bypass 后再执行)
|
||
|
||
$ErrorActionPreference = 'Stop'
|
||
|
||
$ProjectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path # d:\SMANAGE\GERP
|
||
$DistDir = Join-Path $ProjectRoot 'dist'
|
||
$ProdRoot = Join-Path (Split-Path -Parent $ProjectRoot) 'TempLate\GERP' # d:\SMANAGE\TempLate\GERP
|
||
$ProdAssetsDir = Join-Path $ProdRoot 'assets'
|
||
$IndexHtml = Join-Path $ProdRoot 'index.html'
|
||
|
||
Write-Host "`n===== GERP 部署开始 =====" -ForegroundColor Cyan
|
||
Write-Host "工程目录: $ProjectRoot"
|
||
Write-Host "生产目录: $ProdRoot"
|
||
Write-Host ""
|
||
|
||
# 1. 清理旧产物(dist + 生产 assets),保证全量构建无 hash 残留
|
||
Write-Host '[1/4] 清理旧构建产物...' -ForegroundColor Yellow
|
||
if (Test-Path $DistDir) {
|
||
Remove-Item -Recurse -Force $DistDir
|
||
Write-Host " 已删除: $DistDir"
|
||
}
|
||
if (Test-Path $ProdAssetsDir) {
|
||
Remove-Item -Recurse -Force $ProdAssetsDir
|
||
Write-Host " 已删除: $ProdAssetsDir"
|
||
}
|
||
if (Test-Path $IndexHtml) {
|
||
Remove-Item -Force $IndexHtml
|
||
Write-Host " 已删除: $IndexHtml"
|
||
}
|
||
Write-Host ''
|
||
|
||
# 2. 全量构建(vue-tsc 类型检查 + vite build)
|
||
Write-Host '[2/4] 执行 npm run build(类型检查 + 全量编译)...' -ForegroundColor Yellow
|
||
Push-Location $ProjectRoot
|
||
try {
|
||
npm run build
|
||
if ($LASTEXITCODE -ne 0) {
|
||
throw "构建失败,exit code = $LASTEXITCODE"
|
||
}
|
||
} finally {
|
||
Pop-Location
|
||
}
|
||
Write-Host ' 构建成功'
|
||
Write-Host ''
|
||
|
||
# 3. 同步产物到生产目录
|
||
Write-Host '[3/4] 同步产物到生产目录...' -ForegroundColor Yellow
|
||
if (-not (Test-Path $ProdRoot)) {
|
||
New-Item -ItemType Directory -Path $ProdRoot -Force | Out-Null
|
||
}
|
||
Copy-Item -Recurse -Force (Join-Path $DistDir '*') $ProdRoot
|
||
Copy-Item -Force (Join-Path $DistDir 'index.html') $IndexHtml
|
||
Write-Host ' 同步完成'
|
||
Write-Host ''
|
||
|
||
# 4. 校验生产目录与 dist 完全一致(文件名集合)
|
||
Write-Host '[4/4] 校验产物一致性...' -ForegroundColor Yellow
|
||
function Get-AssetNames([string]$dir) {
|
||
if (-not (Test-Path $dir)) { return @() }
|
||
return @(Get-ChildItem -Path $dir -Recurse -File | ForEach-Object { $_.FullName.Substring($dir.Length) })
|
||
}
|
||
$distNames = Get-AssetNames (Join-Path $DistDir 'assets')
|
||
$prodNames = Get-AssetNames $ProdAssetsDir
|
||
$distSet = @($distNames | Sort-Object -Unique)
|
||
$prodSet = @($prodNames | Sort-Object -Unique)
|
||
|
||
$onlyDist = @($distSet | Where-Object { $_ -notin $prodSet })
|
||
$onlyProd = @($prodSet | Where-Object { $_ -notin $distSet })
|
||
|
||
if ($onlyDist.Count -eq 0 -and $onlyProd.Count -eq 0) {
|
||
Write-Host " 校验通过: assets 文件数 $($distSet.Count) 个,生产与 dist 完全一致" -ForegroundColor Green
|
||
} else {
|
||
Write-Host ' 校验异常:' -ForegroundColor Red
|
||
if ($onlyDist.Count) { Write-Host " 仅在 dist : $onlyDist" -ForegroundColor Red }
|
||
if ($onlyProd.Count) { Write-Host " 仅在生产: $onlyProd" -ForegroundColor Red }
|
||
throw '产物校验失败,请检查!'
|
||
}
|
||
|
||
# 校验 index.html 引用的入口 JS 存在
|
||
$indexContent = Get-Content $IndexHtml -Raw
|
||
$entryMatch = [regex]::Match($indexContent, 'src="([^"]+\.js)"')
|
||
if ($entryMatch.Success) {
|
||
$entryPath = Join-Path $ProdRoot ($entryMatch.Groups[1].Value.TrimStart('/'))
|
||
if (Test-Path $entryPath) {
|
||
Write-Host " 入口 JS 校验通过: $($entryMatch.Groups[1].Value)" -ForegroundColor Green
|
||
} else {
|
||
throw "index.html 引用的入口 JS 不存在: $entryPath"
|
||
}
|
||
} else {
|
||
throw 'index.html 中未找到入口 JS 引用'
|
||
}
|
||
|
||
Write-Host ''
|
||
Write-Host "===== GERP 部署完成 =====" -ForegroundColor Cyan
|
||
Write-Host '请浏览器强制刷新(Ctrl+F5)加载新产物。' -ForegroundColor Cyan
|