/** * JNote 后端分发包打包脚本 * 在 Windows 上运行,打包 Linux 和 Windows 两个版本 * 优化:Linux 生成 sh 脚本,Windows 生成 bat 脚本,原生直接执行 */ const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const os = require('os'); const serverDir = __dirname; const isWindows = os.platform() === 'win32'; function log(msg) { console.log(`[Package] ${msg}`); } function run(cmd) { log(`执行: ${cmd}`); execSync(cmd, { cwd: serverDir, stdio: 'inherit' }); } function main() { console.log('========================================='); console.log(' JNote 后端分发包打包工具'); console.log(` 当前平台: ${isWindows ? 'Windows' : 'Linux'}`); console.log('========================================='); // 检查 Node.js 环境 try { const nodeVersion = execSync('node --version', { encoding: 'utf8' }).trim(); log(`✓ Node.js 版本: ${nodeVersion}`); } catch { console.error('❌ 错误: 未找到 Node.js'); process.exit(1); } // 安装依赖 console.log(''); log('📦 安装依赖...'); run('npm install'); // 安装 pkg (如果未安装) try { execSync('pkg --version', { encoding: 'utf8', stdio: 'ignore' }); log('✓ pkg 已安装'); } catch { console.log(''); log('📦 安装 pkg...'); run('npm install -g pkg'); } // 创建输出目录 const distDir = path.join(serverDir, 'dist'); const releaseDir = path.join(serverDir, 'release'); // 清空并重建目录 if (fs.existsSync(distDir)) fs.rmSync(distDir, { recursive: true, force: true }); if (fs.existsSync(releaseDir)) fs.rmSync(releaseDir, { recursive: true, force: true }); fs.mkdirSync(distDir, { recursive: true }); fs.mkdirSync(releaseDir, { recursive: true }); const releaseLinux = path.join(releaseDir, 'linux'); const releaseWindows = path.join(releaseDir, 'windows'); fs.mkdirSync(releaseLinux, { recursive: true }); fs.mkdirSync(releaseWindows, { recursive: true }); // 打包 Linux 版本(适配你的 Node16) console.log(''); log('🔨 打包 Linux 版本...'); run('pkg src/index.js --targets node16-linux-x64 --output dist/jnote-api'); // 打包 Windows 版本(适配你的 Node16) console.log(''); log('🔨 打包 Windows 版本...'); run('pkg src/index.js --targets node16-win-x64 --output dist/jnote-api.exe'); // ===================== 核心优化 ===================== // 1. 复制 Linux 可执行文件 + 生成 .sh 启动脚本 const linuxExe = path.join(distDir, 'jnote-api'); if (fs.existsSync(linuxExe)) { const targetLinuxExe = path.join(releaseLinux, 'jnote-api'); fs.copyFileSync(linuxExe, targetLinuxExe); fs.chmodSync(targetLinuxExe, 0o755); // 生成 Linux 原生启动脚本 start.sh const shScript = `#!/bin/bash # JNote 后端服务启动脚本 cd "$(dirname "$0")" ./jnote-api `; const shPath = path.join(releaseLinux, 'start.sh'); fs.writeFileSync(shPath, shScript, 'utf8'); fs.chmodSync(shPath, 0o755); // 赋可执行权限 log('✓ linux/jnote-api + start.sh (可直接执行)'); } // 2. 复制 Windows 可执行文件 + 生成 .bat 启动脚本 const winExe = path.join(distDir, 'jnote-api.exe'); if (fs.existsSync(winExe)) { fs.copyFileSync(winExe, path.join(releaseWindows, 'jnote-api.exe')); // 生成 Windows 原生启动脚本 start.bat const batScript = `@echo off :: JNote 后端服务启动脚本 cd /d "%~dp0" jnote-api.exe pause `; const batPath = path.join(releaseWindows, 'start.bat'); // ✅ 修复:Node16 兼容 UTF-8 编码 fs.writeFileSync(batPath, batScript, 'utf8'); log('✓ windows/jnote-api.exe + start.bat (双击运行)'); } // ==================================================== // 复制环境配置 const envSrc = path.join(serverDir, '.env'); const defaultEnv = `# 数据库配置 DB_HOST=localhost DB_PORT=3306 DB_USER=root DB_PASSWORD=your_password DB_NAME=jnote # RUSTFS 对象存储配置 RUSTFS_ENDPOINT=http://localhost:9001 RUSTFS_BUCKET=setting RUSTFS_ACCESS_KEY=rustfsadmin RUSTFS_SECRET_KEY=rustfsadmin # 服务器配置 PORT=3000 `; if (fs.existsSync(envSrc)) { fs.copyFileSync(envSrc, path.join(releaseLinux, '.env')); fs.copyFileSync(envSrc, path.join(releaseLinux, '.env.example')); fs.copyFileSync(envSrc, path.join(releaseWindows, '.env')); fs.copyFileSync(envSrc, path.join(releaseWindows, '.env.example')); } else { fs.writeFileSync(path.join(releaseLinux, '.env'), defaultEnv, 'utf8'); fs.writeFileSync(path.join(releaseWindows, '.env'), defaultEnv, 'utf8'); } log('✓ .env 配置文件生成完成'); // 创建 README const readme = `JNote 后端服务部署说明 ===================== 目录结构: ├── linux/ # Linux 服务器部署包 │ ├── jnote-api # Linux 可执行二进制文件 │ ├── start.sh # Linux 原生启动脚本 │ └── .env # 环境配置 │ └── windows/ # Windows 服务器部署包 ├── jnote-api.exe # Windows 可执行程序 ├── start.bat # Windows 原生启动脚本 └── .env # 环境配置 部署步骤: 【Linux 服务器】 1. 上传 linux/ 目录到服务器 2. 修改 .env 中的数据库配置 3. 直接运行: ./start.sh 【Windows 服务器】 1. 上传 windows/ 目录到服务器 2. 修改 .env 中的数据库配置 3. 双击运行 start.bat 即可 `; fs.writeFileSync(path.join(releaseDir, 'README.txt'), readme, 'utf8'); log('✓ README.txt 生成完成'); // 清理临时文件 console.log(''); log('🧹 清理临时文件...'); try { fs.unlinkSync(linuxExe); } catch {} try { fs.unlinkSync(winExe); } catch {} try { fs.rmSync(distDir, { recursive: true, force: true }); } catch {} console.log(''); console.log('========================================='); console.log(' 打包完成!'); console.log('========================================='); console.log(`分发包目录: ${releaseDir}`); } main();