Trình chạy dịch vụ và mô hình shell ứng dụng

Tính năng kiến trúc phổ biến của ứng dụng web một trang (SPA) là tập hợp HTML, CSS và JavaScript tối thiểu cần thiết để hỗ trợ chức năng chung của ứng dụng. Trong thực tế, thường là tiêu đề, điều hướng và các thành phần giao diện người dùng phổ biến khác nằm cố định trên tất cả các trang. Khi một trình chạy dịch vụ lưu trước trong bộ nhớ đệm HTML và các phần tử phụ thuộc tối thiểu của giao diện người dùng này, chúng tôi gọi đây là giao diện ứng dụng.

Sơ đồ về một shell ứng dụng. Đó là ảnh chụp màn hình của một trang web có tiêu đề ở trên cùng và vùng nội dung ở dưới cùng. Tiêu đề có nhãn 'Application Shell' (Vỏ ứng dụng), còn ở dưới cùng được gắn nhãn 'Nội dung'.

Giao diện ứng dụng đóng một vai trò quan trọng trong hiệu suất nhận thức của ứng dụng web. Đây là nội dung đầu tiên được tải và do đó, cũng là nội dung đầu tiên mà người dùng nhìn thấy khi họ chờ nội dung được đưa vào giao diện người dùng.

Mặc dù giao diện ứng dụng tải nhanh — miễn là có mạng và ít nhất là nhanh — một trình chạy dịch vụ sẽ lưu trước giao diện ứng dụng vào bộ nhớ đệm và các nội dung liên quan của giao diện ứng dụng mang lại cho mô hình giao diện ứng dụng những lợi ích bổ sung sau:

  • Hiệu suất đáng tin cậy, nhất quán ở các lượt truy cập lặp lại. Trong lần đầu tiên truy cập vào một ứng dụng chưa cài đặt trình chạy dịch vụ, đánh dấu của ứng dụng và các nội dung liên quan của ứng dụng đó phải được tải từ mạng trước khi trình chạy dịch vụ có thể đưa chúng vào bộ nhớ đệm. Tuy nhiên, lượt truy cập lặp lại sẽ kéo giao diện ứng dụng từ bộ nhớ đệm, có nghĩa là việc tải và kết xuất sẽ diễn ra ngay lập tức.
  • Quyền truy cập đáng tin cậy vào các chức năng khi không có mạng. Đôi khi kết nối Internet không ổn định hoặc hoàn toàn không có kết nối mạng và sợ hãi "chúng tôi không thể tìm thấy trang web đó" màn hình phía sau đầu. Mô hình shell ứng dụng giải quyết vấn đề này bằng cách phản hồi bất kỳ yêu cầu điều hướng nào có đánh dấu shell ứng dụng từ bộ nhớ đệm. Ngay cả khi ai đó truy cập URL trong ứng dụng web của bạn mà họ chưa từng truy cập trước đây, giao diện ứng dụng sẽ được phân phát từ bộ nhớ đệm và có thể được điền sẵn nội dung hữu ích.

Các trường hợp nên sử dụng mô hình shell ứng dụng

Giao diện ứng dụng hợp lý nhất khi bạn có các phần tử giao diện người dùng phổ biến không thay đổi từ tuyến này sang tuyến khác, nhưng nội dung thì thay đổi. Hầu hết các SPA có thể sử dụng mô hình shell ứng dụng hiệu quả.

Nếu thông tin này mô tả dự án của bạn và bạn muốn thêm một trình chạy dịch vụ để nâng cao độ tin cậy và hiệu suất, thì giao diện ứng dụng phải:

  • Tải nhanh.
  • Sử dụng thành phần tĩnh từ một thực thể Cache.
  • Bao gồm các phần tử giao diện phổ biến như tiêu đề và thanh bên, tách biệt với nội dung trang.
  • Truy xuất và hiển thị nội dung cụ thể của trang.
  • Nếu thích hợp, hãy lưu nội dung động vào bộ nhớ đệm (không bắt buộc) để xem ngoại tuyến.

