𝗕𝗲𝘆𝗼𝗻𝗱 𝗠𝗶𝘀𝘀𝗶𝗻𝗴 𝗘𝘅𝗽𝗼𝗿𝘁𝘀: 𝗕𝘂𝗶𝗹𝗱𝗶𝗻𝗴 𝗮𝗻 𝗘𝗮𝗿𝗹𝘆 𝗚𝗮𝗿𝗯𝗮𝗴𝗲 𝗖𝗼𝗹𝗹𝗲𝗰𝘁𝗼𝗿
I tried to use a standard plugin to fix missing links in Webpack documentation. It failed.
Integrating a plugin into a large codebase is not a simple task. It became an architectural challenge. I had to manage Abstract Syntax Tree (AST) manipulation, memory use, and recursive loops.
The Problem with Standard Plugins
I ran three experiments to find a solution.
Experiment 1: The plugin recovered 135 types. However, it put them in an internal module. Our tool created a separate folder for them. We had to sort them manually. The documentation was also structurally wrong.
Experiment 2: I turned on a setting to hide external types. This worked for some things. It reduced the payload to 60 Webpack types. But TypeDoc ignored nested dependencies. It left many types hidden while they still used memory.
Experiment 3: I tried to map types back to their original modules. This caused a recursive loop. The plugin kept extracting nested interfaces until it created 630 types. The documentation was full of noise. It ruined the user experience.
The Solution: Early Garbage Collection
I needed the types in their correct modules without the extra noise. I stopped trying to fix the output and started fixing the process.
I used a hook called EVENT_RESOLVE_END. This let me intercept the AST right after resolution. I did this before TypeDoc assigned categories or used heavy memory.
My logic followed three steps:
- Find the internal module in the AST.
- Check every node using a custom utility.
- Delete the noise. I used project.removeReflection to delete 300 unneeded nodes immediately. This let Node.js free the memory.
- Move the important types. I merged the remaining 300 types into the root scope.
The result: I saved 240 vital types. They are now visible and correctly routed. I avoided the recursive noise of the third experiment.
Lessons Learned
• Handle ASTs early. Removing unneeded nodes prevents memory waste later. • Use hooks instead of hacks. Understanding the compiler lifecycle allows for clean work. • Feedback improves architecture. Maintainer reviews helped me build a better system. • More data is not better. Good engineering means finding the balance between data and usability.
מעבר ל-Missing Exports: בניית Garbage Collector מוקדם עבור ה-TypeDoc AST של Webpack
בעבודה על פרויקטים גדולים של TypeScript, אחת הבעיות הנפוצות ביותר היא הצטברות של "קוד מת" (dead code) — ובמיוחד, ייצואים (exports) של פונקציות, מחלקות או טיפוסים שאינם בשימוש יותר בשום מקום בתוך קוד המקור.
האתגר
בעוד שכלים כמו ts-prune או ה-Tree shaking של Webpack עוזרים, הם פועלים לעיתים קרובות בשלבים שונים של תהליך ה-build. Tree shaking מתבצע במהלך ה-bundling, מה שלעיתים קרובות הוא "מאוחר מדי" עבור מפתחים שרוצים לנקות את קוד המקור שלהם עוד לפני שהוא מגיע ל-bundler.
הפתרון: Garbage Collector מוקדם
הרעיון הוא לבנות כלי שירוץ בשלב מוקדם יותר בתהליך ה-build, וישתמש ב-AST (Abstract Syntax Tree) של TypeDoc כדי לזהות ייצואים שאינם מקושרים לשום מקום אחר.
למה להשתמש ב-TypeDoc?
TypeDoc מספק גישה עשירה למבנה הטיפוסים של הפרויקט. בניגוד לכלים שמנתחים רק תחביר (syntax), TypeDoc מבין את הקשרים בין הטיפוסים השונים, מה שמאפשר לנו לבצע ניתוח מדויק יותר של ה-exports.
מימוש
התהליך כולל מעבר על ה-AST וזיהוי של כל ה-Symbols שיוצאים. לאחר מכן, אנחנו בודקים אם לכל אחד מהם יש ייחוס (reference) בתוך הפרויקט.
// דוגמה ללוגיקה של מעבר על ה-AST
typeDoc.api.forEach(item => {
if (item.isExported && !item.isUsed) {
console.log(`Unused export found: ${item.name}`);
}
});
על ידי שילוב הכלי הזה בתוך תהליך ה-Webpack, אנחנו יכולים לקבל התרעות בזמן אמת על קוד מיותר, מה שמאפשר תחזוקה קלה יותר של קוד המקור ושמירה על פרויקט נקי ומהודק.
סיכום
בניית Garbage Collector מוקדם מבוסס AST מאפשרת לנו לעבור מעבר לזיהוי פשוט של "Missing Exports" ולבנות מערכת חכמה שמזהה קוד מת בשלבים מוקדמים של הפיתוח, לפני שהוא בכלל הופך לחלק מה-bundle הסופי.