Di chuyển Puppeteer sang TypeScript

Chúng tôi là những người hâm mộ TypeScript trong nhóm Công cụ cho nhà phát triển. Chúng tôi đang trong quá trình di chuyển toàn bộ cơ sở mã để TypeScript kiểm tra kiểu. Bạn có thể tìm hiểu thêm về quá trình di chuyển đó trong buổi trò chuyện của chúng tôi tại Chrome Dev Summit 2020. Do đó, bạn cũng nên xem xét việc di chuyển cơ sở mã của Puppeteer sang TypeScript.

Lên kế hoạch di chuyển

Khi lên kế hoạch di chuyển, chúng tôi muốn có thể tiến hành từng bước nhỏ. Điều này giúp giảm chi phí di chuyển (bạn chỉ làm việc trên một phần nhỏ của mã tại một thời điểm) và giảm rủi ro. Nếu có vấn đề xảy ra với một trong các bước, bạn có thể dễ dàng huỷ bỏ bước đó. Puppeteer có rất nhiều người dùng và một bản phát hành bị lỗi sẽ gây ra vấn đề cho nhiều người dùng. Vì vậy, điều quan trọng là chúng tôi phải giảm thiểu nguy cơ thay đổi gây lỗi.

Chúng tôi cũng rất may mắn khi Puppeteer có một bộ kiểm thử đơn vị mạnh mẽ bao gồm tất cả chức năng của Puppeteer. Điều này có nghĩa là chúng tôi có thể tự tin rằng chúng tôi không làm hỏng mã khi di chuyển, đồng thời không đưa ra các thay đổi đối với API. Mục tiêu của quá trình di chuyển là hoàn tất mà không có người dùng Puppeteer nào nhận ra rằng chúng tôi đã di chuyển, và các bài kiểm thử là một phần quan trọng trong chiến lược đó. Nếu không có phạm vi kiểm thử tốt, chúng ta sẽ thêm phạm vi kiểm thử đó trước khi tiếp tục di chuyển.

Việc thực hiện bất kỳ thay đổi nào về mã mà không kiểm thử đều có rủi ro, nhưng những thay đổi mà bạn đang thực hiện trên toàn bộ tệp hoặc toàn bộ cơ sở mã sẽ đặc biệt rủi ro. Khi thực hiện các thay đổi về cơ khí, bạn dễ bỏ lỡ một bước và trong nhiều trường hợp, các bài kiểm thử đã phát hiện ra vấn đề mà cả người triển khai và người đánh giá đều bỏ qua.

Một việc chúng tôi đã đầu tư thời gian trước đó là thiết lập tính năng Tích hợp liên tục (CI). Chúng tôi nhận thấy rằng CI chạy trên các yêu cầu kéo không ổn định và thường không thành công. Điều này xảy ra thường xuyên đến nỗi chúng tôi đã có thói quen bỏ qua CI và hợp nhất các yêu cầu kéo, giả định rằng lỗi này là một vấn đề một lần trên CI chứ không phải vấn đề trong Puppeteer.

Sau một số hoạt động bảo trì chung và dành thời gian để khắc phục một số lỗi kiểm thử thông thường, chúng tôi đã đưa ứng dụng vào trạng thái vượt qua bài kiểm thử một cách nhất quán hơn nhiều, cho phép chúng tôi theo dõi CI và biết rằng lỗi là dấu hiệu của một vấn đề thực tế. Công việc này không hào nhoáng và thật khó chịu khi phải xem quá trình chạy CI vô tận, nhưng điều quan trọng là bộ kiểm thử của chúng ta phải chạy một cách đáng tin cậy do số lượng yêu cầu kéo mà quá trình di chuyển đang gửi đến.

Chọn và hạ cánh một tệp

Tại thời điểm này, chúng tôi đã sẵn sàng di chuyển và có một máy chủ CI mạnh mẽ với đầy đủ các bài kiểm thử để hỗ trợ chúng tôi. Thay vì tìm hiểu bất kỳ tệp tuỳ ý nào, chúng tôi đã chủ ý chọn một tệp nhỏ để di chuyển. Đây là một bài tập hữu ích vì giúp bạn xác thực quy trình đã lên kế hoạch mà bạn sắp thực hiện. Nếu cách này hoạt động trên tệp này, thì phương pháp của bạn là hợp lệ; nếu không, bạn có thể quay lại vẽ lại.

Ngoài ra, việc xử lý từng tệp (và với các bản phát hành Puppeteer thông thường, vì vậy, tất cả các thay đổi đều không được vận chuyển trong cùng một phiên bản npm) đã giảm thiểu rủi ro. Chúng tôi chọn DeviceDescriptors.js làm tệp đầu tiên vì đây là một trong những tệp đơn giản nhất trong cơ sở mã. Bạn có thể cảm thấy hơi thất vọng khi phải làm tất cả công việc chuẩn bị này và chỉ nhận được một thay đổi nhỏ như vậy, nhưng mục tiêu không phải là thực hiện những thay đổi lớn ngay lập tức mà là tiến hành từng tệp một một cách thận trọng và có phương pháp. Thời gian xác thực phương pháp này chắc chắn sẽ giúp bạn tiết kiệm thời gian sau này trong quá trình di chuyển khi gặp phải các tệp phức tạp hơn.

