Progressive Web App (PWA)

Ngày 19/5/2020, Blazor WebAssembly đã trở thành công cụ chính thức của Microsoft thay vì các bản Preview trước đây. Nếu đang dùng Visual Studio 2019 Community (bản Windows) thì cần cập nhật lên phiên bản 16.6.

Một trong những khả năng quan trọng trong bản Blazor WebAssembly chính thức là hỗ trợ xây dựng các PWAs (Progressive Web Apps).  Một PWA là một SPA (Single Page Application) sử dụng các API từ các trình duyệt web hiện đại và có khả năng ứng xử như một ứng dụng desktop. Các đặc điểm chính của một PWA là:

  • Có thể làm việc offline và tải ngay tức thì không phụ thuộc vào tốc độ mạng
  • Có thể chạy trong cửa sổ ứng dụng (its own app window) không chỉ trong cửa sổ trình duyệt (a browser window)
  • Có thể khởi động từ hệ điều hành của host
  • Có thể nhận thông báo từ server ngay cả khi người dùng không dùng app
  • Cập nhật tự động

Tạo một Blazor PWA

Bài viết này sử dụng Visual Studio 2019 Community (bản Windows). Mở Visual Studio và chọn Create a new project. Tiếp tục chọn Blazor App trong khung Create a new project, nhập tên dự án MyFirstPWABlazor, chọn vị trí lưu, nhấn vào tùy chọn Progressive Web Application và nhấn Create

Chú ý rằng, bên cạnh tùy chọn Progressive Web Application, tùy chọn ASP.NET Core hosted cũng được đánh dấu. Mặc dù không đề cập trong bài viết này nhưng với các ứng dụng thực tế chúng ta thường tích hợp thêm các dịch vụ backend (hay các đoạn mã hướng server) và để làm được điều đó chúng ta cần tùy chọn ASP.NET Core hosted. Một lý do khác cho việc chọn ASP.NET Core hosted là để dễ dàng hơn trong việc thực thi các phiên bản đã được xuất bản trong môi trường phát triển cục bộ.

Thêm một thành phần Razor (Razor component)

Thêm một Razor Component bằng cách nhấn chuột vào thư mục Pages chọn Add > New Item > Razor Component, đổi tên thành MyCheckList.razor và nhấn Add. Nội dung mặc định của MyCheckList.razor


a<h3>MyCheckList</h3>

@code {

}

Trong bài Cài đặt bản Preview và tạo ứng dụng Blazor WebAssembly đầu tiên  chúng ta đã làm quen với cách sử dụng Razor component trong Index.razor và trong bài viết này chúng ta sẽ sử dụng chúng theo một cách khác.

Đầu tiên, chúng ta sẽ thêm chỉ danh @page cho phép truy cập đến MyCheckList.razor bằng cách thêm dòng mã sau vào đầu tập tin MyCheckList.razor:


@page "/mychecklist"

<h3>My Check List</h3>

@code {

}

Kế tiếp, chúng ta thêm một Razor component mới đến thanh điều hướng (navigation bar) bằng cách mở tập tin NavMenu.razor trong thư mục Shared và thêm đoạn mã sau phía trên Fetch data


<li class="nav-item px-3">

   <NavLink class="nav-link" href="mychecklist">

       <span class="oi oi-plus" aria-hidden="true"></span> My Check List

   </NavLink>

</li>

Để ý phần tử <NavLink> với thuộc tính href chứa giá trị là tên của MyCheckList.razor. Lưu và thực thi bằng cách chọn Debug > Start Without Debugging

Khung điều hướng bên trái chứa thêm mục My Check List truy cập đến MyCheckList.razor và bên phải là nội dung MyCheckList.razor.

Thêm mã C# đến MyCheckList.razor

Mục đích MyCheckList.razor của chúng ta là thể hiện danh sách công việc cần làm (jobName) và kiểm tra sự hoàn thành của mỗi công việc (isDone). Để làm được điều đó, chúng ta sẽ tạo một lớp gọi là CheckListItem và bởi vì dự án của chúng ta có thể thêm các đoạn mã server sau này (chọn ASP.NET Core host) nên lớp này sẽ được tạo trong dự án Shared cho phép chúng ta chia sẻ các tài nguyên dễ dàng bằng cách nhấn chuột phải vào MyFirstPWABlazor.Shared

chọn Add > Class, đổi tên lớp thành CheckListItem.cs trong mục Name và nhấn Add. Thay đổi nội dung tập tin CheckListItem như sau:


using System;

using System.Collections.Generic;

using System.Text;


namespace MyFirstPWABlazor.Shared

{

  public class CheckListItem

  {

    public string jobName { get; set; }

    public bool IsDone { get; set; }

  }

}

Lưu và trở lại tập tin MyCheckList.razor. Thêm một vài đoạn mã trong phần code:


