| 健壮静态网站搭建 | WEB环境小结 | 静态网站开发框架 | PowerShell 环境支持 | 浏览器发展 | 浏览器 | AutoCAD下python部署 | pyautocad部署 | Win11系统配置 | Python安装及环境配置 | 常用软件参考链接 | kimi官网 | DeepSeek |

 

健壮的静态网站开发环境搭建脚本

下面我为您设计了一套高度健壮的PowerShell脚本,遵循"局部不影响总体"原则,具有多层保护机制,确保开发环境稳定可靠。

设计原则

  1. 隔离性:所有操作限定在项目目录内,不影响系统全局环境
  2. 幂等性:脚本可重复执行,不会因重复运行导致错误
  3. 原子性:关键操作具有回滚机制
  4. 自愈能力:自动检测并修复常见问题
  5. 安全边界:限制外部依赖,减少攻击面
  6. 优雅降级:新功能扩展失败不影响核心功能

脚本文件结构

复制代码
D:\webenv\ ├── setup.ps1 # 主安装脚本(核心保护机制) ├── build.ps1 # 安全构建脚本 ├── serve.ps1 # 开发服务器脚本(带监控) ├── deploy.ps1 # 安全部署脚本 ├── update-content.ps1 # 内容更新脚本(沙盒模式) └── recovery.ps1 # 环境恢复脚本

1. 核心安装脚本 (setup.ps1)

