Thông tin mới về Web In Play

Ngày xuất bản: 2 tháng 12 năm 2020

Kể từ khi ra mắt Hoạt động đáng tin cậy trên web, nhóm Chrome đã giúp bạn dễ dàng sử dụng tính năng này hơn với Bubblewrap. Chúng tôi đã thêm các tính năng bổ sung, chẳng hạn như tích hợp Google Play Billing và cho phép tính năng này hoạt động trên nhiều nền tảng hơn, chẳng hạn như ChromeOS.

Các tính năng Bubblewrap và Hoạt động đáng tin cậy trên web

Bubblewrap giúp bạn tạo các ứng dụng chạy PWA bên trong một Hoạt động web đáng tin cậy mà không cần phải có kiến thức về công cụ dành riêng cho nền tảng.

Quy trình thiết lập đơn giản

Trước đây, để sử dụng Bubblewrap, bạn phải thiết lập Bộ phát triển Java và SDK Android theo cách thủ công, cả hai đều dễ gặp lỗi. Giờ đây, công cụ này sẽ tự động tải các phần phụ thuộc bên ngoài xuống khi chạy lần đầu tiên.

Bạn vẫn có thể chọn sử dụng một bản cài đặt hiện có của các phần phụ thuộc, nếu muốn, và lệnh doctor mới giúp tìm ra vấn đề và đề xuất các bản sửa lỗi cho cấu hình. Giờ đây, bạn có thể cập nhật cấu hình từ dòng lệnh bằng lệnh updateConfig.

Cải thiện trình hướng dẫn

Khi tạo dự án bằng init, Bubblewrap cần thông tin để tạo ứng dụng Android. Công cụ này trích xuất các giá trị từ Tệp kê khai ứng dụng web và cung cấp các giá trị mặc định nếu có thể.

Bạn có thể thay đổi các giá trị đó khi tạo dự án mới, nhưng trước đây, ý nghĩa của từng trường không rõ ràng. Hộp thoại khởi chạy được tạo lại với nội dung mô tả và xác thực tốt hơn cho từng trường nhập.

Hiển thị chế độ toàn màn hình và hỗ trợ hướng

Trong một số trường hợp, bạn có thể muốn ứng dụng của mình sử dụng nhiều màn hình nhất có thể và khi tạo PWA, bạn có thể triển khai việc này bằng cách đặt trường display từ Tệp kê khai ứng dụng web thành fullscreen.

Khi phát hiện tuỳ chọn toàn màn hình trong Tệp kê khai ứng dụng web, Bubblewrap sẽ định cấu hình ứng dụng Android để chạy ở chế độ toàn màn hình hoặc chế độ chìm đắm (theo các thuật ngữ dành riêng cho Android).

Trường orientation trong Tệp kê khai ứng dụng web xác định liệu ứng dụng có được khởi động ở chế độ dọc, chế độ ngang hay theo hướng mà thiết bị đang sử dụng hay không. Bubblewrap hiện đọc trường Tệp kê khai ứng dụng web và sử dụng trường này làm mặc định khi tạo ứng dụng Android.

Bạn có thể tuỳ chỉnh cả hai cấu hình trong quy trình bubblewrap init.

Đầu ra AppBundles

Gói ứng dụng là định dạng phát hành dành cho các ứng dụng uỷ quyền việc tạo và ký tệp APK cuối cùng cho Play. Trong thực tế, điều này cho phép phân phát các tệp nhỏ hơn cho người dùng khi tải ứng dụng xuống từ cửa hàng.

Bubblewrap hiện đóng gói ứng dụng dưới dạng Gói ứng dụng, trong một tệp có tên app-release-bundle.aab. Bạn nên ưu tiên định dạng này khi phát hành ứng dụng lên Cửa hàng Play, vì đây là yêu cầu bắt buộc của cửa hàng kể từ năm 2021.

Uỷ quyền vị trí địa lý

Người dùng mong muốn các ứng dụng được cài đặt trên thiết bị của họ hoạt động nhất quán, bất kể công nghệ. Khi được sử dụng bên trong một Hoạt động web đáng tin cậy, quyền GeoLocation hiện có thể được uỷ quyền cho Hệ điều hành và khi được bật, người dùng sẽ thấy các hộp thoại giống như các ứng dụng được tạo bằng Kotlin hoặc Java và tìm thấy các chế độ điều khiển để quản lý quyền ở cùng một nơi.

Bạn có thể thêm tính năng này thông qua Bubblewrap và vì tính năng này thêm các phần phụ thuộc bổ sung vào dự án Android, nên bạn chỉ nên bật tính năng này khi ứng dụng web đang sử dụng quyền Vị trí địa lý.

Tệp nhị phân được tối ưu hoá

Các thiết bị có dung lượng lưu trữ hạn chế phổ biến ở một số khu vực nhất định trên thế giới và chủ sở hữu của những thiết bị đó thường thích các ứng dụng nhỏ hơn. Các ứng dụng sử dụng tính năng Hoạt động đáng tin cậy trên web sẽ tạo ra các tệp nhị phân nhỏ, giúp loại bỏ một số lo ngại của những người dùng đó.

Bubblewrap đã được tối ưu hoá bằng cách giảm danh sách các thư viện Android cần thiết, dẫn đến việc tạo ra các tệp nhị phân nhỏ hơn 800k. Trong thực tế, kích thước này nhỏ hơn một nửa kích thước trung bình do các phiên bản trước tạo ra. Để tận dụng các tệp nhị phân nhỏ hơn, bạn chỉ cần cập nhật ứng dụng bằng phiên bản Bubblewrap mới nhất.

