mirror of
https://github.com/moeacgx/Telegram-Panel.git
synced 2026-05-22 04:14:22 +08:00
175 lines
7.0 KiB
PowerShell
175 lines
7.0 KiB
PowerShell
param(
|
||
[Parameter(Mandatory = $true)]
|
||
[string]$Project,
|
||
|
||
[Parameter(Mandatory = $true)]
|
||
[string]$Manifest,
|
||
|
||
[Parameter(Mandatory = $false)]
|
||
[string]$OutDir = "artifacts/modules",
|
||
|
||
# 轻量打包:剔除会由宿主共享加载的程序集(减少包体积)。
|
||
# 说明:宿主的 ModuleLoadContext 会强制让这些程序集由 Default ALC 解析,模块包携带它们只会徒增体积。
|
||
[Parameter(Mandatory = $false)]
|
||
[switch]$Slim,
|
||
|
||
# 更激进的轻量打包:额外剔除宿主已内置的第三方依赖(EFCore/Sqlite/WTelegramClient 等)与多平台 native runtimes。
|
||
# 适用场景:目标宿主就是 TelegramPanel 主程序(必带这些依赖),并且部署环境固定(例如 Docker linux-x64)。
|
||
[Parameter(Mandatory = $false)]
|
||
[switch]$SlimHost,
|
||
|
||
# 完整打包:不做任何剔除(体积更大,通常不推荐)。
|
||
# 说明:也可用 -Slim:$false -SlimHost:$false 达到同样效果。
|
||
[Parameter(Mandatory = $false)]
|
||
[switch]$Full
|
||
)
|
||
|
||
$ErrorActionPreference = "Stop"
|
||
|
||
if ($Full)
|
||
{
|
||
$Slim = $false
|
||
$SlimHost = $false
|
||
}
|
||
elseif (-not $PSBoundParameters.ContainsKey("Slim") -and -not $PSBoundParameters.ContainsKey("SlimHost"))
|
||
{
|
||
# 默认轻量化:未显式指定时,按宿主内置依赖(SlimHost)打包。
|
||
$SlimHost = $true
|
||
}
|
||
|
||
$repoRoot = (Resolve-Path ".").Path
|
||
$projectPath = Join-Path $repoRoot $Project
|
||
$manifestPath = Join-Path $repoRoot $Manifest
|
||
$outRoot = Join-Path $repoRoot $OutDir
|
||
|
||
if (-not (Test-Path -Path $projectPath)) { throw "Project 不存在:$Project" }
|
||
if (-not (Test-Path -Path $manifestPath)) { throw "Manifest 不存在:$Manifest" }
|
||
|
||
$manifestObj = Get-Content -Path $manifestPath -Raw | ConvertFrom-Json
|
||
$moduleId = ""
|
||
$version = ""
|
||
if ($null -ne $manifestObj.id) { $moduleId = [string]$manifestObj.id }
|
||
if ($null -ne $manifestObj.version) { $version = [string]$manifestObj.version }
|
||
$moduleId = $moduleId.Trim()
|
||
$version = $version.Trim()
|
||
if ([string]::IsNullOrWhiteSpace($moduleId)) { throw "manifest.json 缺少 id" }
|
||
if ([string]::IsNullOrWhiteSpace($version)) { throw "manifest.json 缺少 version" }
|
||
$entryAssembly = ""
|
||
try {
|
||
if ($null -ne $manifestObj.entry -and $null -ne $manifestObj.entry.assembly) { $entryAssembly = [string]$manifestObj.entry.assembly }
|
||
} catch { }
|
||
$entryAssembly = [string]$entryAssembly
|
||
$entryAssembly = $entryAssembly.Trim()
|
||
if ([string]::IsNullOrWhiteSpace($entryAssembly)) { throw "manifest.json 缺少 entry.assembly" }
|
||
|
||
$buildRootRel = "artifacts/_modulebuild/$moduleId/$version"
|
||
$runId = ([Guid]::NewGuid().ToString("N"))
|
||
$publishRel = "$buildRootRel/publish/$runId"
|
||
$stagingRel = "$buildRootRel/staging/$runId"
|
||
|
||
$publishHost = Join-Path $repoRoot $publishRel
|
||
$stagingHost = Join-Path $repoRoot $stagingRel
|
||
|
||
New-Item -ItemType Directory -Force -Path $publishHost | Out-Null
|
||
New-Item -ItemType Directory -Force -Path $stagingHost | Out-Null
|
||
|
||
$publishContainer = "/src/$publishRel"
|
||
$projectContainer = "/src/$Project"
|
||
|
||
Write-Host "Building module with Docker..." -ForegroundColor Cyan
|
||
docker run --rm `
|
||
-v "${repoRoot}:/src" `
|
||
-w "/src" `
|
||
mcr.microsoft.com/dotnet/sdk:8.0 `
|
||
dotnet publish "$projectContainer" -c Release -o "$publishContainer" /p:UseAppHost=false
|
||
if ($LASTEXITCODE -ne 0)
|
||
{
|
||
Write-Warning "Docker publish 失败(退出码:$LASTEXITCODE),将回退到本机 dotnet publish(需本机已安装 dotnet)。"
|
||
dotnet publish "$projectPath" -c Release -o "$publishHost" /p:UseAppHost=false
|
||
if ($LASTEXITCODE -ne 0) { throw "dotnet publish 失败(退出码:$LASTEXITCODE)" }
|
||
}
|
||
|
||
$stagingLib = Join-Path $stagingHost "lib"
|
||
New-Item -ItemType Directory -Force -Path $stagingLib | Out-Null
|
||
|
||
Copy-Item -Path $manifestPath -Destination (Join-Path $stagingHost "manifest.json") -Force
|
||
Copy-Item -Path (Join-Path $publishHost "*") -Destination $stagingLib -Recurse -Force
|
||
|
||
if ($Slim -or $SlimHost)
|
||
{
|
||
# 与宿主共享的“边界程序集”(见 src/TelegramPanel.Web/Modules/ModuleLoadContext.cs)。
|
||
# 模块包携带这些 dll 会导致体积膨胀(同时也容易造成类型身份不一致的风险),因此在打包阶段直接剔除。
|
||
$sharedPatterns = @(
|
||
"Microsoft.AspNetCore.*.dll",
|
||
"Microsoft.Extensions.*.dll",
|
||
"Microsoft.JSInterop*.dll",
|
||
"TelegramPanel.*.dll",
|
||
"MudBlazor*.dll"
|
||
)
|
||
|
||
foreach ($pattern in $sharedPatterns)
|
||
{
|
||
Get-ChildItem -Path $stagingLib -Filter $pattern -File -ErrorAction SilentlyContinue | ForEach-Object {
|
||
if ($_.Name -ieq $entryAssembly) { return }
|
||
try { Remove-Item -Path $_.FullName -Force -ErrorAction Stop } catch { }
|
||
}
|
||
|
||
$pdbPattern = [System.IO.Path]::ChangeExtension($pattern, ".pdb")
|
||
Get-ChildItem -Path $stagingLib -Filter $pdbPattern -File -ErrorAction SilentlyContinue | ForEach-Object {
|
||
try { Remove-Item -Path $_.FullName -Force -ErrorAction Stop } catch { }
|
||
}
|
||
}
|
||
}
|
||
|
||
if ($SlimHost)
|
||
{
|
||
# 宿主已内置且通常在启动早期加载的依赖:把这些也剔除可大幅减小体积(尤其是 SQLitePCL 的多平台 runtimes/native)。
|
||
$hostBuiltInPatterns = @(
|
||
"Microsoft.EntityFrameworkCore*.dll",
|
||
"Microsoft.Data.Sqlite*.dll",
|
||
"SQLitePCLRaw*.dll",
|
||
"WTelegramClient*.dll",
|
||
"SixLabors.ImageSharp*.dll",
|
||
"PhoneNumbers*.dll"
|
||
)
|
||
|
||
foreach ($pattern in $hostBuiltInPatterns)
|
||
{
|
||
Get-ChildItem -Path $stagingLib -Filter $pattern -File -ErrorAction SilentlyContinue | ForEach-Object {
|
||
if ($_.Name -ieq $entryAssembly) { return }
|
||
try { Remove-Item -Path $_.FullName -Force -ErrorAction Stop } catch { }
|
||
}
|
||
|
||
$pdbPattern = [System.IO.Path]::ChangeExtension($pattern, ".pdb")
|
||
Get-ChildItem -Path $stagingLib -Filter $pdbPattern -File -ErrorAction SilentlyContinue | ForEach-Object {
|
||
try { Remove-Item -Path $_.FullName -Force -ErrorAction Stop } catch { }
|
||
}
|
||
}
|
||
|
||
# 多平台 native runtimes(SQLite)体积很大;TelegramPanel 宿主自身已携带,这里直接剔除。
|
||
$runtimesDir = Join-Path $stagingLib "runtimes"
|
||
if (Test-Path -Path $runtimesDir)
|
||
{
|
||
try { Remove-Item -Path $runtimesDir -Recurse -Force -ErrorAction Stop } catch { }
|
||
}
|
||
|
||
# MudBlazor 静态资源由宿主提供;模块包里携带的这份没有实际用途,顺手剔除。
|
||
$mudWwwroot = Join-Path $stagingLib "wwwroot/_content/MudBlazor"
|
||
if (Test-Path -Path $mudWwwroot)
|
||
{
|
||
try { Remove-Item -Path $mudWwwroot -Recurse -Force -ErrorAction Stop } catch { }
|
||
}
|
||
}
|
||
|
||
New-Item -ItemType Directory -Force -Path $outRoot | Out-Null
|
||
$dest = Join-Path $outRoot "$moduleId-$version.tpm"
|
||
if (Test-Path -Path $dest) { Remove-Item -Path $dest -Force }
|
||
|
||
$destZip = [System.IO.Path]::ChangeExtension($dest, ".zip")
|
||
if (Test-Path -Path $destZip) { Remove-Item -Path $destZip -Force }
|
||
|
||
Compress-Archive -Path (Join-Path $stagingHost "*") -DestinationPath $destZip -Force
|
||
Move-Item -Path $destZip -Destination $dest -Force
|
||
|
||
Write-Host "OK: $dest" -ForegroundColor Green
|