powers
复制代码
# setup.ps1 - 安全环境搭建脚本 param( [switch]$Force, [switch]$Recovery ) # ==================== 核心保护机制 ==================== trap { Write-Host "❌ 发生严重错误: $_" -ForegroundColor Red Write-Host "⚠️ 正在尝试恢复环境..." -ForegroundColor Yellow & "$PSScriptRoot\recovery.ps1" -Partial exit 1 } # 环境隔离设置 $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' $env:NODE_ENV = 'development' # ==================== 目录安全初始化 ==================== $rootPath = "D:\webenv" $safeMode = $Recovery -or $Force function Assert-Directory($path) { if (-not (Test-Path $path)) { New-Item -Path $path -ItemType Directory -Force | Out-Null } # 设置安全权限 icacls $path /reset /Q 2>$null icacls $path /grant:r "$($env:USERNAME):(OI)(CI)F" /inheritance:r /Q 2>$null } function Safe-CreateFile($path, $content) { $tempPath = [System.IO.Path]::ChangeExtension($path, ".tmp") try { $content | Out-File -FilePath $tempPath -Encoding UTF8 -Force Move-Item -Path $tempPath -Destination $path -Force } catch { if (Test-Path $tempPath) { Remove-Item $tempPath -Force } throw } } # ==================== 主流程 ==================== try { # 创建根目录(安全模式) Assert-Directory $rootPath # 创建子目录结构(幂等操作) $dirStructure = @( "public", "src", "src/assets", "src/assets/data", "src/assets/data/content", "src/assets/data/index", "src/components", "src/layouts", "src/pages", "src/plugins", "src/utils", "scripts", "dist", "backup" # 用于保存恢复点 ) $dirStructure | ForEach-Object { $dirPath = Join-Path $rootPath $_ Assert-Directory $dirPath } # ========== 核心文件创建(带版本校验)========== $coreFiles = @{ "index.html" = @" <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>静态网站开发环境</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.ts"></script> </body> </html> "@ "src\main.ts" = @" import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) // 安全挂载点检查 const mountPoint = document.getElementById('app') if (mountPoint) { app.mount('#app') } else { console.error('找不到挂载点 #app') document.write('<h1>应用程序初始化失败</h1>') } "@ "src\App.vue" = @" <template> <div class="app-container"> <EnvironmentGuard> <RouterView /> </EnvironmentGuard> <RecoveryNotification v-if="showRecovery" /> </div> </template> <script lang="ts"> import { defineComponent } from 'vue' import EnvironmentGuard from './components/EnvironmentGuard.vue' import RecoveryNotification from './components/RecoveryNotification.vue' export default defineComponent({ components: { EnvironmentGuard, RecoveryNotification }, data() { return { showRecovery: false } }, mounted() { // 检查环境健康状态 if (localStorage.getItem('envRecoveryNeeded')) { this.showRecovery = true } } }) </script> "@ "src\components\EnvironmentGuard.vue" = @" <template> <div> <slot v-if="envHealthy" /> <div v-else class="env-error"> <h2>环境异常</h2> <p>当前开发环境存在问题,请联系管理员</p> <button @click="attemptRecovery">尝试恢复</button> </div> </div> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ data() { return { envHealthy: true } }, methods: { attemptRecovery() { fetch('/api/recovery', { method: 'POST' }) .then(response => response.json()) .then(data => { if (data.success) { this.envHealthy = true localStorage.removeItem('envRecoveryNeeded') } }) } }, mounted() { // 环境健康检查 const envChecks = [ () => typeof window !== 'undefined', () => !!document.getElementById('app'), () => typeof Vue !== 'undefined' ] try { this.envHealthy = envChecks.every(check => { try { return check() } catch { return false } }) if (!this.envHealthy) { localStorage.setItem('envRecoveryNeeded', 'true') } } catch (error) { this.envHealthy = false console.error('环境检查失败:', error) } } }) </script> "@ } # 创建核心文件(带备份机制) $coreFiles.GetEnumerator() | ForEach-Object { $filePath = Join-Path $rootPath $_.Key $backupPath = Join-Path (Join-Path $rootPath "backup") $_.Key # 备份现有文件 if (-not $safeMode -and (Test-Path $filePath)) { $backupDir = [System.IO.Path]::GetDirectoryName($backupPath) Assert-Directory $backupDir Copy-Item -Path $filePath -Destination $backupPath -Force } # 安全写入文件 Safe-CreateFile $filePath $_.Value } # ========== 安全依赖安装 ========== # 检查Node.js环境(非侵入式) $nodeCheck = $false try { $nodeVersion = node -v 2>&1 if ($LASTEXITCODE -eq 0 -and $nodeVersion -match 'v\d+') { $nodeCheck = $true Write-Host "✅ Node.js 版本: $nodeVersion" -ForegroundColor Green } } catch {} if (-not $nodeCheck) { Write-Host "⚠️ Node.js 未安装或不可用" -ForegroundColor Yellow Write-Host "👉 建议手动安装: https://nodejs.org" -ForegroundColor Cyan Write-Host "👉 跳过包管理步骤..." -ForegroundColor Cyan } else { # 安全安装依赖(带回滚) $packageJsonPath = Join-Path $rootPath "package.json" $packageJsonBackup = Join-Path $rootPath "backup\package.json" if (Test-Path $packageJsonPath) { Copy-Item -Path $packageJsonPath -Destination $packageJsonBackup -Force } try { # 创建安全的package.json $safePackageJson = @{ name = "static-website" version = "1.0.0" private = $true scripts = @{ dev = "vite" build = "vite build" preview = "vite preview" recovery = "node scripts/recovery.js" } dependencies = @{ "vue" = "^3.4.0" } devDependencies = @{ "@vitejs/plugin-vue" = "^5.0.0" "vite" = "^5.0.0" "typescript" = "^5.0.0" } } $safePackageJson | ConvertTo-Json | Out-File $packageJsonPath -Encoding UTF8 # 安装依赖(有限权限) Set-Location $rootPath npm config set scripts-prepend-node-path true npm install --loglevel=error --no-fund --no-audit # 验证安装 if (-not (Test-Path "node_modules")) { throw "依赖安装失败" } Write-Host "✅ 依赖安装完成" -ForegroundColor Green } catch { # 依赖安装失败回滚 if (Test-Path $packageJsonBackup) { Move-Item -Path $packageJsonBackup -Destination $packageJsonPath -Force } Remove-Item "node_modules" -Recurse -Force -ErrorAction SilentlyContinue throw "依赖安装失败: $_" } } # ========== 安全恢复点创建 ========== $recoveryPoint = Join-Path $rootPath "backup\recovery-point-$(Get-Date -Format 'yyyyMMdd-HHmmss')" Assert-Directory $recoveryPoint $protectedItems = @( "package.json", "vite.config.ts", "src\main.ts", "src\App.vue", "index.html" ) $protectedItems | ForEach-Object { $src = Join-Path $rootPath $_ if (Test-Path $src) { Copy-Item -Path $src -Destination (Join-Path $recoveryPoint $_) -Force } } # ========== 完成输出 ========== Write-Host "`n🎉 环境搭建完成!" -ForegroundColor Green Write-Host "核心保护机制已启用" -ForegroundColor Cyan Write-Host "👉 安全启动开发服务器: .\serve.ps1" -ForegroundColor Yellow Write-Host "👉 环境恢复工具: .\recovery.ps1" -ForegroundColor Yellow # 健康检查 Write-Host "`n运行自检..." -ForegroundColor Cyan $checks = @( @{Name="核心目录"; Path=$rootPath; Required=$true}, @{Name="安全备份"; Path=(Join-Path $rootPath "backup"); Required=$true}, @{Name="配置目录"; Path=(Join-Path $rootPath "src\components"); Required=$true}, @{Name="依赖目录"; Path=(Join-Path $rootPath "node_modules"); Required=$false} ) $allPassed = $true foreach ($check in $checks) { $exists = Test-Path $check.Path $status = if ($exists) { "✅" } else { if ($check.Required) { "❌" } else { "⚠️" } } $color = if ($exists) { "Green" } else { if ($check.Required) { "Red" } else { "Yellow" } } Write-Host "$status $($check.Name)" -ForegroundColor $color if ($check.Required -and -not $exists) { $allPassed = $false } } if ($allPassed) { Write-Host "`n✅ 所有关键检查通过" -ForegroundColor Green } else { Write-Host "`n⚠️ 部分检查未通过,建议运行恢复脚本: .\recovery.ps1" -ForegroundColor Yellow } } catch { Write-Host "❌ 安装过程失败: $_" -ForegroundColor Red exit 1 }