@page "/mychecklist"

@using MyFirstPWABlazor.Shared

<h3>My Check List</h3>

<ul>

  @foreach (var job in jobList)

  {

     <li>@job.jobName</li>

  }

</ul>

<input placeholder="Something todo" @bind="newJob" />

<button @onclick="AddJob">Add todo</button>

@code {

   private IList<CheckListItem> jobList = new List<CheckListItem>();

   private string newJob;

   private void AddJob()

   {

      if (!string.IsNullOrWhiteSpace(newJob))

      {

        jobList.Add(new CheckListItem { jobName = newJob });

        newJob = string.Empty;

      }

   }

}

Một vài lưu ý về các đoạn mã trên:

  • Vì lớp CheckListItem được chứa trong dự án Shared nên chúng ta cần tham chiếu đến namespace chứa lớp này bằng cách dùng using:

@using MyFirstPWABlazor.Shared

  • Dùng mã kết C# lồng ghép mã HTML trong Razor dùng dấu @
  • Khai báo danh sách jobList chứa các thể hiện CheckListItem và duyệt qua các thể hiện này với foreach
  • Sử dụng một phần tử HTML input kết buộc dữ liệu đến newJob với thuộc tính @bind
  • Sử dụng một button thêm job mới hay gọi phương thức AddJob thông qua thuộc tính @onClick
  • Phương thức AddJob đảm bảo job phải được nhập vào input và thêm job này đến danh sách jobList

Thực thi ứng dụng bằng cách vào Debug > Start Without Debugging. Thêm job 1 và job 2 đến input và nhấn button

Mặc dù hiển thị danh sách cách công việc nhưng chưa có các checkbox cho phép chúng ta đánh dấu công việc hoàn thành. Cải thiện điều này bằng cách thay đổi nội dung trong vòng lặp foreach:


@foreach (var job in jobList)

{

  <li>

    <input type="checkbox" @bind="job.IsDone" />

    <input @bind="job.jobName" />

  </li>

}

Thực thi lại ứng dụng và đánh dầu job 1

Chúng ta có thể thêm dòng mã thống kê job nào đã hoàn thành (Done) và job nào đang thực hiện (Doing) bằng cách thêm dòng mã sau phía dước button:


<h4>Done:(@jobList.Count(job => job.IsDone)) Doing: (@jobList.Count(job => !job.IsDone))</h4>

Thực thi lại ứng dụng và thêm job 1, job 2

Đánh dấu hoàn thành vào job 1:

Cài đặt PWA

Bây giờ chúng ta có thể cài đặt một ứng dụng PWA trong trình duyệt (vi dụ Chrome) bằng cách nhấn vào dấu hiệu Instal MyFirstPWABlazor góc phải trình duyệt

Sẽ xuất hiện hộp thoại

Nhấn nút Install và lúc này ứng dụng của chúng ta sẽ ứng xử như một ứng dụng Desktop. Một icon ứng dụng sẽ xuất hiện trên Desktop

và khi ứng dụng thực thi cũng sẽ xuất hiện một icon trên thanh tác vụ:

Kiểm tra hỗ trợ offline

Mặc định, các ứng dụng PWA hỗ trợ thực thi chế độ offline nhưng trước đó chúng ta phải truy cập ứng dụng ở chế độ online. Khi truy cập online, trình duyệt sẽ tải và lưu tất cả tài nguyên ứng dụng hỗ trợ thực thi offline. Tuy nhiên, hỗ trợ offline chỉ áp dụng cho các ứng dụng đã được xuất bản.

Xuất bản ứng dụng MyFirstPWABlazor bằng cách nhấn chuột phải vào dự án MyFirstPWABlazor.Server và chọn Publish. Trong cửa sổ Publish xuất hiện ngay sau đó, chọn Folder và nhấn Next

Chọn thư mục chứa ứng dụng trong Folder location (chẳng hạn chọn ổ D:) và nhấn Finish. Cuối cùng, trong tab MyFirstPWABlazor.Server nhấn nút Publish:

Sau khi xuất bản thành công, trong thư mục chứa ứng dụng tìm đến tập tin MyFirstPWABlazor.Server

và nhấn đôi chuột trái để thực thi tập tin này. Kết quả

Như thông tin được cung cấp, chúng ta có thể thực thi ứng dụng trên cổng 5001

Chúng ta có thể dễ dàng kiểm tra khả năng hỗ trợ offline bằng cách chọn chế độ offline trên trình duyệt. Trong Chrome chúng ta có thể nhấn chuột trái vào dấu 3 chấm bên góc phải chọn More tools > Developer tools. Trong tab Network chọn Offline

Lúc này chúng ta có thể kiểm tra khả năng hỗ trợ offline của ứng dụng.