মিসিং এক্সপোর্টসের ঊর্ধ্বে: একটি আর্লি গারবেজ কালেক্টর তৈরি করা

Webpack ডকুমেন্টেশনের মিসিং লিঙ্কগুলো ঠিক করার জন্য আমি একটি স্ট্যান্ডার্ড প্লাগইন ব্যবহার করার চেষ্টা করেছিলাম। সেটি ব্যর্থ হয়েছিল।

একটি বড় কোডবেসে প্লাগইন ইন্টিগ্রেট করা সহজ কাজ নয়। এটি একটি আর্কিটেকচারাল চ্যালেঞ্জে পরিণত হয়েছিল। আমাকে Abstract Syntax Tree (AST) ম্যানিপুলেশন, মেমরি ব্যবহার এবং রিকার্সিভ লুপ (recursive loops) সামলাতে হয়েছিল।

স্ট্যান্ডার্ড প্লাগইনগুলোর সমস্যা

সমাধান খোঁজার জন্য আমি তিনটি পরীক্ষা চালিয়েছিলাম।

পরীক্ষা ১: প্লাগইনটি ১৩৫টি টাইপ রিকভার করেছিল। তবে, এটি সেগুলোকে একটি ইন্টারনাল মডিউলে রেখে দিয়েছিল। আমাদের টুল সেগুলোর জন্য একটি আলাদা ফোল্ডার তৈরি করেছিল। আমাদের সেগুলো ম্যানুয়ালি সর্ট করতে হয়েছিল। ডকুমেন্টেশনের গঠনও ভুল ছিল।

পরীক্ষা ২: আমি এক্সটারনাল টাইপগুলো হাইড করার জন্য একটি সেটিংস অন করেছিলাম। এটি কিছু ক্ষেত্রে কাজ করেছিল। এটি পেলোড কমিয়ে ৬০টি Webpack টাইপে নিয়ে এসেছিল। কিন্তু TypeDoc নেস্টেড ডিপেন্ডেন্সিগুলোকে (nested dependencies) উপেক্ষা করেছিল। এর ফলে অনেক টাইপ হাইড হয়ে থাকলেও সেগুলো মেমরি দখল করে রেখেছিল।

পরীক্ষা ৩: আমি টাইপগুলোকে তাদের আসল মডিউলে ম্যাপ করার চেষ্টা করেছিলাম। এর ফলে একটি রিকার্সিভ লুপ তৈরি হয়েছিল। প্লাগইনটি ক্রমাগত নেস্টেড ইন্টারফেসগুলো এক্সট্র্যাক্ট করতে থাকে যতক্ষণ না এটি ৬৩০টি টাইপ তৈরি করে। ডকুমেন্টেশনটি অপ্রয়োজনীয় তথ্যে (noise) ভরে গিয়েছিল। এটি ইউজার এক্সপেরিয়েন্স নষ্ট করে দিয়েছিল।

সমাধান: আর্লি গারবেজ কালেকশন (Early Garbage Collection)

অতিরিক্ত নয়েজ ছাড়াই আমার টাইপগুলোকে তাদের সঠিক মডিউলে প্রয়োজন ছিল। আমি আউটপুট ঠিক করার চেষ্টা করা বন্ধ করে প্রসেসটি ঠিক করা শুরু করলাম।

আমি EVENT_RESOLVE_END নামক একটি হুক ব্যবহার করেছি। এটি আমাকে রেজোলিউশনের ঠিক পরেই AST ইন্টারসেপ্ট করতে সাহায্য করেছে। TypeDoc ক্যাটাগরি অ্যাসাইন করার বা প্রচুর মেমরি ব্যবহারের আগেই আমি এটি করেছিলাম।

আমার লজিক তিনটি ধাপ অনুসরণ করেছিল:

ফলাফল: আমি ২৪০টি গুরুত্বপূর্ণ টাইপ রক্ষা করতে পেরেছি। সেগুলো এখন দৃশ্যমান এবং সঠিকভাবে রাউট করা হয়েছে। আমি তৃতীয় পরীক্ষার রিকার্সিভ নয়েজ এড়াতে পেরেছি।

শিক্ষা (Lessons Learned)

• AST দ্রুত হ্যান্ডেল করুন। অপ্রয়োজনীয় নোড সরিয়ে ফেললে পরবর্তীতে মেমরি অপচয় রোধ করা যায়। • হ্যাকের পরিবর্তে হুক ব্যবহার করুন। কম্পাইলার লাইফসাইকেল বুঝতে পারলে পরিচ্ছন্ন কাজ করা সম্ভব হয়। • ফিডব্যাক আর্কিটেকচার উন্নত করে। মেইনটেইনারদের রিভিউ আমাকে একটি উন্নত সিস্টেম তৈরি করতে সাহায্য করেছে। • বেশি ডেটা মানেই ভালো নয়। ভালো ইঞ্জিনিয়ারিং মানে হলো ডেটা এবং ইউজেবিলিটির মধ্যে ভারসাম্য বজায় রাখা।

মিসিং এক্সপোর্টসের ঊর্ধ্বে: Webpack-এর TypeDoc AST-এর জন্য একটি আর্লি গারবেজ কালেক্টর তৈরি করা

আধুনিক ওয়েব ডেভেলপমেন্টের জগতে, বিশেষ করে যখন আমরা বড় স্কেলের TypeScript প্রজেক্ট নিয়ে কাজ করি, তখন কোডবেসের পরিধি ক্রমাগত বাড়তে থাকে। এর সাথে সাথে একটি বড় সমস্যা দেখা দেয়: অব্যবহৃত এক্সপোর্টস (unused exports)। যদিও ts-prune বা depcheck-এর মতো টুলস বিদ্যমান, তবে সেগুলো প্রায়শই একটি Abstract Syntax Tree (AST)-এর গভীর সিম্যান্টিক বিশ্লেষণ করতে পারে না।