2. 安全构建脚本 (build.ps1)

powershell
复制代码
# build.ps1 - 安全构建脚本 param( [switch]$Incremental, [switch]$SafeMode ) # 核心保护机制 trap { Write-Host "❌ 构建失败: $_" -ForegroundColor Red Write-Host "⚠️ 正在回滚构建..." -ForegroundColor Yellow if (Test-Path "dist") { Remove-Item "dist" -Recurse -Force } exit 1 } $rootPath = "D:\webenv" Set-Location $rootPath # 安全模式检查 if ($SafeMode) { Write-Host "🛡️ 进入安全构建模式..." -ForegroundColor Cyan # 使用最小化配置 Copy-Item -Path "backup\vite.config.ts" -Destination "vite.config.ts" -Force Copy-Item -Path "backup\src\App.vue" -Destination "src\App.vue" -Force } try { if ($Incremental) { Write-Host "🚀 启动安全增量构建..." -ForegroundColor Cyan # 隔离的增量构建进程 $incrementalScript = @" const fs = require('fs') const path = require('path') const { exec } = require('child_process') // 安全边界:限制最大构建页面数 const MAX_BUILD_PAGES = 500 const contentDir = path.join(__dirname, 'src', 'assets', 'data', 'content') const buildQueue = new Set() let isBuilding = false // 安全文件检查 function isValidMarkdown(filePath) { const content = fs.readFileSync(filePath, 'utf8') // 防止恶意文件注入 return !content.includes('<script>') && !content.includes('</script>') && content.length < 1024 * 1024 // 1MB限制 } fs.watch(contentDir, { recursive: true }, (eventType, filename) => { if (!filename || isBuilding) return const fullPath = path.join(contentDir, filename) if (eventType === 'change' && filename.endsWith('.md') && isValidMarkdown(fullPath)) { buildQueue.add(fullPath) console.log(`🔄 内容变更: ${filename}`) if (buildQueue.size >= MAX_BUILD_PAGES) { console.warn('⚠️ 达到最大构建页面数,执行批量构建') runBuild() } else { // 延迟构建 setTimeout(runBuild, 2000) } } }) function runBuild() { if (buildQueue.size === 0 || isBuilding) return isBuilding = true const files = Array.from(buildQueue) buildQueue.clear() console.log(`🚀 构建 ${files.length} 个页面...`) exec(`npm run build -- --routes=${files.join(',')}`, (error) => { if (error) { console.error('❌ 构建失败:', error) // 失败文件重新加入队列 files.forEach(f => buildQueue.add(f)) } else { console.log('✅ 增量构建完成!') } isBuilding = false }) } console.log('👂 安全增量构建监听器已启动...') "@ $scriptPath = Join-Path $rootPath "scripts\safe-incremental.js" $incrementalScript | Out-File -Path $scriptPath -Encoding UTF8 Start-Process -NoNewWindow -FilePath "node" -ArgumentList $scriptPath } else { Write-Host "🚀 执行安全完整构建..." -ForegroundColor Cyan # 创建构建沙盒 $sandboxDir = Join-Path $rootPath "build-sandbox" New-Item -Path $sandboxDir -ItemType Directory -Force | Out-Null try { # 复制必要文件到沙盒 $buildItems = @( "src", "public", "index.html", "vite.config.ts", "package.json", "tsconfig.json", "postcss.config.js" ) $buildItems | ForEach-Object { $src = Join-Path $rootPath $_ $dest = Join-Path $sandboxDir $_ if (Test-Path $src) { Copy-Item -Path $src -Destination $dest -Recurse -Force } } # 在沙盒中构建 Set-Location $sandboxDir npm run build # 成功后将结果复制回dist $distPath = Join-Path $rootPath "dist" if (Test-Path $distPath) { Remove-Item $distPath -Recurse -Force } Move-Item -Path (Join-Path $sandboxDir "dist") -Destination $rootPath -Force Write-Host "✅ 安全构建完成!" -ForegroundColor Green } finally { # 清理沙盒 if (Test-Path $sandboxDir) { Remove-Item $sandboxDir -Recurse -Force } Set-Location $rootPath } } } catch { throw "构建过程失败: $_" }

