analyze-sites.tsโข6.69 kB
#!/usr/bin/env tsx
/**
* Analyze third-party impact on nicovideo.jp and goal.com
*
* Usage: pnpm tsx scripts/analyze-sites.ts
*/
import { executeL2ThirdPartyImpact } from '../src/tools/l2-third-party-impact.js';
async function analyzeSite(url: string, siteName: string) {
console.log(`\n${'='.repeat(60)}`);
console.log(` ${siteName} (${url})`);
console.log(`${'='.repeat(60)}\n`);
try {
// Step 1: Analyze third-party scripts
console.log('๐ Analyzing third-party scripts...\n');
const analysisResult = await executeL2ThirdPartyImpact({
url,
device: 'mobile',
compareMode: 'analyze',
gather: true,
});
if (analysisResult.analysis) {
const { summary, entities, impact } = analysisResult.analysis;
console.log('๐ Summary:');
console.log(` โข Third-party entities: ${summary.entityCount}`);
console.log(` โข Total blocking time: ${Math.round(summary.totalBlockingTime)}ms`);
console.log(` โข Total main thread time: ${Math.round(summary.totalMainThreadTime)}ms`);
console.log(` โข Total transfer size: ${Math.round(summary.totalTransferSize / 1024)}KB`);
console.log();
console.log('๐ฏ Estimated Impact:');
console.log(` โข Performance score impact: ${(impact.performanceScore * 100).toFixed(1)}%`);
console.log(` โข FCP impact: ${(impact.fcpImpact * 100).toFixed(1)}%`);
console.log(` โข LCP impact: ${(impact.lcpImpact * 100).toFixed(1)}%`);
console.log(` โข TBT impact: ${(impact.tbtImpact * 100).toFixed(1)}%`);
console.log();
console.log('๐ฅ Top 5 Performance Offenders:');
entities.slice(0, 5).forEach((entity, i) => {
const blockingRatio = entity.blockingTime / entity.mainThreadTime;
console.log(` ${i + 1}. ${entity.entity}`);
console.log(` โข Blocking: ${Math.round(entity.blockingTime)}ms (${(blockingRatio * 100).toFixed(1)}% of main thread)`);
console.log(` โข Transfer: ${Math.round(entity.transferSize / 1024)}KB`);
console.log(` โข Scripts: ${entity.subRequests.length}`);
});
console.log();
// Get high-impact domains for testing
const highImpactDomains: string[] = [];
for (const entity of entities.slice(0, 3)) {
for (const subRequest of entity.subRequests.slice(0, 3)) {
try {
const requestUrl = new URL(subRequest.url);
if (!highImpactDomains.includes(requestUrl.hostname)) {
highImpactDomains.push(requestUrl.hostname);
}
} catch {}
}
}
if (highImpactDomains.length > 0) {
console.log('๐ซ Testing with blocking top domains...\n');
console.log(` Blocking: ${highImpactDomains.slice(0, 5).join(', ')}`);
if (highImpactDomains.length > 5) {
console.log(` ... and ${highImpactDomains.length - 5} more`);
}
console.log();
// Compare with blocking
const compareResult = await executeL2ThirdPartyImpact({
url,
device: 'mobile',
compareMode: 'compare',
blockDomains: highImpactDomains.slice(0, 10),
gather: true,
});
if (compareResult.comparison) {
const { baseline, withThirdParty, impact: compareImpact } = compareResult.comparison;
console.log('โก Performance Comparison:');
console.log(' โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
console.log(' โ Metric โ With 3P โ Without 3P โ');
console.log(' โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค');
console.log(` โ Score โ ${(withThirdParty.score * 100).toFixed(0).padEnd(11)} โ ${(baseline.score * 100).toFixed(0).padEnd(12)} โ`);
console.log(` โ FCP (ms) โ ${withThirdParty.fcp.toFixed(0).padEnd(11)} โ ${baseline.fcp.toFixed(0).padEnd(12)} โ`);
console.log(` โ LCP (ms) โ ${withThirdParty.lcp.toFixed(0).padEnd(11)} โ ${baseline.lcp.toFixed(0).padEnd(12)} โ`);
console.log(` โ TBT (ms) โ ${withThirdParty.tbt.toFixed(0).padEnd(11)} โ ${baseline.tbt.toFixed(0).padEnd(12)} โ`);
console.log(` โ CLS โ ${withThirdParty.cls.toFixed(3).padEnd(11)} โ ${baseline.cls.toFixed(3).padEnd(12)} โ`);
console.log(' โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
console.log();
console.log('๐ Impact Summary:');
const scoreImprovement = compareImpact.scoreDelta * 100;
console.log(` โข Score: ${scoreImprovement > 0 ? '+' : ''}${scoreImprovement.toFixed(0)} points`);
console.log(` โข FCP: ${compareImpact.fcpDelta > 0 ? '+' : ''}${Math.round(compareImpact.fcpDelta)}ms`);
console.log(` โข LCP: ${compareImpact.lcpDelta > 0 ? '+' : ''}${Math.round(compareImpact.lcpDelta)}ms`);
console.log(` โข TBT: ${compareImpact.tbtDelta > 0 ? '+' : ''}${Math.round(compareImpact.tbtDelta)}ms`);
if (scoreImprovement > 10) {
console.log(`\n ๐ Significant improvement potential: ${scoreImprovement.toFixed(0)} points!`);
} else if (scoreImprovement > 5) {
console.log(`\n โ
Moderate improvement potential: ${scoreImprovement.toFixed(0)} points`);
} else {
console.log(`\n โน๏ธ Minor improvement potential: ${scoreImprovement.toFixed(0)} points`);
}
}
}
if (analysisResult.recommendations) {
console.log('\n๐ก Recommendations:');
analysisResult.recommendations.slice(0, 5).forEach(rec => {
console.log(` โข ${rec}`);
});
}
}
} catch (error) {
console.error(`โ Error analyzing ${siteName}:`, error);
}
}
async function main() {
console.log('๐ Third-Party Script Impact Analysis\n');
console.log('Analyzing two sites: nicovideo.jp and goal.com');
console.log('This will take several minutes...\n');
// Analyze nicovideo.jp
await analyzeSite('https://www.nicovideo.jp/', 'ใใณใใณๅ็ป');
// Analyze goal.com
await analyzeSite('https://www.goal.com/', 'Goal.com');
console.log(`\n${'='.repeat(60)}`);
console.log(' Analysis Complete');
console.log(`${'='.repeat(60)}\n`);
}
main().catch(console.error);