Một codebase H5, chạy native trên iOS 12: techstack của GoBrain
Cách chúng tôi đưa một game giải đố PixiJS lên iOS, Android và web từ một codebase TypeScript duy nhất, với cập nhật OTA vẫn tới được cả những máy iOS 12.
GoBrain là một ứng dụng giải đố trí tuệ nhỏ gọn: một bản 2048 tốc độ cao cùng loạt trò chơi logic đổi mới mỗi ngày. Nó chạy như một app native trên iOS và Android, và như một website thuần, tất cả từ một codebase. Bài viết này đi qua techstack làm nên điều đó, cùng những phần thực sự tốn công để giữ chân những chiếc máy đời cũ.
Một engine, ba nền tảng
Toàn bộ game là một ứng dụng H5 (HTML5) dựng trên PixiJS v7, một bộ render WebGL nhẹ. Chúng tôi chọn PixiJS thay vì một game engine đầy đủ một cách có chủ đích: các câu đố là 2D, hiệu ứng chỉ là trượt và gộp ô, và chúng tôi muốn bundle đủ nhỏ để load tức thì trong một WebView di động. Logic game và giao diện viết bằng TypeScript, đóng gói bằng Vite.
Bản web build duy nhất đó sau đó được bọc cho các cửa hàng bằng Capacitor 6 (runtime native của Ionic). Capacitor cho chúng tôi một lớp vỏ native mỏng quanh app web cùng các cầu nối có kiểu tới nền tảng: haptics, thông báo cục bộ, share sheet, thanh trạng thái, lưu trữ preferences, và Firebase Analytics qua các plugin @capacitor-firebase. Bản web và bản native chạy đúng cùng một đoạn code game.
Mỗi mini-game (2048, memory, patch, sudoku, và các trò khác) được dựng thành module riêng và ghép lại bằng một catalog được sinh tự động, nên thêm một câu đố mới không đụng tới các trò còn lại. Các lượt chạy end-to-end đi qua Playwright trên bản game đã build.
Giữ iOS 12 còn sống
Đây là điểm ràng buộc thú vị: GoBrain hỗ trợ xuống tới iOS 12.0. Một chiếc iPhone đời 2018 vẫn phải chơi được.
Cái khó nằm ở cập nhật over-the-air (OTA). Chúng tôi tung bản vá và câu đố mới mà không cần chờ App Store duyệt, bằng cách đẩy bundle web mới qua @capgo/capacitor-updater. Nhưng bản updater gốc giả định một WebView hiện đại, và nó hỏng trên WebKit cũ mà iOS 12 dùng. Vì thế chúng tôi chạy một fork được ghim:
"@capgo/capacitor-updater": "github:fighttechvn/capacitor-updater#ios12-6.45.10"
Fork đó giữ cho luồng tải-và-thay-thế OTA hoạt động trên WebView iOS 12, nghĩa là ngay cả những thiết bị cũ nhất được hỗ trợ cũng nhận cùng bản vá như mọi người, trong cùng một ngày, không cần vòng chờ cửa hàng. Khả năng lặp nhanh như vậy chính là lý do chính khiến game sống trên nền tảng web thay vì một native engine.
Dữ liệu gọn nhẹ trên đường truyền
Bảng xếp hạng và catalog game di chuyển dưới dạng Protocol Buffers qua @bufbuild/protobuf. Protobuf giữ payload nhỏ và có kiểu chặt chẽ ở cả hai đầu, điều rất quan trọng trên những kết nối chậm mà máy đời cũ thường phải chịu. Các định nghĩa .proto là nguồn chân lý duy nhất, và các kiểu TypeScript được sinh ra từ chúng lúc build.
Vì sao chọn hình hài này
Techstack là một tập hợp các đánh đổi xoay quanh độ phủ và tốc độ lặp:
- Độ phủ — một codebase phủ iOS, Android và web, và mức sàn hệ điều hành đủ thấp (iOS 12) để một lượng lớn máy đời cũ vẫn được mời vào.
- Tốc độ lặp — OTA nghĩa là một bản vá lên sóng trong vài phút, không phải một tuần, kể cả trên phần cứng cũ nhất.
- Dung lượng nhỏ — PixiJS + Vite giữ bản tải nhẹ, nên game đầu tiên load nhanh trên một chiếc điện thoại đã qua thời hoàng kim.
Không có công nghệ nào ở đây là kỳ lạ. Công sức nằm ở các mối nối: fork updater cho iOS 12, tách game thành các module độc lập, và sinh kiểu cùng catalog để một đội nhỏ di chuyển nhanh mà không phá vỡ lời hứa với máy đời cũ.
Muốn xem nó chạy? GoBrain chơi được ngay trên trình duyệt, không cần cài đặt.