File size: 5,484 Bytes
98ace4c
 
20c5151
 
 
 
98ace4c
 
20c5151
98ace4c
 
 
 
 
 
 
20c5151
 
98ace4c
 
 
 
20c5151
98ace4c
 
 
 
 
 
 
 
 
20c5151
 
98ace4c
 
 
 
 
 
 
20c5151
 
98ace4c
 
20c5151
98ace4c
20c5151
98ace4c
 
 
 
 
 
 
 
 
 
 
 
 
20c5151
98ace4c
20c5151
98ace4c
 
 
20c5151
98ace4c
 
 
20c5151
98ace4c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20c5151
98ace4c
 
 
20c5151
 
98ace4c
 
 
20c5151
98ace4c
20c5151
98ace4c
 
 
 
 
 
20c5151
 
98ace4c
 
 
 
 
 
20c5151
 
98ace4c
 
 
 
 
 
20c5151
 
98ace4c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// 📊 Script de Análise de Performance do Bundle
// Analisa o tamanho dos arquivos e identifica oportunidades de otimização

const fs = require('fs');
const path = require('path');

console.log('🔍 ANÁLISE DE PERFORMANCE DO BUNDLE\n');
console.log('═'.repeat(80));

// Função para calcular tamanho legível
function formatBytes(bytes) {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
}

// Função para analisar arquivo
function analyzeFile(filePath) {
    const stats = fs.statSync(filePath);
    const content = fs.readFileSync(filePath, 'utf8');
    
    return {
        path: filePath,
        size: stats.size,
        sizeFormatted: formatBytes(stats.size),
        lines: content.split('\n').length,
        characters: content.length,
        // Estimativa de tamanho gzipped (aproximadamente 30% do original para texto)
        gzipEstimate: formatBytes(Math.round(stats.size * 0.3))
    };
}

// Arquivos principais para análise
const filesToAnalyze = [
    'public/app.js',
    'public/styles.css',
    'public/index.html',
    'public/sw.js',
    'public/manifest.json'
];

let totalSize = 0;
const results = [];

console.log('\n📁 ARQUIVOS PRINCIPAIS:\n');

filesToAnalyze.forEach(file => {
    try {
        const analysis = analyzeFile(file);
        results.push(analysis);
        totalSize += analysis.size;
        
        console.log(`📄 ${path.basename(file)}`);
        console.log(`   Tamanho: ${analysis.sizeFormatted}`);
        console.log(`   Linhas: ${analysis.lines.toLocaleString()}`);
        console.log(`   Gzip (est.): ${analysis.gzipEstimate}`);
        console.log('');
    } catch (error) {
        console.log(`⚠️  ${file} - Arquivo não encontrado`);
    }
});

console.log('─'.repeat(80));
console.log(`\n📊 TOTAL: ${formatBytes(totalSize)}`);
console.log(`📦 GZIP ESTIMADO: ${formatBytes(Math.round(totalSize * 0.3))}`);

// Análise de app.js para identificar oportunidades
console.log('\n═'.repeat(80));
console.log('🔬 ANÁLISE DETALHADA DO app.js\n');

try {
    const appJs = fs.readFileSync('public/app.js', 'utf8');
    
    // Contar funções
    const functionCount = (appJs.match(/function\s+\w+/g) || []).length;
    const arrowFunctionCount = (appJs.match(/=>\s*{/g) || []).length;
    const classCount = (appJs.match(/class\s+\w+/g) || []).length;
    
    // Contar comentários
    const commentLines = (appJs.match(/\/\/.+|\/\*[\s\S]*?\*\//g) || []).length;
    
    // Contar imports/requires (se houver)
    const imports = (appJs.match(/import\s+.+from|require\(.+\)/g) || []).length;
    
    console.log(`📦 Classes: ${classCount}`);
    console.log(`🔧 Funções: ${functionCount}`);
    console.log(`➡️  Arrow Functions: ${arrowFunctionCount}`);
    console.log(`💬 Comentários: ${commentLines}`);
    console.log(`📥 Imports: ${imports}`);
    
    // Análise de strings grandes (possíveis JSON embutidos)
    const largeStrings = appJs.match(/['"`][\s\S]{500,}['"`]/g) || [];
    if (largeStrings.length > 0) {
        console.log(`\n⚠️  ${largeStrings.length} strings grandes encontradas (>500 chars)`);
        console.log(`   Considere mover para arquivos JSON externos`);
    }
    
} catch (error) {
    console.log('⚠️  Erro ao analisar app.js');
}

// Recomendações
console.log('\n═'.repeat(80));
console.log('💡 RECOMENDAÇÕES DE OTIMIZAÇÃO\n');

const recommendations = [];

if (totalSize > 300000) {
    recommendations.push({
        priority: 'ALTA',
        issue: 'Bundle muito grande (>300KB)',
        solution: 'Implementar code splitting e lazy loading'
    });
}

if (results.find(r => r.path.includes('app.js') && r.size > 150000)) {
    recommendations.push({
        priority: 'ALTA',
        issue: 'app.js muito grande (>150KB)',
        solution: 'Dividir em módulos menores e carregar sob demanda'
    });
}

if (results.find(r => r.path.includes('styles.css') && r.size > 50000)) {
    recommendations.push({
        priority: 'MÉDIA',
        issue: 'styles.css grande (>50KB)',
        solution: 'Remover CSS não utilizado com PurgeCSS'
    });
}

recommendations.push({
    priority: 'MÉDIA',
    issue: 'Sem minificação',
    solution: 'Implementar minificação com Terser (JS) e cssnano (CSS)'
});

recommendations.push({
    priority: 'ALTA',
    issue: 'Sem compressão Gzip/Brotli',
    solution: 'Configurar compressão no servidor'
});

recommendations.push({
    priority: 'BAIXA',
    issue: 'Otimização de imagens',
    solution: 'Converter SVGs para WebP quando apropriado'
});

recommendations.forEach((rec, index) => {
    console.log(`${index + 1}. [${rec.priority}] ${rec.issue}`);
    console.log(`   💡 ${rec.solution}\n`);
});

console.log('═'.repeat(80));
console.log('\n✅ Análise completa! Execute os scripts de otimização para melhorar o desempenho.\n');

// Salvar relatório em JSON
const report = {
    timestamp: new Date().toISOString(),
    files: results,
    totalSize: totalSize,
    totalSizeFormatted: formatBytes(totalSize),
    gzipEstimate: formatBytes(Math.round(totalSize * 0.3)),
    recommendations: recommendations
};

fs.writeFileSync('scripts/bundle-analysis.json', JSON.stringify(report, null, 2));
console.log('📄 Relatório salvo em: scripts/bundle-analysis.json\n');