Chứng minh mẫu và lặp lại

Rất may, thay đổi đối với DeviceDescriptors.js đã được đưa vào cơ sở mã thành công và kế hoạch đã hoạt động như mong đợi! Đến đây, bạn đã sẵn sàng bắt tay vào việc, đó cũng chính là những gì chúng tôi đã làm. Việc sử dụng nhãn GitHub là một cách rất hay để nhóm tất cả các yêu cầu kéo lại với nhau và chúng tôi nhận thấy điều đó rất hữu ích để theo dõi tiến trình.

Di chuyển và cải thiện sau

Đối với từng tệp JavaScript riêng lẻ, quy trình của chúng tôi là:

  1. Đổi tên tệp từ .js thành .ts.
  2. Chạy trình biên dịch TypeScript.
  3. Khắc phục mọi vấn đề.
  4. Tạo yêu cầu kéo.

Hầu hết công việc trong các yêu cầu kéo ban đầu này là trích xuất giao diện TypeScript cho các cấu trúc dữ liệu hiện có. Trong trường hợp yêu cầu kéo đầu tiên đã di chuyển DeviceDescriptors.js mà chúng ta đã thảo luận trước đó, mã đã chuyển từ:

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

Và trở thành:

interface Device {
  name: string,
  
}

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

module.exports = devices;

Trong quá trình này, chúng ta đã kiểm tra mọi dòng trong cơ sở mã để tìm vấn đề. Giống như mọi cơ sở mã đã tồn tại được vài năm và phát triển theo thời gian, có những cơ hội để tái cấu trúc mã và cải thiện tình hình. Đặc biệt là khi chuyển sang TypeScript, chúng tôi nhận thấy một số nơi cần tái cấu trúc mã một chút để có thể dựa vào trình biên dịch nhiều hơn và tăng độ an toàn của loại.

Trái với trực giác, bạn cần tránh thực hiện những thay đổi này ngay lập tức. Mục tiêu của quá trình di chuyển là đưa cơ sở mã vào TypeScript và mọi lúc trong quá trình di chuyển lớn, bạn nên nghĩ đến nguy cơ gây ra sự cố cho phần mềm và người dùng. Bằng cách giảm thiểu các thay đổi ban đầu, chúng tôi đã giảm thiểu rủi ro đó. Sau khi hợp nhất và di chuyển tệp sang TypeScript, chúng ta có thể thực hiện các thay đổi tiếp theo để cải thiện mã nhằm tận dụng hệ thống loại. Hãy nhớ đặt ra các ranh giới nghiêm ngặt cho quá trình di chuyển và cố gắng tuân thủ các ranh giới đó.

Di chuyển các chương trình kiểm thử để kiểm thử định nghĩa loại

Sau khi di chuyển toàn bộ mã nguồn sang TypeScript, chúng ta có thể tập trung vào các bài kiểm thử. Các bài kiểm thử của chúng tôi có phạm vi kiểm thử rất lớn, nhưng đều được viết bằng JavaScript. Điều này có nghĩa là một điều họ không kiểm thử là định nghĩa loại của chúng ta. Một trong những mục tiêu dài hạn của dự án (mà chúng tôi vẫn đang thực hiện) là cung cấp các định nghĩa loại chất lượng cao ngay từ đầu bằng Puppeteer, nhưng chúng tôi không có bất kỳ quy trình kiểm tra nào trong cơ sở mã về định nghĩa loại.

Bằng cách di chuyển các chương trình kiểm thử sang TypeScript (làm theo cùng một quy trình, từng tệp một), chúng tôi đã phát hiện các vấn đề với TypeScript mà nếu không có người dùng tìm giúp thì chúng tôi sẽ không biết. Giờ đây, các bài kiểm thử của chúng ta không chỉ bao gồm tất cả chức năng mà còn đóng vai trò là công cụ kiểm tra chất lượng của TypeScript!

Chúng tôi đã nhận được rất nhiều lợi ích từ TypeScript khi là các kỹ sư làm việc trên cơ sở mã Puppeteer. Cùng với môi trường CI được cải thiện đáng kể, điều này đã giúp chúng tôi làm việc hiệu quả hơn khi làm việc trên Puppeteer và có TypeScript phát hiện lỗi mà nếu không thì lỗi đó sẽ được đưa vào bản phát hành npm. Chúng tôi rất vui khi được cung cấp các định nghĩa TypeScript chất lượng cao để tất cả nhà phát triển sử dụng Puppeteer cũng có thể hưởng lợi từ công việc này.

Tải các kênh xem trước xuống

Hãy cân nhắc sử dụng Chrome Canary, Dev hoặc Beta làm trình duyệt phát triển mặc định. Các kênh xem trước này cho phép bạn sử dụng các tính năng mới nhất của DevTools, kiểm thử các API nền tảng web tiên tiến và giúp bạn tìm thấy vấn đề trên trang web của mình trước khi người dùng phát hiện ra!

Liên hệ với nhóm Công cụ của Chrome cho nhà phát triển

Hãy sử dụng các lựa chọn sau để thảo luận về các tính năng, bản cập nhật mới hoặc bất kỳ nội dung nào khác liên quan đến Công cụ cho nhà phát triển.