From 312660c41f9dfdeafe80770cbdbb499fe25e070e Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 11 Aug 2026 01:03:46 +0800 Subject: [PATCH] =?UTF-8?q?chore(gerp):=20deploy.ps1=20=E8=BD=AC=E7=BA=AF?= =?UTF-8?q?=20ASCII=20=E6=B6=88=E9=99=A4=20BOM=20=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PS 5.1 无 BOM 时按 ANSI 代码页解析 UTF-8 文件,中文会乱码导致语法错误; 保留 BOM 又会触发首行 "'#' 不是 cmdlet" 警告 - 脚本注释与输出改为英文(纯 ASCII),无 BOM 下可被 PS 5.1 正确解析 - 头部注释注明须保持 ASCII 以防回归 --- deploy.ps1 | 212 +++++++++++++++++++++++++++-------------------------- 1 file changed, 107 insertions(+), 105 deletions(-) diff --git a/deploy.ps1 b/deploy.ps1 index 4bfcbab..faf3788 100644 --- a/deploy.ps1 +++ b/deploy.ps1 @@ -1,105 +1,107 @@ -# 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 +# GERP frontend deploy script: build and sync dist to production dir (TempLate/GERP) +# +# IMPORTANT: keep this file pure ASCII. PS 5.1 parses BOM-less UTF-8 files +# using the ANSI codepage, so non-ASCII text would be garbled. +# +# Usage: +# 1. Clean old artifacts (dist and TempLate/GERP/assets) so no stale hashes remain +# 2. Full rebuild (vue-tsc type check + vite build) +# 3. Sync dist to TempLate/GERP (index.html + assets) +# 4. Verify TempLate matches dist exactly +# +# Run: .\deploy.ps1 +# (if execution policy blocks: Set-ExecutionPolicy -Scope Process Bypass) + +$ErrorActionPreference = 'Stop' + +$ProjectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path +$DistDir = Join-Path $ProjectRoot 'dist' +$ProdRoot = Join-Path (Split-Path -Parent $ProjectRoot) 'TempLate\GERP' +$ProdAssetsDir = Join-Path $ProdRoot 'assets' +$IndexHtml = Join-Path $ProdRoot 'index.html' + +Write-Host "`n===== GERP DEPLOY START =====" -ForegroundColor Cyan +Write-Host "Project dir : $ProjectRoot" +Write-Host "Prod dir : $ProdRoot" +Write-Host "" + +# 1. Clean old artifacts +Write-Host '[1/4] Cleaning old build artifacts...' -ForegroundColor Yellow +if (Test-Path $DistDir) { + Remove-Item -Recurse -Force $DistDir + Write-Host " removed: $DistDir" +} +if (Test-Path $ProdAssetsDir) { + Remove-Item -Recurse -Force $ProdAssetsDir + Write-Host " removed: $ProdAssetsDir" +} +if (Test-Path $IndexHtml) { + Remove-Item -Force $IndexHtml + Write-Host " removed: $IndexHtml" +} +Write-Host '' + +# 2. Full build (vue-tsc type check + vite build) +Write-Host '[2/4] Running npm run build (type check + full build)...' -ForegroundColor Yellow +Push-Location $ProjectRoot +try { + npm run build + if ($LASTEXITCODE -ne 0) { + throw "Build failed, exit code = $LASTEXITCODE" + } +} finally { + Pop-Location +} +Write-Host ' Build OK' +Write-Host '' + +# 3. Sync artifacts to prod dir +Write-Host '[3/4] Syncing artifacts to prod dir...' -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 ' Sync done' +Write-Host '' + +# 4. Verify prod dir matches dist (file name sets) +Write-Host '[4/4] Verifying artifact consistency...' -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 " OK: $($distSet.Count) assets, prod matches dist exactly" -ForegroundColor Green +} else { + Write-Host ' MISMATCH:' -ForegroundColor Red + if ($onlyDist.Count) { Write-Host " only in dist: $onlyDist" -ForegroundColor Red } + if ($onlyProd.Count) { Write-Host " only in prod: $onlyProd" -ForegroundColor Red } + throw 'Artifact verification failed!' +} + +# Verify the entry JS referenced by index.html exists +$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 " entry JS OK: $($entryMatch.Groups[1].Value)" -ForegroundColor Green + } else { + throw "index.html entry JS not found: $entryPath" + } +} else { + throw 'No entry JS reference found in index.html' +} + +Write-Host '' +Write-Host "===== GERP DEPLOY DONE =====" -ForegroundColor Cyan +Write-Host 'Please hard-refresh the browser (Ctrl+F5) to load the new build.' -ForegroundColor Cyan