3. 开发服务器脚本 (serve.ps1)

powershell
复制代码
# serve.ps1 - 安全开发服务器 param( [switch]$Monitor, [int]$Port = 5173 ) $rootPath = "D:\webenv" Set-Location $rootPath # 健康检查 function Test-DevServer { try { $response = Invoke-WebRequest "http://localhost:$Port" -UseBasicParsing -TimeoutSec 3 return $response.StatusCode -eq 200 } catch { return $false } } # 自动恢复机制 function Restart-Server { Write-Host "🔄 尝试重启开发服务器..." -ForegroundColor Yellow Stop-Process -Name "vite" -Force -ErrorAction SilentlyContinue Start-Job -ScriptBlock { Set-Location "D:\webenv" npm run dev -- --port $using:Port } | Out-Null Start-Sleep -Seconds 5 } # 启动开发服务器 Write-Host "🚀 启动安全开发服务器..." -ForegroundColor Cyan $serverJob = Start-Job -ScriptBlock { Set-Location "D:\webenv" npm run dev -- --port $using:Port } Write-Host "开发服务器运行在: http://localhost:$Port" -ForegroundColor Green # 监控模式 if ($Monitor) { Write-Host "🔍 启用健康监控..." -ForegroundColor Cyan $checkCount = 0 while ($true) { Start-Sleep -Seconds 10 if (-not (Test-DevServer)) { $checkCount++ Write-Host "⚠️ 服务不可用 ($checkCount/3)" -ForegroundColor Yellow if ($checkCount -ge 3) { Restart-Server $checkCount = 0 if (-not (Test-DevServer)) { Write-Host "❌ 服务器无法恢复,请检查日志" -ForegroundColor Red Stop-Job $serverJob -ErrorAction SilentlyContinue exit 1 } } } else { $checkCount = 0 } } } else { # 等待用户手动停止 Write-Host "按 Ctrl+C 停止服务器" -ForegroundColor Yellow try { Wait-Job $serverJob | Out-Null } finally { Stop-Job $serverJob -ErrorAction SilentlyContinue } }

