适用场景
前后端同步开发的时候,需要全流程构建
源码
python
#!/usr/bin/env python3
"""
IPAM Frontend - PNPM 构建和验证脚本
实现类型检查、编译验证和代码质量检查
"""
import os
import sys
import json
import time
import subprocess
from pathlib import Path
import argparse
from loguru import logger
def check_pnpm_installed() -> bool:
"""检查 pnpm 是否已安装"""
logger.info("📋 检查依赖")
logger.info(" 验证 pnpm 是否已安装")
# 使用os.system进行检测,与build.py保持一致
pnpm_check_result = os.system("pnpm --version")
if pnpm_check_result == 0:
version = subprocess.getoutput("pnpm --version").strip()
logger.success(f"✅ pnpm已安装 (版本: {version})")
return True
else:
logger.info("ℹ️ 安装命令: npm install -g pnpm")
logger.error("❌ pnpm未安装,请先安装 pnpm")
sys.exit(1)
def install_dependencies() -> bool:
"""安装依赖"""
logger.info("📋 安装依赖")
logger.info(" 使用 pnpm install 安装项目依赖")
try:
exitCode, output = subprocess.getstatusoutput('pnpm install')
if exitCode == 0:
logger.success("✅ 依赖安装成功")
return True
else:
logger.error(f"错误输出: {output}")
logger.error("❌ 依赖安装失败")
return False
except Exception as e:
logger.error(f"❌ 安装依赖时发生错误: {e}")
return False
def run_dev_server_test() -> bool:
"""测试开发服务器启动"""
logger.info("📋 开发服务器测试")
logger.info(" 验证开发服务器可以正常启动")
# 这里我们只是检查配置,不实际启动服务器
# 因为启动服务器会阻塞进程
if os.system('npx vite --version') == 0:
logger.success("✅ Vite 开发服务器配置正常")
return True
else:
logger.error("❌ Vite 开发服务器配置有问题")
return False
def run_type_check() -> bool:
"""运行 TypeScript 类型检查和构建验证
如果任何一个检查步骤发现错误,将立即终止后续检查。
统一使用os.system执行,避免输出排版混乱。
"""
# 定义所有检查步骤:title 和 command
check_steps = [
{"title": "TypeScript 类型检查", "command": "npx tsc --noEmit"},
{"title": "TypeScript 类型检查", "command": "pnpm exec tsc --noEmit"},
{"title": "TypeScript 类型检查", "command": "pnpm run typecheck"},
{"title": "Vue 严格类型检查", "command": "pnpm run typecheck:strict"},
{"title": "Vue 文件类型检查", "command": "npx vue-tsc --noEmit"},
{"title": "Vue SFC 检查", "command": "pnpm run lint:vue"},
{"title": "Vite 构建类型检查", "command": "npx vite build --mode production"}
]
try:
# 使用 for 循环执行所有检查步骤
for step in check_steps:
title = step["title"]
command = step["command"]
desc = f"使用 {command.split()[0]} 进行{title.replace('检查', '')}"
logger.info(f"📋 {title}")
logger.info(f" {desc}")
if os.system(command) != 0:
logger.debug(f"执行命令: {command}")
logger.error(f"❌ {title}失败")
return False
logger.success(f"✅ {title}通过")
except Exception as e:
logger.error(f"❌ 类型检查过程中发生错误: {e}")
return False
# 所有类型检查通过
logger.info("📋 编译验证")
logger.info(" 类型检查通过,准备编译验证")
return True
class PNPMRunner:
"""PNPM 脚本运行器"""
def __init__(self, frontend_dir: str = None):
self.frontend_dir = Path(frontend_dir or os.getcwd()) # pyright: ignore[reportUnannotatedClassAttribute]
self.project_root = self.frontend_dir.parent # pyright: ignore[reportUnannotatedClassAttribute]
def check_typescript_config(self) -> bool:
"""检查 TypeScript 配置"""
logger.info("📋 TypeScript 配置检查")
logger.info(" 验证 tsconfig.json 配置")
tsconfig_path = self.frontend_dir / 'tsconfig.json'
if not tsconfig_path.exists():
logger.error("❌ tsconfig.json 文件不存在")
sys.exit(1)
try:
with open(tsconfig_path, 'r', encoding='utf-8') as f:
config = json.load(f)
# 检查关键配置
compiler_options = config.get('compilerOptions', {})
checks = [
('strict', compiler_options.get('strict', False)),
('noEmit', compiler_options.get('noEmit', False)),
('skipLibCheck', compiler_options.get('skipLibCheck', True)),
]
for key, value in checks:
status = "启用" if value else "禁用"
symbol = "✅" if value else "⚠️ "
logger.info(f" {symbol} {key}: {status}")
logger.success("✅ TypeScript 配置检查完成")
return True
except json.JSONDecodeError as e:
logger.error(f"❌ tsconfig.json 格式错误: {e}")
sys.exit(1)
except Exception as e:
logger.error(f"❌ 检查 TypeScript 配置时出错: {e}")
sys.exit(1)
def check_bundle_size(self) -> bool:
"""检查构建产物大小"""
logger.info("📋 构建产物检查")
logger.info(" 检查构建产物体积")
dist_dir = self.frontend_dir / 'dist'
if not dist_dir.exists():
logger.warning("⚠️ dist 目录不存在,跳过大小检查")
return True
total_size = 0
for file_path in dist_dir.rglob('*'):
if file_path.is_file():
total_size += file_path.stat().st_size
size_mb = total_size / (1024 * 1024)
logger.info(f"ℹ️ 构建产物总大小: {size_mb:.2f} MB")
# 建议的阈值
if size_mb > 10:
logger.warning("⚠️ 构建产物较大,建议优化")
else:
logger.success("✅ 构建产物大小正常")
return True
def clean_build(self) -> bool:
"""清理构建产物"""
logger.info("📋 清理构建产物")
logger.info(" 删除 dist 和 node_modules/.vite")
dist_dir = self.frontend_dir / 'dist'
vite_cache = self.frontend_dir / 'node_modules' / '.vite'
try:
if dist_dir.exists():
import shutil
shutil.rmtree(dist_dir)
logger.success("✅ 清理 dist 目录")
if vite_cache.exists():
import shutil
shutil.rmtree(vite_cache)
logger.success("✅ 清理 vite 缓存")
return True
except Exception as e:
logger.error(f"❌ 清理失败: {e}")
return False
def run_lint_check(self) -> bool:
"""运行代码质量检查"""
logger.info("📋 代码质量检查")
logger.info(" 检查项目结构和关键文件")
# 检查关键文件是否存在
key_files = [
'src/main.js',
'src/App.vue',
'src/router',
'src/stores',
'src/views',
'src/utils',
'package.json',
'vite.config.js',
'tsconfig.json'
]
missing_files = []
for file_path in key_files:
full_path = self.frontend_dir / file_path
if not full_path.exists():
missing_files.append(file_path)
if missing_files:
logger.warning(f"⚠️ 缺少关键文件: {', '.join(missing_files)}")
else:
logger.success("✅ 关键文件检查通过")
# 检查 utils 目录中的工具文件
utils_dir = self.frontend_dir / 'src' / 'utils'
if utils_dir.exists():
utils_files = list(utils_dir.glob('*.ts'))
logger.info(f"ℹ️ 找到 {len(utils_files)} 个工具文件")
return len(missing_files) == 0
def start(self, need_build: bool = True) -> bool:
"""启动构建流程
这个方法提供了一个简单的接口来执行前端构建流程,
根据need_build参数决定是否需要执行构建步骤:
- need_build=True: 全流程,包括所有检查和构建步骤
- need_build=False: 仅检查,包括所有检查步骤但不执行构建
如果任何一个检查步骤发现错误,将立即终止后续流程。
Args:
need_build: 是否需要执行构建步骤,默认值为True
Returns:
bool: 构建是否成功
"""
# self.print_banner()
start_time = time.time()
try:
# 1. 检查 pnpm
if not check_pnpm_installed():
logger.error("pnpm 检查失败,终止后续流程")
return False
# 2. 安装依赖
if not install_dependencies():
logger.error("依赖安装失败,终止后续流程")
return False
# 3. 检查 TypeScript 配置
if not self.check_typescript_config():
logger.error("❌ TypeScript 配置检查失败,终止后续流程")
return False
# 4. 清理构建产物
if not self.clean_build():
logger.error("❌ 清理构建产物失败,终止后续流程")
return False
# 5. 类型检查
if not run_type_check():
logger.error("❌ 类型检查失败,终止后续流程")
return False
# 6. Vite 构建检查 (仅在need_build=True时执行)
if need_build:
logger.info("📋 Vite 构建类型检查")
logger.info(" 使用 npx vite build --mode production 进行构建验证")
if os.system("npx vite build --mode production") != 0:
logger.error("❌ Vite 构建失败")
return False
logger.success("✅ Vite 构建类型检查通过")
# 7. 检查构建产物
if not self.check_bundle_size():
logger.error("❌ 构建产物检查失败,终止后续流程")
return False
# 8. 代码质量检查
if not self.run_lint_check():
logger.error("❌ 代码质量检查失败,终止后续流程")
return False
# 9. 开发服务器测试
if not run_dev_server_test():
logger.error("❌ 开发服务器测试失败,终止后续流程")
return False
# 完成
end_time = time.time()
duration = end_time - start_time
logger.success("🎉 构建验证完成!")
logger.info(f"总耗时: {duration:.2f} 秒")
return True
except Exception as e:
logger.error(f"❌ 构建验证过程中发生错误: {e}")
return False
def find_frontend_root(start_path: Path = None) -> Path:
"""
递归查找前端根目录
遍历所有目录,找到同时存在 package.json、vite.config.ts 文件及 src 目录的目标作为前端根目录
Args:
start_path: 开始查找的路径,默认为当前工作目录
Returns:
Path: 找到的前端根目录路径
Raises:
FileNotFoundError: 未找到符合条件的前端根目录
"""
if start_path is None:
start_path = Path.cwd()
# 需要检查的关键文件和目录
required_files = ['package.json', 'vite.config.ts']
required_dir = 'src'
logger.info(f"开始从 {start_path} 查找前端根目录...")
# 使用广度优先搜索遍历目录
from collections import deque
queue = deque([start_path])
while queue:
current_dir = queue.popleft()
# 检查当前目录是否符合条件
has_all_files = all((current_dir / file).exists() for file in required_files)
has_src_dir = (current_dir / required_dir).is_dir()
if has_all_files and has_src_dir:
logger.success(f"找到前端根目录: {current_dir}")
return current_dir
# 将子目录加入队列继续搜索
try:
for item in current_dir.iterdir():
if item.is_dir() and not item.name.startswith('.') and item.name != 'node_modules':
queue.append(item)
except PermissionError:
# 跳过无权限访问的目录
continue
# 如果遍历完所有目录都没找到,抛出异常
raise FileNotFoundError(f"未找到包含 {required_files} 和 {required_dir} 目录的前端根目录")
def main():
"""主函数"""
parser = argparse.ArgumentParser(description='IPAM Frontend PNPM 构建验证工具')
parser.add_argument( # pyright: ignore[reportUnusedCallResult]
'action',
nargs='?', # 使参数可选
default='full', # 默认执行完整构建
choices=['full', 'types'],
type=str,
help='执行的操作: full(完整构建), types(类型检查)'
) # type: ignore
parser.add_argument( # pyright: ignore[reportUnusedCallResult]
'--frontend-dir',
default=None,
type=str,
help='前端项目目录路径'
) # type: ignore
args = parser.parse_args()
# 智能判断前端目录
if args.frontend_dir:
# 如果指定了前端目录,则使用指定的路径
frontend_path = Path(args.frontend_dir) # pyright: ignore[reportAny]
if not frontend_path.exists():
logger.error(f"❌ 指定的前端目录 {frontend_path} 不存在")
sys.exit(1)
else:
# 如果没有指定前端目录,使用递归查找
try:
frontend_path = find_frontend_root()
except FileNotFoundError as e:
logger.error(f"❌ {e}")
sys.exit(1)
runner = PNPMRunner(str(frontend_path))
# 保存当前工作目录
original_cwd = os.getcwd()
try:
# 切换到前端目录
os.chdir(str(frontend_path))
logger.info(f"切换到前端目录: {frontend_path}")
# 打印横幅
logger.info("=" * 60)
logger.info("🚀 IPAM Frontend - PNPM 构建验证工具")
logger.info("=" * 60)
need_build = False
if str(args.action).lower() == 'full'.lower():
need_build = True
success = runner.start(need_build=need_build)
if success:
logger.success("✅ 操作执行成功")
sys.exit(0)
else:
logger.error("❌ 操作执行失败")
sys.exit(1)
except KeyboardInterrupt:
logger.warning("操作被用户中断")
sys.exit(1)
except Exception as e:
logger.error(f"执行过程中出现错误: {e}")
finally:
# 确保切换回原始目录
try:
os.chdir(original_cwd)
logger.info(f"切换回原始目录: {original_cwd}")
except Exception as e:
logger.error(f"切换目录失败: {e}")
if __name__ == '__main__':
main()
效果
powershell
PS D:\Code\gitee\go\系统\dns-go\pure-admin-thin-v6.0.0> python .\pnpm.py
2025-12-17 23:22:53.957 | INFO | __main__:find_frontend_root:359 - 开始从 D:\Code\gitee\go\系统\dns-go\pure-admin-thin-v6.0.0 查找前端根目录...
2025-12-17 23:22:53.958 | SUCCESS | __main__:find_frontend_root:373 - 找到前端根目录: D:\Code\gitee\go\系统\dns-go\pure-admin-thin-v6.0.0
2025-12-17 23:22:53.958 | INFO | __main__:main:432 - 切换到前端目录: D:\Code\gitee\go\系统\dns-go\pure-admin-thin-v6.0.0
2025-12-17 23:22:53.958 | INFO | __main__:main:435 - ============================================================
2025-12-17 23:22:53.959 | INFO | __main__:main:436 - 🚀 IPAM Frontend - PNPM 构建验证工具
2025-12-17 23:22:53.959 | INFO | __main__:main:437 - ============================================================
2025-12-17 23:22:53.959 | INFO | __main__:check_pnpm_installed:19 - 📋 检查依赖
2025-12-17 23:22:53.959 | INFO | __main__:check_pnpm_installed:20 - 验证 pnpm 是否已安装
2025-12-17 23:22:54.337 | SUCCESS | __main__:check_pnpm_installed:27 - ✅ pnpm已安装 (版本: )
2025-12-17 23:22:54.338 | INFO | __main__:install_dependencies:37 - 📋 安装依赖
2025-12-17 23:22:54.338 | INFO | __main__:install_dependencies:38 - 使用 pnpm install 安装项目依赖
2025-12-17 23:22:54.545 | SUCCESS | __main__:install_dependencies:44 - ✅ 依赖安装成功
2025-12-17 23:22:54.545 | INFO | __main__:check_typescript_config:124 - 📋 TypeScript 配置检查
2025-12-17 23:22:54.545 | INFO | __main__:check_typescript_config:125 - 验证 tsconfig.json 配置
2025-12-17 23:22:54.546 | INFO | __main__:check_typescript_config:148 - ⚠️ strict: 禁用
2025-12-17 23:22:54.546 | INFO | __main__:check_typescript_config:148 - ✅ noEmit: 启用
2025-12-17 23:22:54.546 | INFO | __main__:check_typescript_config:148 - ✅ skipLibCheck: 启用
2025-12-17 23:22:54.546 | SUCCESS | __main__:check_typescript_config:150 - ✅ TypeScript 配置检查完成
2025-12-17 23:22:54.547 | INFO | __main__:clean_build:190 - 📋 清理构建产物
2025-12-17 23:22:54.547 | INFO | __main__:clean_build:191 - 删除 dist 和 node_modules/.vite
2025-12-17 23:22:54.568 | SUCCESS | __main__:clean_build:200 - ✅ 清理 dist 目录
2025-12-17 23:22:54.568 | INFO | __main__:run_type_check:97 - 📋 TypeScript 类型检查
2025-12-17 23:22:54.568 | INFO | __main__:run_type_check:98 - 使用 npx 进行TypeScript 类型
2025-12-17 23:23:06.914 | SUCCESS | __main__:run_type_check:103 - ✅ TypeScript 类型检查通过
2025-12-17 23:23:06.914 | INFO | __main__:run_type_check:97 - 📋 TypeScript 类型检查
2025-12-17 23:23:06.915 | INFO | __main__:run_type_check:98 - 使用 pnpm 进行TypeScript 类型
2025-12-17 23:23:07.124 | SUCCESS | __main__:run_type_check:103 - ✅ TypeScript 类型检查通过
2025-12-17 23:23:07.124 | INFO | __main__:run_type_check:97 - 📋 TypeScript 类型检查
2025-12-17 23:23:07.124 | INFO | __main__:run_type_check:98 - 使用 pnpm 进行TypeScript 类型
2025-12-17 23:23:07.345 | SUCCESS | __main__:run_type_check:103 - ✅ TypeScript 类型检查通过
2025-12-17 23:23:07.345 | INFO | __main__:run_type_check:97 - 📋 Vue 严格类型检查
2025-12-17 23:23:07.345 | INFO | __main__:run_type_check:98 - 使用 pnpm 进行Vue 严格类型
2025-12-17 23:23:07.581 | SUCCESS | __main__:run_type_check:103 - ✅ Vue 严格类型检查通过
2025-12-17 23:23:07.582 | INFO | __main__:run_type_check:97 - 📋 Vue 文件类型检查
2025-12-17 23:23:07.582 | INFO | __main__:run_type_check:98 - 使用 npx 进行Vue 文件类型
2025-12-17 23:23:20.486 | SUCCESS | __main__:run_type_check:103 - ✅ Vue 文件类型检查通过
2025-12-17 23:23:20.486 | INFO | __main__:run_type_check:97 - 📋 Vue SFC 检查
2025-12-17 23:23:20.486 | INFO | __main__:run_type_check:98 - 使用 pnpm 进行Vue SFC
2025-12-17 23:23:20.683 | SUCCESS | __main__:run_type_check:103 - ✅ Vue SFC 检查通过
2025-12-17 23:23:20.683 | INFO | __main__:run_type_check:97 - 📋 Vite 构建类型检查
2025-12-17 23:23:20.683 | INFO | __main__:run_type_check:98 - 使用 npx 进行Vite 构建类型
vite v6.3.5 building for production...
Browserslist: browsers data (caniuse-lite) is 6 months old. Please run:
npx update-browserslist-db@latest
Why you should do it regularly: https://github.com/browserslist/update-db#readme
╭─────────────────────────────────────────────╮
│ 您好! 欢迎使用 pure-admin 开源项目 │
│ 我们为您精心准备了下面两个贴心的保姆级文档 │
│ https://pure-admin.cn │
│ https://pure-admin-utils.netlify.app │
╰─────────────────────────────────────────────╯
vite v6.3.5 building for production... (x2)
✓ 4 modules transformed.
✓ built in 86ms
✓ 2124 modules transformed.
dist/index.html 1.38 kB │ gzip: 0.79 kB
dist/static/png/bg-oEDCYcDF.png 17.47 kB
dist/static/css/index-CuXHOUNG.css 0.71 kB │ gzip: 0.29 kB
dist/static/css/index-BwpJ2zvG.css 0.76 kB │ gzip: 0.32 kB
dist/static/css/ServerStatusCard-BXWi_eVN.css 1.00 kB │ gzip: 0.41 kB
dist/static/css/index-CwweYm2b.css 1.05 kB │ gzip: 0.44 kB
dist/static/css/index-Dq2LWDcB.css 1.13 kB │ gzip: 0.50 kB
dist/static/css/index-CoW4IlgW.css 1.19 kB │ gzip: 0.48 kB
dist/static/css/index-lBbMo2Rz.css 1.45 kB │ gzip: 0.50 kB
dist/static/css/index-BU2_xh3l.css 1.51 kB │ gzip: 0.56 kB
dist/static/css/index-BZXwHqyH.css 1.64 kB │ gzip: 0.52 kB
dist/static/css/index-DELtkfT7.css 2.06 kB │ gzip: 0.69 kB
dist/static/css/index-DK-BFDeJ.css 2.09 kB │ gzip: 0.56 kB
dist/static/css/index-DLPS3bnu.css 2.35 kB │ gzip: 0.73 kB
dist/static/css/index-CsV-WVqV.css 6.71 kB │ gzip: 1.25 kB
dist/static/css/index-BoJncB2v.css 10.66 kB │ gzip: 2.66 kB
dist/static/css/index-vK_cPLDp.css 12.59 kB │ gzip: 1.84 kB
dist/static/css/index-BwuqdUXz.css 89.23 kB │ gzip: 8.91 kB
dist/static/css/index-DZHeCOjN.css 407.16 kB │ gzip: 62.13 kB
dist/static/js/sse-Dhjr6cTk.js 0.12 kB │ gzip: 0.13 kB
dist/static/js/fixed-menu-B7zLbfz-.js 0.23 kB │ gzip: 0.20 kB
dist/static/js/database-6w86ZeGl.js 0.23 kB │ gzip: 0.17 kB
dist/static/js/redirect-B--L8EPc.js 0.30 kB │ gzip: 0.24 kB
dist/static/js/time-DyQSDnlA.js 0.62 kB │ gzip: 0.35 kB
dist/static/js/domain-api-CAqJoWNM.js 0.84 kB │ gzip: 0.36 kB
dist/static/js/user-BXk2TImu.js 0.87 kB │ gzip: 0.46 kB
dist/static/js/data-formatter-1125vuTK.js 1.65 kB │ gzip: 0.70 kB
dist/static/js/sse-BuRURl0b.js 2.30 kB │ gzip: 0.80 kB
dist/static/js/index-Br2TOtv0.js 5.81 kB │ gzip: 2.04 kB
dist/static/js/index-uaiQm_YY.js 6.53 kB │ gzip: 2.29 kB
dist/static/js/index-DkmO5dFZ.js 7.50 kB │ gzip: 2.53 kB
dist/static/js/index-B66HAFaa.js 7.86 kB │ gzip: 3.01 kB
dist/static/js/index-BEE6bx05.js 9.97 kB │ gzip: 3.81 kB
dist/static/js/index-CKr8-tTK.js 10.32 kB │ gzip: 2.72 kB
dist/static/js/index-DVjMqkCd.js 10.85 kB │ gzip: 4.13 kB
dist/static/js/index-CWon3ikp.js 11.21 kB │ gzip: 3.70 kB
dist/static/js/403-DsJhAKRy.js 11.67 kB │ gzip: 5.12 kB
dist/static/js/404-1Ck2fgZx.js 12.77 kB │ gzip: 5.53 kB
dist/static/js/index-BJow6DFB.js 13.78 kB │ gzip: 4.38 kB
dist/static/js/500-Dmln0DMO.js 14.75 kB │ gzip: 5.91 kB
dist/static/js/dark-DmnHUM4t.js 15.58 kB │ gzip: 8.58 kB
dist/static/js/index-CTZitnQn.js 15.66 kB │ gzip: 5.04 kB
dist/static/js/index-DVbii3Zm.js 16.56 kB │ gzip: 5.70 kB
dist/static/js/index-DNWph3c8.js 19.16 kB │ gzip: 6.31 kB
dist/static/js/index-BPNaIIJB.js 25.95 kB │ gzip: 8.33 kB
dist/static/js/index-BDZNKtfQ.js 35.89 kB │ gzip: 10.44 kB
dist/static/js/index-BgIdC-wq.js 424.26 kB │ gzip: 182.96 kB
dist/static/js/index-BlmFNnW-.js 1,284.70 kB │ gzip: 430.59 kB
✓ built in 13.10s
╭───────────────────────────────────────────────────────────╮
│ 🎉 恭喜打包完成(总用时00分13秒,打包后的大小为2.42 MB) │
╰───────────────────────────────────────────────────────────╯
2025-12-17 23:23:39.111 | SUCCESS | __main__:run_type_check:103 - ✅ Vite 构建类型检查通过
2025-12-17 23:23:39.111 | INFO | __main__:run_type_check:110 - 📋 编译验证
2025-12-17 23:23:39.111 | INFO | __main__:run_type_check:111 - 类型检查通过,准备编译验证
2025-12-17 23:23:39.111 | INFO | __main__:start:299 - 📋 Vite 构建类型检查
2025-12-17 23:23:39.111 | INFO | __main__:start:300 - 使用 npx vite build --mode production 进行构建验证
vite v6.3.5 building for production...
Browserslist: browsers data (caniuse-lite) is 6 months old. Please run:
npx update-browserslist-db@latest
Why you should do it regularly: https://github.com/browserslist/update-db#readme
╭─────────────────────────────────────────────╮
│ 您好! 欢迎使用 pure-admin 开源项目 │
│ 我们为您精心准备了下面两个贴心的保姆级文档 │
│ https://pure-admin.cn │
│ https://pure-admin-utils.netlify.app │
╰─────────────────────────────────────────────╯
vite v6.3.5 building for production... (x2)
✓ 4 modules transformed.
✓ built in 88ms
✓ 2124 modules transformed.
dist/index.html 1.38 kB │ gzip: 0.79 kB
dist/static/png/bg-oEDCYcDF.png 17.47 kB
dist/static/css/index-CuXHOUNG.css 0.71 kB │ gzip: 0.29 kB
dist/static/css/index-BwpJ2zvG.css 0.76 kB │ gzip: 0.32 kB
dist/static/css/ServerStatusCard-BXWi_eVN.css 1.00 kB │ gzip: 0.41 kB
dist/static/css/index-CwweYm2b.css 1.05 kB │ gzip: 0.44 kB
dist/static/css/index-Dq2LWDcB.css 1.13 kB │ gzip: 0.50 kB
dist/static/css/index-CoW4IlgW.css 1.19 kB │ gzip: 0.48 kB
dist/static/css/index-lBbMo2Rz.css 1.45 kB │ gzip: 0.50 kB
dist/static/css/index-BU2_xh3l.css 1.51 kB │ gzip: 0.56 kB
dist/static/css/index-BZXwHqyH.css 1.64 kB │ gzip: 0.52 kB
dist/static/css/index-DELtkfT7.css 2.06 kB │ gzip: 0.69 kB
dist/static/css/index-DK-BFDeJ.css 2.09 kB │ gzip: 0.56 kB
dist/static/css/index-DLPS3bnu.css 2.35 kB │ gzip: 0.73 kB
dist/static/css/index-CsV-WVqV.css 6.71 kB │ gzip: 1.25 kB
dist/static/css/index-BoJncB2v.css 10.66 kB │ gzip: 2.66 kB
dist/static/css/index-vK_cPLDp.css 12.59 kB │ gzip: 1.84 kB
dist/static/css/index-BwuqdUXz.css 89.23 kB │ gzip: 8.91 kB
dist/static/css/index-DZHeCOjN.css 407.16 kB │ gzip: 62.13 kB
dist/static/js/sse-Dhjr6cTk.js 0.12 kB │ gzip: 0.13 kB
dist/static/js/fixed-menu-B7zLbfz-.js 0.23 kB │ gzip: 0.20 kB
dist/static/js/database-6w86ZeGl.js 0.23 kB │ gzip: 0.17 kB
dist/static/js/redirect-B--L8EPc.js 0.30 kB │ gzip: 0.24 kB
dist/static/js/time-DyQSDnlA.js 0.62 kB │ gzip: 0.35 kB
dist/static/js/domain-api-CAqJoWNM.js 0.84 kB │ gzip: 0.36 kB
dist/static/js/user-BXk2TImu.js 0.87 kB │ gzip: 0.46 kB
dist/static/js/data-formatter-1125vuTK.js 1.65 kB │ gzip: 0.70 kB
dist/static/js/sse-BuRURl0b.js 2.30 kB │ gzip: 0.80 kB
dist/static/js/index-Br2TOtv0.js 5.81 kB │ gzip: 2.04 kB
dist/static/js/index-uaiQm_YY.js 6.53 kB │ gzip: 2.29 kB
dist/static/js/index-DkmO5dFZ.js 7.50 kB │ gzip: 2.53 kB
dist/static/js/index-B66HAFaa.js 7.86 kB │ gzip: 3.01 kB
dist/static/js/index-BEE6bx05.js 9.97 kB │ gzip: 3.81 kB
dist/static/js/index-CKr8-tTK.js 10.32 kB │ gzip: 2.72 kB
dist/static/js/index-DVjMqkCd.js 10.85 kB │ gzip: 4.13 kB
dist/static/js/index-CWon3ikp.js 11.21 kB │ gzip: 3.70 kB
dist/static/js/403-DsJhAKRy.js 11.67 kB │ gzip: 5.12 kB
dist/static/js/404-1Ck2fgZx.js 12.77 kB │ gzip: 5.53 kB
dist/static/js/index-BJow6DFB.js 13.78 kB │ gzip: 4.38 kB
dist/static/js/500-Dmln0DMO.js 14.75 kB │ gzip: 5.91 kB
dist/static/js/dark-DmnHUM4t.js 15.58 kB │ gzip: 8.58 kB
dist/static/js/index-CTZitnQn.js 15.66 kB │ gzip: 5.04 kB
dist/static/js/index-DVbii3Zm.js 16.56 kB │ gzip: 5.70 kB
dist/static/js/index-DNWph3c8.js 19.16 kB │ gzip: 6.31 kB
dist/static/js/index-BPNaIIJB.js 25.95 kB │ gzip: 8.33 kB
dist/static/js/index-BDZNKtfQ.js 35.89 kB │ gzip: 10.44 kB
dist/static/js/index-BgIdC-wq.js 424.26 kB │ gzip: 182.96 kB
dist/static/js/index-BlmFNnW-.js 1,284.70 kB │ gzip: 430.59 kB
✓ built in 12.30s
╭───────────────────────────────────────────────────────────╮
│ 🎉 恭喜打包完成(总用时00分12秒,打包后的大小为2.42 MB) │
╰───────────────────────────────────────────────────────────╯
2025-12-17 23:23:55.804 | SUCCESS | __main__:start:304 - ✅ Vite 构建类型检查通过
2025-12-17 23:23:55.804 | INFO | __main__:check_bundle_size:163 - 📋 构建产物检查
2025-12-17 23:23:55.804 | INFO | __main__:check_bundle_size:164 - 检查构建产物体积
2025-12-17 23:23:55.822 | INFO | __main__:check_bundle_size:178 - ℹ️ 构建产物总大小: 2.42 MB
2025-12-17 23:23:55.822 | SUCCESS | __main__:check_bundle_size:184 - ✅ 构建产物大小正常
2025-12-17 23:23:55.822 | INFO | __main__:run_lint_check:215 - 📋 代码质量检查
2025-12-17 23:23:55.822 | INFO | __main__:run_lint_check:216 - 检查项目结构和关键文件
2025-12-17 23:23:55.823 | SUCCESS | __main__:run_lint_check:240 - ✅ 关键文件检查通过
2025-12-17 23:23:55.824 | INFO | __main__:run_lint_check:246 - ℹ️ 找到 17 个工具文件
2025-12-17 23:23:55.824 | INFO | __main__:run_dev_server_test:58 - 📋 开发服务器测试
2025-12-17 23:23:55.824 | INFO | __main__:run_dev_server_test:59 - 验证开发服务器可以正常启动
vite/6.3.5 win32-x64 node-v22.15.0
2025-12-17 23:23:57.285 | SUCCESS | __main__:run_dev_server_test:65 - ✅ Vite 开发服务器配置正常
2025-12-17 23:23:57.285 | SUCCESS | __main__:start:325 - 🎉 构建验证完成!
2025-12-17 23:23:57.285 | INFO | __main__:start:326 - 总耗时: 63.33 秒
2025-12-17 23:23:57.285 | SUCCESS | __main__:main:443 - ✅ 操作执行成功
2025-12-17 23:23:57.285 | INFO | __main__:main:457 - 切换回原始目录: D:\Code\gitee\go\系统\dns-go\pure-admin-thin-v6.0.0
PS D:\Code\gitee\go\系统\dns-go\pure-admin-thin-v6.0.0>