انتقال Puppeteer به TypeScript

اینجا ثبت‌نام کنید.

ما در تیم DevTools طرفداران پر و پا قرص TypeScript هستیم—به‌طوری که کد جدید در DevTools با آن نوشته می‌شود و درحال انجام یک مهاجرت بزرگ برای بررسی نوع کل پایگاه کد با TypeScript هستیم. می‌توانید درباره این انتقال در صحبت‌های ما در «نشست توسعه‌دهندگان Chrome در سال ۲۰۲۰» بیشتر بدانید. بنابراین، منطقی بود که به انتقال پایگاه کد Puppeteer به TypeScript نیز نگاه کنیم.

درحال برنامه‌ریزی برای انتقال

هنگام برنامه‌ریزی برای نحوه انتقال، می‌خواستیم بتوانیم در مراحل کوچک پیشرفت کنیم. این کار سربار انتقال را پایین نگه می‌دارد—در هر زمان فقط روی بخش کوچکی از کد کار می‌کنید—و خطر را نیز پایین نگه می‌دارد. اگر مشکلی در یکی از مراحل پیش آمد، به‌راحتی می‌توانید آن را برگردانید. ‫Puppeteer کاربران زیادی دارد و نسخه معیوب آن برای بسیاری از آن‌ها مشکل ایجاد می‌کند، بنابراین بسیار مهم بود که خطر تغییرات مخرب را به حداقل برسانیم.

همچنین خوش‌شانس بودیم که Puppeteer مجموعه قدرتمندی از آزمون‌های واحد دارد که همه عملکردهای آن را پوشش می‌دهد. این یعنی می‌توانستیم مطمئن باشیم که هنگام انتقال کد، آن را خراب نمی‌کنیم و همچنین تغییراتی در «میانای برنامه‌سازی کاربردی» خود ایجاد نمی‌کنیم. هدف از انتقال این بود که آن را بدون اینکه حتی کاربران Puppeteer متوجه شوند که انتقال داده‌ایم تکمیل کنیم، و آزمایش‌ها بخش حیاتی این استراتژی بودند. اگر پوشش آزمایشی خوبی نداشتیم، آن را قبل‌از ادامه مهاجرت اضافه می‌کردیم.

انجام هرگونه تغییر کد بدون آزمایش خطرناک است، اما تغییراتی که در آن کل فایل‌ها یا کل پایگاه کد را لمس می‌کنید، به‌ویژه خطرناک است. هنگام ایجاد تغییرات مکانیکی، به‌راحتی ممکن است مرحله‌ای را از قلم بیندازید و در موارد متعدد، آزمایش‌ها مشکلی را شناسایی کردند که هم از دید مجری و هم از دید بازبین پنهان مانده بود.

یکی از مواردی که از ابتدا برای آن زمان صرف کردیم، راه‌اندازی یکپارچه‌سازی مداوم (CI) بود. متوجه شدیم که اجرای CI دربرابر درخواست‌های واکشی ناپایدار بود و اغلب ناموفق بود. این اتفاق آنقدر زیاد افتاد که به این عادت کردیم که CI خود را نادیده بگیریم و درخواست‌های کشش را درهرصورت ادغام کنیم، با این فرض که خرابی یک مشکل یک‌باره در CI است نه مشکلی در Puppeteer.

پس‌از انجام برخی تعمیرات عمومی و اختصاص دادن زمان برای رفع برخی‌از ناپایداری‌های معمول در آزمایش، آن را به وضعیت بسیار پایدارتری رساندیم که به ما امکان داد به CI گوش دهیم و بدانیم که شکست نشان‌دهنده یک مشکل واقعی است. این کار چندان جذاب نیست و تماشای اجراهای بی‌پایان CI خسته‌کننده است، اما با توجه به تعداد درخواست‌های واکشی که انتقال به آن وارد می‌کرد، داشتن مجموعه آزمایشی که به‌طور قابل‌اعتماد اجرا شود حیاتی بود.

انتخاب و فرود یک فایل

در این مرحله، انتقال ما آماده اجرا بود و سرور CI قدرتمندی داشتیم که پر از آزمایش‌هایی بود که از ما پشتیبانی می‌کردند. به‌جای اینکه هر فایل دلخواهی را انتخاب کنیم، به‌طور هدفمند فایل کوچکی را برای انتقال انتخاب کردیم. این تمرین مفیدی است زیرا به شما امکان می‌دهد فرایند برنامه‌ریزی‌شده‌ای را که درحال انجام آن هستید تأیید کنید. اگر روی این فایل کار کند، رویکرد شما معتبر است؛ اگر نه، می‌توانید به مرحله طراحی برگردید.

علاوه‌براین، بررسی فایل‌به‌فایل (و با نسخه‌های منظم Puppeteer، به‌طوری‌که همه تغییرات در یک نسخه npm ارسال نشدند) ریسک را کاهش داد. ‫DeviceDescriptors.js را به‌عنوان اولین فایل انتخاب کردیم، زیرا یکی از ساده‌ترین فایل‌ها در پایگاه کد بود. انجام همه این کارهای آماده‌سازی و اعمال چنین تغییر کوچکی ممکن است کمی ناامیدکننده باشد، اما هدف این نیست که بلافاصله تغییرات بزرگی ایجاد کنیم، بلکه هدف این است که با احتیاط و به‌صورت روشمند فایل به فایل پیش برویم. زمانی که برای اعتبارسنجی رویکرد صرف می‌شود، قطعاً در ادامه فرایند انتقال، زمانی که به فایل‌های پیچیده‌تر می‌رسید، صرفه‌جویی در زمان را به‌همراه خواهد داشت.