এই নিবন্ধে, আমি দেখাব কীভাবে TypeDoc-এর AST ব্যবহার করে একটি "আর্লি গারবেজ কালেক্টর" তৈরি করা যায়, যা Webpack বিল্ড প্রসেসের আরও আগে থেকেই অব্যবহৃত কোড শনাক্ত করতে পারে।

সমস্যাটি কী?

যখন একটি প্রজেক্ট বড় হয়, তখন ডেভেলপাররা প্রায়ই নতুন ফিচার যোগ করার সময় পুরনো ফাংশন বা টাইপগুলো এক্সপোর্ট করে রাখেন। পরবর্তীতে সেই ফিচারটি সরিয়ে ফেললেও, এক্সপোর্টগুলো কোডবেসে থেকে যায়। এগুলো কেবল কোডের আকারই বাড়ায় না, বরং ডেভেলপারদের মধ্যে বিভ্রান্তিও তৈরি করে।

সাধারণ টুলগুলো মডিউল লেভেলে কাজ করে, কিন্তু তারা অনেক সময় বুঝতে পারে না যে একটি নির্দিষ্ট এক্সপোর্টটি আসলে অন্য কোনো মডিউল থেকে ইমপোর্ট করা হয়েছে কি না, বিশেষ করে যখন ডাইনামিক ইমপোর্ট বা জটিল টাইপ রিলেশনশিপ থাকে।

AST কেন গুরুত্বপূর্ণ?

AST বা Abstract Syntax Tree হলো একটি কোড স্ট্রাকচারের রিপ্রেজেন্টেশন। এটি কোডকে কেবল টেক্সট হিসেবে দেখে না, বরং কোডের লজিক্যাল গঠন বুঝতে সাহায্য করে। TypeDoc-এর AST ব্যবহার করে আমরা প্রতিটি এক্সপোর্ট, ইমপোর্ট এবং তাদের মধ্যকার সম্পর্ককে একটি গ্রাফ আকারে দেখতে পারি।

TypeDoc-এর মাধ্যমে সমাধান

TypeDoc আমাদের কোডবেস থেকে একটি বিস্তারিত AST তৈরি করতে দেয়। আমরা এই AST-কে ট্রাভার্স (traverse) করে নিচের ধাপগুলো অনুসরণ করতে পারি:

  1. এক্সপোর্ট ম্যাপিং: সমস্ত এক্সপোর্টেড সিম্বল (ফাংশন, ক্লাস, ইন্টারফেস) সংগ্রহ করা।
  2. ইমপোর্ট ট্র্যাকিং: প্রতিটি মডিউল থেকে কী কী ইমপোর্ট করা হচ্ছে তা ট্র্যাক করা।
  3. ক্রস-রেফারেন্সিং: দেখা যে কোন এক্সপোর্টগুলো কোনো ইমপোর্ট স্টেটমেন্টের মাধ্যমে রেফারেন্স করা হয়নি।

ইমপ্লিমেন্টেশন কৌশল

আমরা একটি স্ক্রিপ্ট তৈরি করতে পারি যা TypeDoc API ব্যবহার করে প্রজেক্টটি পার্স করবে। নিচে একটি ধারণা দেওয়া হলো:

import { Application, Project } from 'typedoc';

async function findUnusedExports(entryPoints: string[]) {
  const app = new Application();
  const project = await app.convertProject(entryPoints);

  const exportedSymbols = new Set<string>();
  const importedSymbols = new Set<string>();

  // AST ট্রাভার্সাল লজিক এখানে থাকবে
  project.getReflections().forEach(reflection => {
    // এক্সপোর্ট শনাক্তকরণ
    if (reflection.flags & ReflectionFlags.Exported) {
      exportedSymbols.add(reflection.getSignature());
    }
    // ইমপোর্ট শনাক্তকরণ
    // ...
  });

  // পার্থক্য বের করা
  const unused = [...exportedSymbols].filter(s => !importedSymbols.has(s));
  console.log('Unused Exports:', unused);
}

Webpack-এর সাথে ইন্টিগ্রেশন

এই টুলটিকে একটি Webpack প্লাগইন হিসেবে তৈরি করা সম্ভব। বিল্ড প্রসেস শুরু হওয়ার আগেই এটি কোডবেস স্ক্যান করবে এবং যদি কোনো উল্লেখযোগ্য পরিমাণ অব্যবহৃত কোড পাওয়া যায়, তবে এটি ওয়ার্নিং বা এরর প্রদান করবে। এটি আমাদের "আর্লি গারবেজ কালেকশন" করার সুযোগ দেয়, যা প্রোডাকশন বান্ডেল সাইজ কমানোর জন্য অত্যন্ত কার্যকর।

উপসংহার

অব্যবহৃত কোড বা ডেড কোড (dead code) ম্যানেজ করা একটি বড় চ্যালেঞ্জ। TypeDoc-এর AST ব্যবহার করে আমরা কেবল সাধারণ টুলসের চেয়ে অনেক বেশি নির্ভুলভাবে এই সমস্যাটি সমাধান করতে পারি। এটি আমাদের কোডবেসকে ক্লিন রাখতে এবং Webpack বিল্ডকে আরও অপ্টিমাইজড করতে সাহায্য করে।