Giao diện ứng dụng tải động nội dung cụ thể của trang thông qua API hoặc nội dung được gói trong JavaScript. Trình chạy dịch vụ cũng phải tự cập nhật theo nghĩa là nếu nội dung đánh dấu của giao diện ứng dụng thay đổi, bản cập nhật trình chạy dịch vụ sẽ chọn giao diện ứng dụng mới và lưu nó vào bộ nhớ đệm.

Xây dựng giao diện ứng dụng

Giao diện ứng dụng phải tồn tại độc lập với nội dung, nhưng vẫn cung cấp cơ sở cho nội dung được điền trong đó. Tốt nhất là quảng cáo nên càng gọn nhẹ càng tốt, nhưng bao gồm đủ nội dung có ý nghĩa trong tệp tải xuống ban đầu để người dùng hiểu rằng một trải nghiệm đang tải nhanh.

Sự cân bằng phù hợp tuỳ thuộc vào ứng dụng của bạn. Giao diện ứng dụng cho ứng dụng Được huấn luyện To Thrill của Jake Archibald bao gồm một tiêu đề với nút làm mới để lấy nội dung mới từ Flickr.

Ảnh chụp màn hình ứng dụng web Trained to Thrill ở hai trạng thái khác nhau. Ở bên trái, chỉ có giao diện ứng dụng được lưu vào bộ nhớ đệm hiển thị và không có nội dung nào được điền sẵn. Ở bên phải, nội dung (một vài hình ảnh của một số chuyến tàu) sẽ được tải động vào vùng nội dung của giao diện ứng dụng.

Mã đánh dấu shell ứng dụng sẽ khác nhau tuỳ theo dự án, nhưng sau đây là một ví dụ về tệp index.html cung cấp mã nguyên mẫu cho ứng dụng:

​​<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      Application Shell Example
    </title>
    <link rel="manifest" href="/manifest.json">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="styles/global.css">
  </head>
  <body>
    <header class="header">
      <!-- Application header -->
      <h1 class="header__title">Application Shell Example</h1>
    </header>

    <nav class="nav">
      <!-- Navigation items -->
    </nav>

    <main id="app">
      <!-- Where the application content populates -->
    </main>

    <div class="loader">
      <!-- Spinner/content placeholders -->
    </div>

    <!-- Critical application shell logic -->
    <script src="app.js"></script>

    <!-- Service worker registration script -->
    <script>
      if ('serviceWorker' in navigator) {
        // Register a service worker after the load event
        window.addEventListener('load', () => {
          navigator.serviceWorker.register('/sw.js');
        });
      }
    </script>
  </body>
</html>

Tuy nhiên, khi bạn xây dựng một giao diện ứng dụng cho dự án của mình, giao diện này phải có các đặc điểm sau:

  • HTML phải có các khu vực tách biệt rõ ràng cho từng phần tử giao diện người dùng riêng lẻ. Trong ví dụ trên, điều này bao gồm tiêu đề, điều hướng, vùng nội dung chính và không gian của ứng dụng "vòng quay" đang tải chỉ xuất hiện khi nội dung đang tải.
  • JavaScript và CSS ban đầu được tải cho giao diện ứng dụng phải ở mức tối thiểu và chỉ liên quan đến chức năng của chính giao diện ứng dụng chứ không liên quan đến nội dung. Điều này đảm bảo ứng dụng hiển thị shell nhanh nhất có thể và giảm thiểu công việc của luồng chính cho đến khi nội dung xuất hiện.
  • Tập lệnh cùng dòng đăng ký trình chạy dịch vụ.

Sau khi tạo xong giao diện ứng dụng, bạn có thể tạo một trình chạy dịch vụ để lưu cả giao diện này và nội dung của trình chạy dịch vụ đó vào bộ nhớ đệm.

