Để thiết kế ứng dụng nhằm khai thác tối đa công nghệ giúp PWA trở nên đáng tin cậy, có thể cài đặt và có khả năng, bạn cần bắt đầu bằng cách tìm hiểu ứng dụng và các quy tắc ràng buộc của ứng dụng, đồng thời chọn một cấu trúc phù hợp cho cả hai.
SPA so với MPA
Hiện nay, có hai mô hình kiến trúc chính trong phát triển web: ứng dụng trang đơn (SPA) và ứng dụng nhiều trang (MPA).
Ứng dụng trang đơn được định nghĩa bằng cách cho phép JavaScript phía máy khách kiểm soát hầu hết hoặc toàn bộ quá trình hiển thị HTML của một trang dựa trên dữ liệu do ứng dụng truy xuất hoặc cung cấp cho ứng dụng. Ứng dụng này sẽ ghi đè thành phần điều hướng tích hợp của trình duyệt, thay thế bằng chức năng định tuyến và xử lý chế độ xem.
Các ứng dụng nhiều trang thường có HTML được kết xuất trước được gửi trực tiếp đến trình duyệt, thường được cải tiến bằng JavaScript phía máy khách sau khi trình duyệt tải xong HTML và dựa vào cơ chế điều hướng tích hợp của trình duyệt để hiển thị các chế độ xem tiếp theo.
Bạn có thể dùng cả hai cấu trúc này để tạo PWA.
Mỗi loại đều có ưu và nhược điểm. Việc chọn loại phù hợp với trường hợp sử dụng và ngữ cảnh của bạn là yếu tố then chốt để mang lại trải nghiệm nhanh chóng và đáng tin cậy cho người dùng.
Ứng dụng một trang
- Chủ yếu là các bản cập nhật nguyên tử trong trang.
- Các phần phụ thuộc phía máy khách được tải khi khởi động.
- Các lần tải tiếp theo sẽ diễn ra nhanh chóng nhờ việc sử dụng bộ nhớ đệm.
- Chi phí tải ban đầu cao.
- Hiệu suất phụ thuộc vào phần cứng thiết bị và kết nối mạng.
- Cần có thêm độ phức tạp của ứng dụng.
Ứng dụng trang đơn phù hợp với cấu trúc nếu:
- Hoạt động tương tác của người dùng chủ yếu tập trung vào các bản cập nhật nguyên tử của dữ liệu được kết nối hiển thị trên cùng một trang, ví dụ: trang tổng quan dữ liệu theo thời gian thực hoặc ứng dụng chỉnh sửa video.
- Ứng dụng của bạn có các phần phụ thuộc khởi động chỉ phía máy khách, chẳng hạn như nhà cung cấp dịch vụ xác thực bên thứ ba có chi phí khởi động rất cao.
- Dữ liệu cần thiết để một thành phần hiển thị tải dựa vào một ngữ cảnh cụ thể chỉ dành cho phía máy khách, ví dụ: hiển thị các thành phần điều khiển cho một phần cứng đã kết nối.
- Ứng dụng này đủ nhỏ và đơn giản để kích thước và độ phức tạp của ứng dụng không ảnh hưởng đến các nhược điểm nêu trên.
SPA có thể không phải là lựa chọn kiến trúc phù hợp nếu:
- Hiệu suất tải ban đầu là yếu tố thiết yếu. SPA thường cần tải thêm JavaScript để xác định nội dung cần tải và cách hiển thị nội dung đó. Thời gian phân tích cú pháp và thực thi của JavaScript này (kết hợp với việc truy xuất nội dung) chậm hơn so với việc gửi HTML được hiển thị.
- Ứng dụng của bạn chủ yếu chạy trên các thiết bị có công suất từ thấp đến trung bình. Vì SPA phụ thuộc vào JavaScript để hiển thị, nên trải nghiệm người dùng phụ thuộc đáng kể vào sức mạnh của thiết bị cụ thể hơn nhiều so với trong MPA.
Vì SPA cần thay thế tính năng điều hướng tích hợp của trình duyệt bằng tính năng định tuyến, nên SPA yêu cầu mức độ phức tạp tối thiểu để cập nhật hiệu quả chế độ xem hiện tại, quản lý các thay đổi về điều hướng và dọn dẹp các chế độ xem trước đó mà trình duyệt sẽ xử lý, khiến việc duy trì tổng thể trở nên khó khăn hơn và gây nhiều hao tổn hơn cho thiết bị của người dùng.
Ứng dụng nhiều trang
- Chủ yếu là nội dung cập nhật toàn trang.
- Tốc độ kết xuất ban đầu rất quan trọng.
- Bạn có thể cải tiến bằng cách sử dụng tập lệnh phía máy khách.
- Khung hiển thị phụ yêu cầu một lệnh gọi máy chủ khác.
- Bối cảnh không chuyển qua lại giữa các khung hiển thị.
- Cần có máy chủ hoặc kết xuất trước.
Ứng dụng nhiều trang là một lựa chọn cấu trúc phù hợp nếu:
- Hoạt động tương tác của người dùng chủ yếu tập trung vào các chế độ xem của một phần dữ liệu có dữ liệu dựa trên bối cảnh không bắt buộc, ví dụ: ứng dụng tin tức hoặc thương mại điện tử.
- Tốc độ kết xuất ban đầu rất quan trọng vì việc gửi HTML đã kết xuất đến trình duyệt nhanh hơn so với việc tập hợp HTML từ một yêu cầu dữ liệu sau khi tải, phân tích cú pháp và thực thi một phương án thay thế dựa trên JavaScript.
- Ngữ cảnh hoặc khả năng tương tác phía máy khách có thể được đưa vào như một tính năng nâng cao sau lần tải đầu tiên, chẳng hạn như xếp lớp một hồ sơ vào một trang được hiển thị hoặc thêm các thành phần phụ thuộc vào ngữ cảnh phía máy khách phụ.
MPA có thể không phải là lựa chọn cấu trúc phù hợp nếu:
- Việc tải xuống lại, phân tích cú pháp lại và thực thi lại JavaScript hoặc CSS sẽ rất tốn kém. Rủi ro này được giảm thiểu trong PWA có trình chạy dịch vụ.
- Ngữ cảnh phía máy khách, chẳng hạn như vị trí của người dùng, không được chuyển liền mạch giữa các thành phần hiển thị và việc lấy lại ngữ cảnh đó có thể tốn kém. Bạn cần thu thập và truy xuất hoặc yêu cầu lại giữa các thành phần hiển thị.
Bởi vì từng khung hiển thị cần được máy chủ kết xuất động hoặc được kết xuất trước trước khi truy cập. Điều này có thể hạn chế việc lưu trữ hoặc tăng độ phức tạp của dữ liệu.
Bạn nên chọn loại nào?
Ngay cả với những ưu và nhược điểm này, cả hai cấu trúc đều hợp lệ để tạo PWA. Bạn thậm chí có thể kết hợp chúng cho các phần khác nhau trong ứng dụng, tuỳ theo nhu cầu của ứng dụng. Ví dụ: trang thông tin trên Cửa hàng Play tuân theo cấu trúc MPA còn quy trình thanh toán tuân theo cấu trúc SPA.
Bất kể lựa chọn nào, bước tiếp theo là tìm hiểu cách sử dụng trình chạy dịch vụ hiệu quả nhất để mang lại trải nghiệm tốt nhất.
Sức mạnh của trình chạy dịch vụ
Trình chạy dịch vụ có nhiều chức năng ngoài việc định tuyến và phân phối cơ bản các phản hồi mạng và lưu vào bộ nhớ đệm. Chúng tôi có thể tạo ra các thuật toán phức tạp để cải thiện hiệu suất và trải nghiệm của người dùng.
Trình chạy dịch vụ bao gồm (SWI)
Một mô hình mới nổi khi sử dụng trình chạy dịch vụ như một phần không thể thiếu trong cấu trúc của trang web là trình chạy dịch vụ (SWI). SWI chia từng nội dung riêng lẻ (thường là một trang HTML) thành nhiều phần dựa theo nhu cầu lưu vào bộ nhớ đệm, sau đó ghép chúng lại với nhau trong trình chạy dịch vụ để cải thiện tính nhất quán, hiệu suất và độ tin cậy, đồng thời giảm kích thước bộ nhớ đệm.
Hình ảnh này là một trang web mẫu. Trang này có 5 phần khác nhau, chia trang thành:
- Bố cục tổng thể.
- Tiêu đề chung (thanh tối ở trên cùng).
- Vùng nội dung (các dòng và hình ảnh ở giữa bên trái).
- Thanh bên (thanh cao màu tối trung bình ở giữa bên phải).
- Chân trang (thanh dưới cùng màu tối).
Bố cục tổng thể
Bố cục tổng thể không có khả năng thay đổi thường xuyên và không có phần phụ thuộc. Đây là một ứng cử viên phù hợp để lưu trước.
Đầu trang và chân trang
Tiêu đề và chân trang toàn cục chứa các thành phần như trình đơn trên cùng và chân trang của trang web, đồng thời đưa ra một thách thức cụ thể: nếu toàn bộ trang được lưu vào bộ nhớ đệm, thì các thành phần này có thể thay đổi giữa các lần tải trang, tuỳ thuộc vào thời điểm trang nhất định được lưu vào bộ nhớ đệm.
Bằng cách tách riêng và lưu các tệp này vào bộ nhớ đệm độc lập với nội dung, bạn có thể đảm bảo rằng người dùng sẽ luôn nhận được cùng một phiên bản, bất kể thời điểm lưu vào bộ nhớ đệm. Vì không được cập nhật thường xuyên nên đây cũng là những ứng dụng phù hợp để lưu vào bộ nhớ đệm trước. Tuy nhiên, các lớp này có một phần phụ thuộc: CSS và JavaScript của trang web.
CSS và JavaScript
Lý tưởng nhất là bạn nên lưu CSS và JavaScript của trang web vào bộ nhớ đệm bằng chiến lược xác thực lại khi đã cũ để cho phép cập nhật tăng dần mà không cần cập nhật trình chạy dịch vụ, như trường hợp của các thành phần được lưu vào bộ nhớ đệm trước. Tuy nhiên, bạn cũng cần duy trì các phiên bản này ở phiên bản tối thiểu bất cứ khi nào worker dịch vụ cập nhật bằng một tiêu đề hoặc chân trang chung mới. Do đó, bộ nhớ đệm của chúng cũng phải được cập nhật bằng phiên bản tài sản mới nhất khi trình chạy dịch vụ cài đặt.
Vùng nội dung
Tiếp theo là khu vực nội dung. Tuỳ thuộc vào tần suất cập nhật, bạn nên sử dụng chiến lược mạng trước hoặc nội dung cũ trong khi xác thực lại. Hình ảnh phải được lưu vào bộ nhớ đệm bằng chiến lược ưu tiên bộ nhớ đệm, như đã thảo luận trước đây.
Thanh bên
Cuối cùng, giả sử nội dung thanh bên có chứa nội dung phụ như thẻ và các mục có liên quan thì nội dung này không đủ quan trọng để lấy nội dung từ mạng. Chiến lược xác thực lại trong khi cũ sẽ hoạt động cho trường hợp này.
Sau khi tìm hiểu kỹ lưỡng, có thể bạn nghĩ rằng mình chỉ có thể lưu vào bộ nhớ đệm theo từng phần đối với các ứng dụng một trang. Tuy nhiên, bằng cách áp dụng các mẫu lấy cảm hứng từ tệp bao gồm phía cạnh hoặc tệp bao gồm phía máy chủ trong worker dịch vụ, với một số tính năng worker dịch vụ nâng cao, bạn có thể thực hiện việc này cho cả hai cấu trúc.
Tự thử
Bạn có thể dùng thử trình chạy dịch vụ này trong lớp học lập trình tiếp theo:
Hiện câu trả lời theo thời gian thực
Bạn có thể tạo trang trước đó bằng cách sử dụng mô hình vỏ ứng dụng trong thế giới SPA, trong đó vỏ ứng dụng được lưu vào bộ nhớ đệm, sau đó phân phát và nội dung được tải ở phía máy khách. Với việc ra mắt và cung cấp rộng rãi API Luồng, bạn có thể kết hợp cả vỏ ứng dụng và nội dung trong worker dịch vụ và truyền trực tuyến đến trình duyệt, mang đến cho bạn khả năng lưu vào bộ nhớ đệm linh hoạt của vỏ ứng dụng với tốc độ của MPA.
Việc này là do:
- Bạn có thể tạo luồng không đồng bộ, cho phép các phần khác nhau của luồng đến từ các nguồn khác.
- Người yêu cầu trong luồng có thể bắt đầu xử lý câu trả lời ngay khi có phần dữ liệu đầu tiên, thay vì đợi toàn bộ mục hoàn tất.
- Trình phân tích cú pháp được tối ưu hoá để truyền trực tuyến, bao gồm cả trình duyệt, có thể hiển thị dần nội dung của luồng trước khi luồng hoàn tất, giúp tăng tốc hiệu suất nhận thấy của phản hồi.
Nhờ ba thuộc tính này của luồng, các kiến trúc được xây dựng dựa trên tính năng phát trực tiếp thường có hiệu suất cảm nhận được nhanh hơn so với các kiến trúc không có.
Việc làm việc với Streams API có thể gặp khó khăn vì API này phức tạp và ở cấp thấp. May mắn là có một mô-đun Workbox có thể giúp bạn thiết lập phản hồi truyền trực tuyến cho worker dịch vụ.
Miền, nguồn gốc và phạm vi PWA
Tất cả worker trên web, bao gồm cả worker dịch vụ, bộ nhớ, thậm chí cả cửa sổ của một PWA đã cài đặt, đều tuân theo một trong những cơ chế bảo mật quan trọng nhất trên web: chính sách cùng nguồn gốc. Trong cùng một nguồn gốc, các quyền sẽ được cấp, dữ liệu có thể được chia sẻ và trình chạy dịch vụ có thể trao đổi với nhiều ứng dụng. Ngoài cùng một nguồn gốc, các quyền sẽ không được cấp tự động và dữ liệu sẽ bị tách biệt và không truy cập được giữa các nguồn gốc khác nhau.
Chính sách cùng nguồn gốc
Hai URL được xác định là có cùng nguồn gốc nếu giao thức, cổng và máy chủ lưu trữ giống nhau.
Ví dụ: https://squoosh.app
và https://squoosh.app/v2
có cùng nguồn gốc, nhưng http://squoosh.app
, https://squoosh.com
, https://app.squoosh.app
và https://squoosh.app:8080
có nguồn gốc khác nhau. Hãy xem tài liệu tham khảo MDN về chính sách cùng nguồn gốc để biết thêm thông tin và ví dụ.
Việc thay đổi miền con không phải là cách duy nhất mà máy chủ lưu trữ có thể thay đổi. Mỗi máy chủ lưu trữ bao gồm một miền cấp cao nhất (TLD), một miền cấp hai (SLD) và từ 0 đến nhiều nhãn (đôi khi được gọi là miền con), được phân tách bằng dấu chấm ở giữa và đọc từ phải sang trái trong URL. Nếu bạn thay đổi bất kỳ mục nào, thì máy chủ lưu trữ sẽ khác.
Trong mô-đun quản lý cửa sổ, chúng ta đã thấy giao diện của trình duyệt trong ứng dụng khi người dùng chuyển đến một nguồn gốc khác với PWA đã cài đặt.
Trình duyệt trong ứng dụng đó sẽ xuất hiện ngay cả khi các trang web có cùng TLD và SLD nhưng có nhãn khác nhau, vì sau đó chúng được coi là có nguồn gốc khác nhau.
Một trong những khía cạnh chính của một nguồn gốc trong ngữ cảnh duyệt web là cách hoạt động của bộ nhớ và quyền. Một nguồn gốc chia sẻ nhiều tính năng giữa tất cả nội dung và PWA trong đó, bao gồm:
- Dữ liệu và hạn mức bộ nhớ (IndexedDB, cookie, bộ nhớ trên web, bộ nhớ bộ nhớ đệm).
- Lượt đăng ký trình chạy dịch vụ.
- Quyền được cấp hoặc bị từ chối (chẳng hạn như thông báo đẩy web, thông tin vị trí địa lý, cảm biến).
- Lượt đăng ký thông báo đẩy trên web.
Khi bạn di chuyển từ nguồn gốc này sang nguồn khác, toàn bộ quyền truy cập trước đó sẽ bị thu hồi. Vì vậy, bạn sẽ phải cấp lại các quyền và PWA của bạn không thể truy cập vào tất cả dữ liệu đã lưu trong bộ nhớ.