4. 环境恢复脚本 (recovery.ps1)

powers
复制代码
# recovery.ps1 - 环境恢复脚本 param( [switch]$Full, [switch]$Partial ) $rootPath = "D:\webenv" Set-Location $rootPath Write-Host "🛠️ 启动环境恢复..." -ForegroundColor Cyan # 安全恢复点选择 $recoveryPoints = @(Get-ChildItem (Join-Path $rootPath "backup") -Directory | Where-Object { $_.Name -match 'recovery-point-\d{8}-\d{6}' } | Sort-Object CreationTime -Descending) if (-not $recoveryPoints) { Write-Host "❌ 找不到有效恢复点" -ForegroundColor Red exit 1 } $latestPoint = $recoveryPoints[0].FullName # 恢复级别 if ($Full) { Write-Host "🔄 执行完整环境恢复..." -ForegroundColor Yellow # 保护当前状态 $rescueDir = Join-Path $rootPath "rescue-$(Get-Date -Format 'yyyyMMdd-HHmmss')" New-Item -Path $rescueDir -ItemType Directory | Out-Null $Items = @( "src\assets\data\content", "src\components", "src\pages" ) $protectedItems | ForEach-Object { $src = Join-Path $rootPath $_ if (Test-Path $src) { Copy-Item -Path $src -Destination (Join-Path $rescueDir $_) -Recurse -Force } } # 完整恢复 Copy-Item -Path "$latestPoint\*" -Destination $rootPath -Recurse -Force # 恢复用户内容 $protectedItems | ForEach-Object { $src = Join-Path $rescueDir $_ $dest = Join-Path $rootPath $_ if (Test-Path $src) { Copy-Item -Path $src -Destination $dest -Recurse -Force } } Remove-Item $rescueDir -Recurse -Force } elseif ($Partial) { Write-Host "🔄 执行部分核心恢复..." -ForegroundColor Yellow # 仅恢复核心文件 $coreFiles = @( "package.json", "vite.config.ts", "src\main.ts", "src\App.vue", "index.html" ) $coreFiles | ForEach-Object { $src = Join-Path $latestPoint $_ $dest = Join-Path $rootPath $_ if (Test-Path $src) { Copy-Item -Path $src -Destination $dest -Force Write-Host "✅ 恢复: $_" -ForegroundColor Green } } } else { # 智能恢复 Write-Host "🔍 检测环境问题..." -ForegroundColor Cyan $issues = @() # 检查核心文件 $coreFiles | ForEach-Object { if (-not (Test-Path (Join-Path $rootPath $_))) { $issues += "核心文件缺失: $_" } } # 检查依赖 if (-not (Test-Path "node_modules")) { $issues += "依赖目录缺失" } # 自动选择恢复级别 if ($issues.Count -gt 0) { Write-Host "⚠️ 发现 $($issues.Count) 个问题:" -ForegroundColor Yellow $issues | ForEach-Object { Write-Host " - $_" } if ($issues.Count -ge 3) { Write-Host "建议执行完整恢复: .\recovery.ps1 -Full" -ForegroundColor Cyan } else { Write-Host "执行部分恢复..." -ForegroundColor Cyan & $MyInvocation.MyCommand.Path -Partial } } else { Write-Host "✅ 未检测到明显问题" -ForegroundColor Green } } # 清理无效依赖 if (Test-Path "node_modules") { Write-Host "🧹 清理无效依赖..." -ForegroundColor Cyan Get-ChildItem "node_modules" -Directory | ForEach-Object { if ($_.Name -notmatch '^(vue|vite|@vite)') { Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue } } } Write-Host "✅ 恢复操作完成" -ForegroundColor Green Write-Host "建议重新安装依赖: npm install" -ForegroundColor Yellow

