mirror of
https://github.com/asyouplz/SpeechNote.git
synced 2026-07-22 06:43:33 +00:00
* refactor: address PR #8004 review comments and fix lint errors * fix: address CI failures and code review feedback * Refactor: comprehensive fix for lint errors and type safety regressions * chore: trigger CI and Claude Code Review workflows
221 lines
7.7 KiB
JavaScript
221 lines
7.7 KiB
JavaScript
import esbuild from 'esbuild';
|
|
import process from 'process';
|
|
import builtins from 'builtin-modules';
|
|
import { promises as fs } from 'fs';
|
|
import path from 'path';
|
|
|
|
const banner = `/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
Optimized for Phase 4 Performance
|
|
*/`;
|
|
|
|
const prod = process.argv[2] === 'production';
|
|
const watch = !prod && process.argv[2] !== 'build';
|
|
const analyze = process.env.ANALYZE === 'true';
|
|
|
|
// Ensure output directory exists
|
|
const outdir = '.';
|
|
await fs.mkdir(outdir, { recursive: true });
|
|
|
|
// Phase 4 최적화 설정
|
|
const optimizationConfig = {
|
|
// Tree shaking 강화
|
|
treeShaking: true,
|
|
|
|
// 사용하지 않는 코드 제거
|
|
pure: prod ? ['console.log', 'console.debug', 'console.trace'] : [],
|
|
drop: prod ? ['debugger'] : [],
|
|
|
|
// 번들 분석용 메타데이터
|
|
metafile: analyze,
|
|
|
|
// 코드 스플리팅 설정
|
|
splitting: false, // Obsidian 플러그인은 단일 파일 필요
|
|
|
|
// 최적화 플래그
|
|
minify: prod,
|
|
minifyWhitespace: prod,
|
|
minifyIdentifiers: prod,
|
|
minifySyntax: prod,
|
|
|
|
// 소스맵 최적화
|
|
sourcemap: prod ? false : 'inline',
|
|
|
|
// 타겟 최적화
|
|
target: 'es2018',
|
|
|
|
// 번들 크기 경고
|
|
logLimit: 10,
|
|
};
|
|
|
|
const context = await esbuild.context({
|
|
banner: {
|
|
js: banner,
|
|
},
|
|
entryPoints: ['src/main.ts'],
|
|
bundle: true,
|
|
external: [
|
|
'obsidian',
|
|
'electron',
|
|
'@codemirror/autocomplete',
|
|
'@codemirror/collab',
|
|
'@codemirror/commands',
|
|
'@codemirror/language',
|
|
'@codemirror/lint',
|
|
'@codemirror/search',
|
|
'@codemirror/state',
|
|
'@codemirror/view',
|
|
'@lezer/common',
|
|
'@lezer/highlight',
|
|
'@lezer/lr',
|
|
...builtins,
|
|
],
|
|
format: 'cjs',
|
|
outfile: 'main.js',
|
|
logLevel: 'info',
|
|
|
|
// Phase 4 최적화 적용
|
|
...optimizationConfig,
|
|
|
|
define: {
|
|
'process.env.NODE_ENV': prod ? '"production"' : '"development"',
|
|
'process.env.PERFORMANCE_MONITORING': '"enabled"',
|
|
},
|
|
|
|
plugins: [
|
|
{
|
|
name: 'clean',
|
|
setup(build) {
|
|
build.onStart(async () => {
|
|
// Clean previous build artifacts
|
|
const filesToClean = ['main.js', 'main.js.map', 'meta.json'];
|
|
for (const file of filesToClean) {
|
|
try {
|
|
await fs.unlink(file);
|
|
} catch (e) {
|
|
// File doesn't exist, ignore
|
|
}
|
|
}
|
|
});
|
|
},
|
|
},
|
|
{
|
|
name: 'bundle-size-checker',
|
|
setup(build) {
|
|
build.onEnd(async (result) => {
|
|
if (result.errors.length > 0) return;
|
|
|
|
try {
|
|
const stats = await fs.stat('main.js');
|
|
const sizeKB = (stats.size / 1024).toFixed(2);
|
|
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
|
|
|
|
console.log(`📦 Bundle size: ${sizeKB} KB (${sizeMB} MB)`);
|
|
|
|
// Phase 4 목표: 초기 번들 < 150KB
|
|
const targetSize = 150 * 1024; // 150KB in bytes
|
|
|
|
if (stats.size > targetSize) {
|
|
console.warn(`⚠️ Bundle size exceeds target of 150KB!`);
|
|
console.warn(` Current: ${sizeKB} KB`);
|
|
console.warn(` Target: 150.00 KB`);
|
|
console.warn(
|
|
` Excess: ${((stats.size - targetSize) / 1024).toFixed(2)} KB`
|
|
);
|
|
} else {
|
|
console.log(`✅ Bundle size is within target (< 150KB)`);
|
|
}
|
|
|
|
// 메타데이터 분석
|
|
if (analyze && result.metafile) {
|
|
await fs.writeFile(
|
|
'meta.json',
|
|
JSON.stringify(result.metafile, null, 2)
|
|
);
|
|
console.log('📊 Bundle analysis saved to meta.json');
|
|
|
|
// 주요 모듈 크기 분석
|
|
const outputs = result.metafile.outputs;
|
|
const inputs = result.metafile.inputs;
|
|
|
|
console.log('\n📈 Top 10 largest modules:');
|
|
const modules = Object.entries(inputs)
|
|
.map(([path, info]) => ({
|
|
path: path.replace('src/', ''),
|
|
size: info.bytes,
|
|
}))
|
|
.sort((a, b) => b.size - a.size)
|
|
.slice(0, 10);
|
|
|
|
modules.forEach((module, index) => {
|
|
const sizeKB = (module.size / 1024).toFixed(2);
|
|
console.log(` ${index + 1}. ${module.path}: ${sizeKB} KB`);
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to check bundle size:', error);
|
|
}
|
|
});
|
|
},
|
|
},
|
|
{
|
|
name: 'performance-hints',
|
|
setup(build) {
|
|
build.onEnd((result) => {
|
|
if (result.errors.length > 0) {
|
|
console.error('❌ Build failed with errors:');
|
|
result.errors.forEach((error) => {
|
|
console.error(error);
|
|
});
|
|
} else if (result.warnings.length > 0) {
|
|
console.warn('⚠️ Build succeeded with warnings:');
|
|
result.warnings.forEach((warning) => {
|
|
console.warn(warning);
|
|
});
|
|
} else {
|
|
const time = new Date().toLocaleTimeString();
|
|
console.log(`✅ Build succeeded at ${time}`);
|
|
|
|
if (prod) {
|
|
console.log('\n💡 Performance optimization tips:');
|
|
console.log(' - Consider lazy loading for non-critical components');
|
|
console.log(' - Review large dependencies for alternatives');
|
|
console.log(' - Enable caching for API responses');
|
|
console.log(' - Monitor runtime memory usage');
|
|
}
|
|
}
|
|
});
|
|
},
|
|
},
|
|
],
|
|
});
|
|
|
|
if (prod) {
|
|
// Production build with optimization report
|
|
console.log('🚀 Starting optimized production build...');
|
|
await context.rebuild();
|
|
|
|
// Generate optimization report
|
|
console.log('\n📋 Optimization Report:');
|
|
console.log(' ✅ Tree shaking: Enabled');
|
|
console.log(' ✅ Minification: Enabled');
|
|
console.log(' ✅ Dead code elimination: Enabled');
|
|
console.log(' ✅ Console statements: Removed');
|
|
|
|
console.log('\n🎯 Phase 4 Performance Targets:');
|
|
console.log(' - Initial bundle: < 150KB');
|
|
console.log(' - Total bundle: < 400KB');
|
|
console.log(' - TTI: < 2 seconds');
|
|
console.log(' - Memory usage: < 50MB');
|
|
|
|
process.exit(0);
|
|
} else if (watch) {
|
|
// Development with watch mode
|
|
console.log('👀 Watching for changes with performance monitoring...');
|
|
await context.watch();
|
|
} else {
|
|
// Single development build
|
|
await context.rebuild();
|
|
console.log('✅ Development build complete');
|
|
await context.dispose();
|
|
}
|