Lưu giao diện ứng dụng vào bộ nhớ đệm

Giao diện ứng dụng và các phần tử cần thiết của nó là những gì mà worker dịch vụ nên lưu vào bộ nhớ đệm trước ngay lập tức tại thời điểm cài đặt. Giả sử một shell ứng dụng như ví dụ trên, hãy xem cách thực hiện việc này trong ví dụ cơ bản về Workbox sử dụng workbox-build:

// build-sw.js
import {generateSW} from 'workbox-build';

// Where the generated service worker will be written to:
const swDest = './dist/sw.js';

generateSW({
  swDest,
  globDirectory: './dist',
  globPatterns: [
    // The necessary CSS and JS for the app shell
    '**/*.js',
    '**/*.css',
    // The app shell itself
    'shell.html'
  ],
  // All navigations for URLs not precached will use this HTML
  navigateFallback: 'shell.html'
}).then(({count, size}) => {
  console.log(`Generated ${swDest}, which precaches ${count} assets totaling ${size} bytes.`);
});

Cấu hình này được lưu trữ trong build-sw.js sẽ nhập CSS và JavaScript của ứng dụng, bao gồm cả tệp đánh dấu giao diện ứng dụng có trong shell.html. Tập lệnh được thực thi với Nút như sau:

node build-sw.js

Trình chạy dịch vụ đã tạo được ghi vào ./dist/sw.js và sẽ ghi lại thông báo sau đây khi hoàn tất:

Generated ./dist/sw.js, which precaches 5 assets totaling 44375 bytes.

Khi trang tải, trình chạy dịch vụ sẽ lưu trước mã đánh dấu shell ứng dụng và các phần phụ thuộc của nó vào bộ nhớ đệm:

Ảnh chụp màn hình bảng điều khiển mạng trong Công cụ cho nhà phát triển của Chrome, trong đó cho thấy danh sách các thành phần đã tải xuống qua mạng. Những tài sản mà worker đã lưu trước vào bộ nhớ đệm sẽ khác với các tài sản khác bằng một biểu tượng bánh răng ở bên trái trong hàng. Một số tệp JavaScript và CSS được trình chạy dịch vụ lưu trước vào bộ nhớ đệm tại thời điểm cài đặt.
Trình chạy dịch vụ sẽ lưu trước trong bộ nhớ đệm các phần phụ thuộc của giao diện ứng dụng tại thời điểm cài đặt. Yêu cầu lưu trước vào bộ nhớ đệm là hai hàng cuối cùng và biểu tượng bánh răng bên cạnh yêu cầu cho biết trình chạy dịch vụ đã xử lý yêu cầu.

Bạn có thể lưu trước HTML, CSS và JavaScript trong giao diện của ứng dụng trong hầu hết mọi quy trình làm việc, bao gồm cả các dự án sử dụng trình gói ứng dụng. Trong quá trình xem qua tài liệu, bạn sẽ tìm hiểu cách sử dụng trực tiếp Workbox để thiết lập chuỗi công cụ nhằm tạo trình chạy dịch vụ phù hợp nhất cho dự án của mình, bất kể đó có phải là SPA hay không.

Kết luận

Việc kết hợp mô hình shell ứng dụng với một trình chạy dịch vụ là một lựa chọn lý tưởng cho việc lưu vào bộ nhớ đệm khi không có kết nối mạng, đặc biệt nếu bạn kết hợp chức năng lưu vào bộ nhớ đệm với chiến lược ưu tiên mạng, quay lại chiến lược lưu vào bộ nhớ đệm đối với mã đánh dấu hoặc phản hồi của API. Kết quả là một trải nghiệm nhanh và đáng tin cậy sẽ hiển thị ngay giao diện ứng dụng của bạn trong các lần truy cập lặp lại, ngay cả trong điều kiện ngoại tuyến.