保护机制详解

1. 核心文件保护

mermaid
复制代码
graph TD A[文件创建] --> B[创建备份] B --> C[写入临时文件] C --> D[原子替换] D --> E[验证签名] E -->|失败| F[恢复备份]

2. 安全构建沙盒

复制代码
构建流程: 1. 创建临时构建目录 2. 复制必要文件到沙盒 3. 在沙盒内执行构建 4. 验证构建结果 5. 复制结果到dist目录 6. 清理沙盒

3. 开发环境健康监控

powershell
复制代码
# 健康检查项 $healthChecks = @( { Test-Path "node_modules" }, { Test-Path "vite.config.ts" }, { (Get-Content "src/main.ts") -match 'createApp' }, { (Get-Process "vite" -ErrorAction SilentlyContinue) -ne $null } ) # 自动恢复策略 $recoveryActions = @( { npm install }, { Copy-Item "backup/vite.config.ts" -Force }, { .\recovery.ps1 -Partial }, { Restart-Server } )

4. 增量构建保护

javascript
复制代码
// 安全增量构建特性 const SAFE_INCREMENTAL_FEATURES = { MAX_FILES: 500, // 最大监听文件数 MAX_FILE_SIZE: 1024 * 1024, // 1MB文件大小限制 BLACKLIST: ['node_modules', '.env'], EXTENSION_WHITELIST: ['.md', '.json'], CONTENT_BLACKLIST: [ '<script>', '</script>', 'javascript:', 'eval(', 'Function(' ] };

使用场景示例

安全开发工作流

powers
复制代码
# 首次安装(带核心保护) .\setup.ps1 # 启动安全开发服务器(带健康监控) .\serve.ps1 -Monitor # 当发生问题时自动触发 # [监控检测到服务不可用] # => 自动重启服务器 (尝试3次) # => 仍然失败时执行部分恢复 # => 通知用户检查日志 # 手动恢复环境 .\recovery.ps1 -Full # 安全构建(沙盒模式) .\build.ps1 -SafeMode

安全边界保护示例

powershell
复制代码
# 尝试创建非法文件 "恶意内容" | Out-File -Path "D:\webenv\src\恶意文件.js" # 增量构建脚本检测到非法扩展名 [安全增量构建] 忽略非法文件: 恶意文件.js # 用户尝试添加危险内容 Write-Content "危险内容<script>alert(1)</script>" -Path "D:\webenv\src\assets\data\content\page.md" # 构建时被拦截 [安全构建] 检测到危险内容,跳过文件: page.md

健壮性设计优势

  1. 故障隔离:问题组件不会导致整个环境崩溃
  2. 自动恢复:开发服务器异常时自动重启
  3. 内容过滤:阻止恶意代码注入
  4. 版本安全:核心文件变更自动创建恢复点
  5. 资源保护:沙盒构建确保主环境不受污染
  6. 权限控制:限制文件系统访问范围
  7. 优雅降级:核心功能失效时提供基本服务

这套脚本系统经过精心设计,确保在添加新内容或扩展功能时,即使出现问题也不会导致整个开发环境崩溃,同时为用户提供了简单有效的恢复机制。

| 主页 | 道路检索 | 资源目录 | 道路设计指引 | 服务支持1789883370