الگو را ثابت کنید و تکرار کنید

خوشبختانه تغییر DeviceDescriptors.js باموفقیت به پایگاه کد اضافه شد و طرح همان‌طور که امیدوار بودیم کار کرد! در این مرحله، آماده‌اید که آستین‌ها را بالا بزنید و کار را شروع کنید، که دقیقاً همان کاری است که ما کردیم. استفاده از برچسب GitHub روشی بسیار خوب برای گروه‌بندی همه درخواست‌های کشیدن با هم است و ما این روش را برای پیگیری پیشرفت مفید یافتیم.

آن را انتقال دهید و بعداً بهبود دهید

برای هر فایل JavaScript، فرایند ما به این صورت بود:

  1. نام فایل را از .js به .ts تغییر دهید.
  2. مترجم TypeScript را اجرا کنید.
  3. هرگونه مشکل را رفع کنید.
  4. درخواست کشیدن را ایجاد کنید.

بیشتر کار در این درخواست‌های اولیه کشیدن، استخراج میاناهای TypeScript برای ساختارهای داده موجود بود. درمورد اولین درخواست واکشی که DeviceDescriptors.js را منتقل کرد و قبلاً درباره آن صحبت کردیم، کد از این حالت:

module.exports = [
  { 
    name: 'Pixel 4',
    … // Other fields omitted to save space
  }, 
  …
]

و تبدیل شد به:

interface Device {
  name: string,
  …
}

const devices: Device[] = [{name: 'Pixel 4', …}, …]

module.exports = devices;

به‌عنوان بخشی از این فرایند، ما هر خط کدپایه را بررسی کردیم تا مشکلات را پیدا کنیم. مانند هر پایگاه کدی که چند سالی است وجود دارد و به‌مرور زمان رشد کرده است، فرصت‌هایی برای بازسازی کد و بهبود وضعیت وجود دارد. به‌ویژه با انتقال به TypeScript، دیدیم که در جاهایی با کمی تغییر ساختار کد می‌توانیم بیشتر به کامپایلر تکیه کنیم و ایمنی نوع بهتری داشته باشیم.

به‌طور غیرمنتظره، واقعاً مهم است که از ایجاد این تغییرات بلافاصله خودداری کنید. هدف از انتقال این است که پایگاه کد به TypeScript منتقل شود، و در تمام مدت یک انتقال بزرگ باید به خطر ایجاد اختلال در نرم‌افزار و کاربران خود فکر کنید. با حداقل نگه داشتن تغییرات اولیه، این خطر را پایین نگه داشتیم. پس‌از ادغام و انتقال فایل به TypeScript، می‌توانستیم تغییرات بعدی را برای بهبود کد و استفاده از سیستم نوع انجام دهیم. مطمئن شوید که مرزهای دقیقی برای انتقال خود تعیین کرده‌اید و سعی کنید در این مرزها بمانید.

درحال انتقال آزمایش‌ها برای آزمایش تعاریف نوع ما

وقتی کل کد منبع را به TypeScript منتقل کردیم، توانستیم تمرکزمان را روی آزمایش‌هایمان بگذاریم. آزمایش‌های ما پوشش عالی داشتند، اما همه به زبان جاوا اسکریپت نوشته شده بودند. این یعنی یکی از چیزهایی که آن‌ها آزمایش نکردند تعریف‌های نوع ما بود. یکی از اهداف بلندمدت پروژه (که هنوز روی آن کار می‌کنیم) این است که تعاریف نوع باکیفیت را به‌صورت آماده با Puppeteer ارائه دهیم، اما هیچ بررسی‌ای در پایگاه کد خود درباره تعاریف نوع نداشتیم.

با انتقال آزمایش‌ها به TypeScript (با دنبال کردن همان فرایند، فایل به فایل)، مشکلاتی در TypeScript خود پیدا کردیم که درغیراین‌صورت کاربران باید آن‌ها را برای ما پیدا می‌کردند. اکنون آزمایش‌های ما نه‌تنها همه عملکردهای ما را پوشش می‌دهند، بلکه به‌عنوان بررسی کیفیت TypeScript ما نیز عمل می‌کنند!

ما به‌عنوان مهندسانی که روی پایگاه کد Puppeteer کار می‌کنیم، قبلاً از TypeScript بهره زیادی برده‌ایم. این ویژگی به‌همراه محیط CI بسیار بهبودیافته ما، به ما امکان داده است تا هنگام کار روی Puppeteer بهره‌وری بیشتری داشته باشیم و TypeScript اشکالاتی را شناسایی کند که درغیراین‌صورت به نسخه npm راه می‌یافتند. ما هیجان‌زده هستیم که تعاریف TypeScript با کیفیت بالا را ارسال کنیم تا همه توسعه‌دهندگانی که از Puppeteer استفاده می‌کنند نیز بتوانند از این کار بهره‌مند شوند.

بارگیری کانال‌های پیش‌نمایش

از Chrome Canary، Dev، یا Beta به‌عنوان مرورگر توسعه پیش‌فرض خود استفاده کنید. این کانال‌های پیش‌نمایش به شما امکان می‌دهند به جدیدترین ویژگی‌های DevTools دسترسی داشته باشید، میاناهای برنامه‌سازی کاربردی پلاتفرم وب پیشرفته را آزمایش کنید، و قبل‌از اینکه کاربران با مشکلات سایتتان مواجه شوند آن‌ها را پیدا کنید!

تماس با تیم Chrome DevTools

از گزینه‌های زیر برای بحث درباره ویژگی‌های جدید، به‌روزرسانی‌ها، یا هر چیز دیگری که به DevTools مربوط می‌شود استفاده کنید.