Cách cập nhật ứng dụng hiện có

Ứng dụng do Bubblewrap tạo ra bao gồm một ứng dụng web và một trình bao bọc Android nhẹ mở PWA. Mặc dù PWA mở bên trong một Hoạt động web đáng tin cậy tuân theo các chu kỳ cập nhật giống như mọi ứng dụng web, nhưng trình bao bọc gốc có thể và nên được cập nhật.

Bạn nên cập nhật ứng dụng để đảm bảo ứng dụng đó đang sử dụng phiên bản trình bao bọc mới nhất, với các bản sửa lỗi và tính năng mới nhất. Khi bạn đã cài đặt phiên bản Bubblewrap mới nhất, lệnh update sẽ áp dụng phiên bản mới nhất của trình bao bọc cho một dự án hiện có:

npm update -g @bubblewrap/cli
bubblewrap update
bubblewrap build

Một lý do khác để cập nhật các ứng dụng đó là đảm bảo rằng các thay đổi đối với Tệp kê khai web được áp dụng cho ứng dụng. Hãy sử dụng lệnh merge mới cho việc đó:

bubblewrap merge
bubblewrap update
bubblewrap build

Nội dung cập nhật về Tiêu chí chất lượng

Chrome 86 đã đưa ra các thay đổi đối với Tiêu chí chất lượng của Hoạt động đáng tin cậy trên web. Bạn có thể xem nội dung giải thích đầy đủ trong phần Các thay đổi đối với tiêu chí chất lượng cho những PWA sử dụng Hoạt động đáng tin cậy trên web.

Tóm lại, bạn nên đảm bảo ứng dụng của mình xử lý các trường hợp sau để ngăn ứng dụng gặp sự cố:

  • Không xác minh được đường liên kết đến tài sản kỹ thuật số khi khởi chạy ứng dụng
  • Không trả về HTTP 200 cho yêu cầu tài nguyên mạng ngoại tuyến
  • Trả về lỗi HTTP 404 hoặc 5xx trong ứng dụng.

Ngoài việc đảm bảo ứng dụng vượt qua quy trình xác thực Đường liên kết đến tài sản kỹ thuật số, các trường hợp còn lại có thể được worker dịch vụ xử lý:

self.addEventListener('fetch', event => {
  event.respondWith((async () => {
    try {
      return await fetchAndHandleError(event.request);
    } catch {
      // Failed to load from the network. User is offline or the response
      // has a status code that triggers the Quality Criteria.
      // Try loading from cache.
      const cachedResponse = await caches.match(event.request);
      if (cachedResponse) {
        return cachedResponse;
      }
      // Response was not found on the cache. Send the error / offline
      // page. OFFLINE_PAGE should be pre-cached when the service worker
      // is activated.
      return await caches.match(OFFLINE_PAGE);
    }
  })());
});

async function fetchAndHandleError(request) {
  const cache = await caches.open(RUNTIME_CACHE);
  const response = await fetch(request);

  // Throw an error if the response returns one of the status
  // that trigger the Quality Criteria.
  if (response.status === 404 ||
      response.status >= 500 && response.status < 600) {
    throw new Error(`Server responded with status: ${response.status}`);
  }

  // Cache the response if the request is successful.
  cache.put(request, response.clone());
  return response;
}

Workbox tích hợp các phương pháp hay nhất và xoá mã nguyên mẫu khi sử dụng trình chạy dịch vụ. Ngoài ra, hãy cân nhắc sử dụng trình bổ trợ Workbox để xử lý các trường hợp đó:

export class FallbackOnErrorPlugin {
  constructor(offlineFallbackUrl, notFoundFallbackUrl, serverErrorFallbackUrl) {
    this.notFoundFallbackUrl = notFoundFallbackUrl;
    this.offlineFallbackUrl = offlineFallbackUrl;
    this.serverErrorFallbackUrl = serverErrorFallbackUrl;
  }

  checkTrustedWebActivityCrash(response) {
    if (response.status === 404 || response.status >= 500 && response.status <= 600) {
      const type = response.status === 404 ? 'E_NOT_FOUND' : 'E_SERVER_ERROR';
      const error = new Error(`Invalid response status (${response.status})`);
      error.type = type;
      throw error;
    }
  }

  // This is called whenever there's a network response,
  // but we want special behavior for 404 and 5**.
  fetchDidSucceed({response}) {
    // Cause a crash if this is a Trusted Web Activity crash.
    this.checkTrustedWebActivityCrash(response);

    // If it's a good response, it can be used as-is.
    return response;
  }

  // This callback is new in Workbox v6, and is triggered whenever
  // an error (including a NetworkError) is thrown when a handler runs.
  handlerDidError(details) {
    let fallbackURL;
    switch (details.error.details.error.type) {
      case 'E_NOT_FOUND': fallbackURL = this.notFoundFallbackUrl; break;
      case 'E_SERVER_ERROR': fallbackURL = this.serverErrorFallbackUrl; break;
      default: fallbackURL = this.offlineFallbackUrl;
    }

    return caches.match(fallbackURL, {
      // Use ignoreSearch as a shortcut to work with precached URLs
      // that have _WB_REVISION parameters.
      ignoreSearch: true,
    });
  }
}