Fix Windows installation timeout with smart retry mechanism (#1071)

Problem:
- Windows users experiencing 10-minute timeout during first build
- Network detection didn't help users with low latency but slow downloads
- Native compilation and antivirus scanning make Windows builds slower

Solution:
1. Increase timeout: Windows 15min (from 10min), other platforms 10min (from 5min)
2. Smart retry: Auto-retry with CN mirror if first attempt times out
3. Better UX: Show expected time (10-15min for Windows first build)
4. Documentation: Add Windows timeout troubleshooting to FAQ

Technical changes:
- BaseBuilder.ts: Implement try-catch with automatic mirror fallback
- FAQ: Document the issue, causes, and solutions in both EN/CN
- User-friendly messages for first-time setup expectations

Fixes #1071
This commit is contained in:
Claude
2025-11-13 06:30:24 +00:00
parent 6e2c1c22bf
commit 07afdd8eeb
4 changed files with 200 additions and 37 deletions

View File

@@ -34,7 +34,8 @@ export default abstract class BaseBuilder {
}
private getInstallTimeout(): number {
return process.platform === 'win32' ? 600000 : 300000;
// Windows needs more time due to native compilation and antivirus scanning
return process.platform === 'win32' ? 900000 : 600000;
}
private getBuildTimeout(): number {
@@ -100,38 +101,74 @@ export default abstract class BaseBuilder {
const projectConf = path.join(rustProjectDir, 'config.toml');
await fsExtra.ensureDir(rustProjectDir);
// 智能检测可用的包管理器
// Detect available package manager
const packageManager = await this.detectPackageManager();
const registryOption = isChina
? ' --registry=https://registry.npmmirror.com'
: '';
// 根据包管理器类型设置依赖冲突解决选项
const registryOption = ' --registry=https://registry.npmmirror.com';
const peerDepsOption =
packageManager === 'npm' ? ' --legacy-peer-deps' : '';
const timeout = this.getInstallTimeout();
const buildEnv = this.getBuildEnvironment();
if (isChina) {
// Show helpful message for first-time users
if (!tauriTargetPathExists) {
logger.info(
`✺ Located in China, using ${packageManager}/rsProxy CN mirror.`,
);
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
await fsExtra.copy(projectCnConf, projectConf);
await shellExec(
`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`,
timeout,
buildEnv,
);
} else {
await shellExec(
`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`,
timeout,
buildEnv,
process.platform === 'win32'
? '✺ First-time setup may take 10-15 minutes on Windows (compiling dependencies)...'
: '✺ First-time setup may take 5-10 minutes (installing dependencies)...',
);
}
spinner.succeed(chalk.green('Package installed!'));
let usedMirror = isChina;
try {
if (isChina) {
logger.info(
`✺ Located in China, using ${packageManager}/rsProxy CN mirror.`,
);
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
await fsExtra.copy(projectCnConf, projectConf);
await shellExec(
`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`,
timeout,
buildEnv,
);
} else {
await shellExec(
`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`,
timeout,
buildEnv,
);
}
spinner.succeed(chalk.green('Package installed!'));
} catch (error: any) {
// If installation times out and we haven't tried the mirror yet, retry with mirror
if (error.message?.includes('timed out') && !usedMirror) {
spinner.fail(chalk.yellow('Installation timed out, retrying with CN mirror...'));
logger.info('✺ Retrying installation with CN mirror for better speed...');
const retrySpinner = getSpinner('Retrying installation...');
usedMirror = true;
try {
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
await fsExtra.copy(projectCnConf, projectConf);
await shellExec(
`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`,
timeout,
buildEnv,
);
retrySpinner.succeed(chalk.green('Package installed with CN mirror!'));
} catch (retryError) {
retrySpinner.fail(chalk.red('Installation failed'));
throw retryError;
}
} else {
spinner.fail(chalk.red('Installation failed'));
throw error;
}
}
if (!tauriTargetPathExists) {
logger.warn(
'✼ The first packaging may be slow, please be patient and wait, it will be faster afterwards.',