Trang chủ

Đưa một ứng dụng từ 142MB xuống 38MB

Trang App Store ghi 142MB. Trên mạng di động, Apple cảnh báo người dùng với ứng dụng trên 200MB, và tôi đang ở gần một ngưỡng đến khó chịu, cái ngưỡng sẽ lấy đi lượt cài đặt.

Xuống được 38MB mất khoảng hai ngày, và phần lớn nằm ở một chỗ tôi đã không nghĩ đến việc đi tìm.

Đo đúng con số trước đã

Dung lượng trong Organizer của Xcode không phải con số người dùng nhìn thấy. Có ba con số khác nhau đáng quan tâm:

  • Dung lượng archive — đầu ra bản build của bạn. Bao gồm mọi kiến trúc và toàn bộ ký hiệu gỡ lỗi. Không liên quan.
  • Dung lượng file trên App Store — sau khi Apple xử lý và cắt gọt cho một thiết bị cụ thể. Đây là lượt tải về.
  • Dung lượng cài đặt — sau khi giải nén trên thiết bị.

Để xem chúng: Xcode → Organizer → chọn archive → Distribute App → App Store Connect → Export, rồi đọc file App Thinning Size Report.txt. Nó liệt kê dung lượng tải và dung lượng cài cho từng biến thể thiết bị.

Đoán ở bất cứ chỗ nào khác thì bạn sẽ tối ưu nhầm con số. Archive của tôi là 142MB, còn lượt tải thật cho một chiếc iPhone đời mới vốn đã là 96MB trước khi tôi sửa bất cứ thứ gì.

Dung lượng của tôi nằm ở đâu

Asset catalog       58MB
Binary              21MB
JSON đóng gói       11MB
Font                 4MB
Mọi thứ khác         2MB

Ảnh — 58MB xuống 6MB

Gần như toàn bộ là một sai lầm: các file PNG xuất ở 3x cho những hình chưa bao giờ hiển thị lớn hơn 120 điểm, và mấy file PNG đủ màu cho những thứ thực chất là icon một màu phẳng.

Ba thay đổi:

Icon chuyển sang SF Symbols hoặc vector. Một icon một màu chẳng có lý do gì để là một file PNG ở ba độ phân giải. SF Symbols thì miễn phí và co giãn được; một file PDF vector bật “Preserve Vector Data” là lựa chọn tốt kế tiếp.

Ảnh chụp chuyển sang HEIC. Với nội dung ảnh chụp, HEIC nhỏ khoảng một nửa JPEG ở cùng chất lượng, và mọi thiết bị mà ứng dụng hỗ trợ đều giải mã được.

Tôi bỏ các asset 1x. Không thiết bị được hỗ trợ nào dùng chúng. Xcode vẫn cho bạn phát hành chúng và chúng là trọng lượng thuần túy.

Mẹo

Hãy kiểm tra asset trùng lặp trước mọi thứ khác. Hai catalog, hoặc một asset tồn tại ở cả ứng dụng lẫn một package, sẽ được phát hành hai lần. Câu lệnh find . -name "*.png" | xargs md5 | sort | uniq -d -w 32 đã tìm ra bốn megabyte trùng khớp y hệt trong trường hợp của tôi.

JSON đóng gói — 11MB xuống 800KB

Một tập dữ liệu tra cứu lớn được phát hành dưới dạng JSON có định dạng đẹp mắt. Hai thay đổi: rút gọn nó (bỏ hết khoảng trắng), và nén nó lại, rồi giải nén ở lần chạy đầu tiên vào thư mục hỗ trợ của ứng dụng.

Nếu dữ liệu thật sự tĩnh và được truy vấn chứ không đọc nguyên khối, một file SQLite dựng sẵn còn tốt hơn nữa — nhỏ hơn JSON và không cần phân tích cú pháp lúc khởi động.

Binary — 21MB xuống 12MB

Bóc ký hiệu Swift. Đặt STRIP_SWIFT_SYMBOLS = YES và DEPLOYMENT_POSTPROCESSING = YES cho Release. Việc này không ảnh hưởng đến khả năng giải mã ký hiệu sự cố, miễn là bạn giữ lại dSYM.

Dead code stripping bật sẵn theo mặc định; hãy xác nhận là nó chưa bị tắt.

Rà lại các phụ thuộc. Tôi đang liên kết một SDK phân tích nặng 4MB cho hai sự kiện, và một thư viện ảnh cho đúng một hàm đổi kích thước. Cả hai được thay bằng vài chục dòng.

Liên kết tĩnh thay vì động cũng giúp ở đây, và giúp thời gian khởi động còn nhiều hơn.

Hai thứ chẳng tạo ra khác biệt nào

Bitcode. Đã bị khai tử, và nó không làm đổi dung lượng.

Ám ảnh về generic của Swift. Monomorphisation có nhân bản code thật, và trong một codebase cỡ ứng dụng thì nó là nhiễu bên cạnh một asset catalog 58MB.

App thinning làm được rất nhiều thứ miễn phí

Apple dựng một biến thể cho mỗi thiết bị, nên người dùng chỉ tải về kiến trúc và độ phân giải asset mà máy họ cần. Đó là lý do archive lớn hơn lượt tải nhiều đến vậy.

Hai thứ khiến bạn vô tình bị loại khỏi cơ chế đó:

Ảnh nạp theo tên file từ một folder reference thay vì từ một asset catalog thì không được cắt gọt — mọi thiết bị nhận mọi độ phân giải. Hãy chuyển các ảnh rời vào một catalog.

On-demand resources đáng biết đến với bất cứ thứ gì thật sự là tùy chọn. Các gói màn chơi, video hướng dẫn, bản đồ ngoại tuyến — được gắn thẻ rồi tải về ở lần dùng đầu tiên thay vì phát hành kèm lượt tải ban đầu.

Kết quả

Trước Sau
Archive 142MB 41MB
Tải về (iPhone đời mới) 96MB 38MB
Cài đặt 128MB 44MB

Thứ tôi sẽ kiểm tra đầu tiên trong một ứng dụng khác

  1. Asset catalog. Gần như luôn là câu trả lời, và gần như luôn là các file PNG 3x lẽ ra phải là vector.
  2. Các bản trùng lặp, bằng câu lệnh md5 ở trên.
  3. Mọi file dữ liệu đóng gói lớn hơn một megabyte. Hãy nén nó, hoặc biến nó thành một cơ sở dữ liệu.
  4. Danh sách phụ thuộc, một cách thành thật. Mỗi SDK hoặc là xứng với dung lượng của nó, hoặc là không.

Binary là chỗ cuối cùng nên nhìn và lại là chỗ người ta bắt đầu, vì nó cho cảm giác là bài toán kỹ thuật. Còn megabyte thì nằm ở đám ảnh.