blog kỹ thuật web.dev #1: Cách chúng tôi xây dựng trang web và sử dụng Thành phần web

Đây là bài đăng đầu tiên trong blog kỹ thuật của web.dev. Trong những tháng tới, chúng tôi hy vọng có thể chia sẻ những thông tin chi tiết hữu ích từ công việc của mình. Vì vậy, hãy chú ý đến các bài đăng có thẻ Blog kỹ thuật! Ở đây, chúng ta sẽ đề cập đến quy trình xây dựng trang web tĩnh (không bắt buộc!) JavaScript đằng sau các thành phần web của chúng tôi.

web.dev cung cấp nội dung về cách xây dựng trải nghiệm web hiện đại và cho phép bạn đo lường hiệu suất của trang web. Những người dùng tinh ý có thể nhận ra rằng trang Đo lường của chúng tôi chỉ là một giao diện cho Lighthouse. Công cụ này cũng có trong Công cụ của Chrome cho nhà phát triển. Khi đăng nhập vào web.dev, bạn có thể chạy các quy trình kiểm tra Lighthouse thường xuyên trên trang web của mình để xem điểm số của trang web thay đổi như thế nào theo thời gian. Tôi sẽ quay lại trang Đo lường sau một lát vì chúng tôi cho rằng trang này khá đặc biệt. 🎊

Giới thiệu

Về cơ bản, web.dev là một trang web tĩnh được tạo từ một tập hợp các tệp Markdown. Chúng tôi đã chọn sử dụng Eleventy vì đây là một công cụ chỉn chu, có thể mở rộng, giúp bạn dễ dàng chuyển Markdown thành HTML.

Chúng tôi cũng dùng các gói JavaScript hiện đại mà chỉ phân phát cho các trình duyệt hỗ trợ type="module", bao gồm asyncawait. Chúng tôi cũng rất vui khi sử dụng các tính năng được trình duyệt Evergreen hỗ trợ nhưng không được một số phiên bản cũ hỗ trợ. Vì chúng tôi là một trang web tĩnh nên JavaScript chỉ không cần thiết để đọc nội dung của chúng tôi.

Sau khi quá trình tạo bản dựng (bao gồm việc tạo HTML tĩnh và đóng gói JavaScript bằng Rollup) hoàn tất, bạn có thể lưu trữ web.dev bằng một máy chủ tĩnh đơn giản để kiểm thử. Trang web này gần hoàn toàn tĩnh, nhưng chúng tôi có một vài nhu cầu đặc biệt vẫn được hưởng lợi từ máy chủ Node.js tuỳ chỉnh. Các mã này bao gồm lệnh chuyển hướng cho các miền không hợp lệ, cũng như mã để phân tích cú pháp ngôn ngữ ưu tiên của người dùng cho một tính năng quốc tế hoá sắp ra mắt.

Tạo tĩnh

Mỗi trang trên web.dev đều được viết bằng Markdown. Tất cả các trang đều có phần trước mô tả siêu dữ liệu về từng bài đăng. Siêu dữ liệu này được đưa vào bố cục của mỗi trang, tạo tiêu đề, thẻ, v.v. Ví dụ:

---
layout: post
title: What is network reliability and how do you measure it?
authors:
  - jeffposnick
date: 2018-11-05
description: |
  The modern web is enjoyed by a wide swath of people…
---

The modern web is enjoyed by a wide swath of [people](https://www.youtube.com/watch?v=dQw4w9WgXcQ), using a range of different devices and types of network connections.

Your creations can reach users all across the world...

Vấn đề trước này cho phép chúng tôi xác định các thuộc tính tuỳ ý như(các) tác giả, ngày xuất bản và thẻ. Eleventy hiển thị thuận tiện phần đầu trang dưới dạng dữ liệu trong hầu hết mọi trình bổ trợ, mẫu hoặc ngữ cảnh khác mà chúng ta muốn thực hiện một thao tác thông minh. Đối tượng dữ liệu này cũng chứa dữ liệu mà Eleventy mô tả là phân cấp dữ liệu – một loạt dữ liệu được lấy từ từng trang, từ bố cục mà trang sử dụng và từ dữ liệu trong cấu trúc thư mục phân cấp.

Mỗi bố cục riêng biệt mô tả một loại nội dung khác nhau và có thể kế thừa từ các bố cục khác. Trên web.dev, chúng tôi sử dụng tính năng này để định dạng chính xác các loại nội dung (như bài đăng và lớp học lập trình) trong khi vẫn chia sẻ một bố cục HTML cấp cao nhất.

Bộ sưu tập

Eleventy cung cấp một phương thức có lập trình để tạo các bộ sưu tập nội dung tuỳ ý. Điều này cho phép chúng tôi xây dựng tính năng phân trang và tạo các trang ảo (trang không có tệp Markdown phù hợp trên ổ đĩa) cho tác giả bài đăng. Ví dụ: chúng tôi tạo các trang tác giả bằng cách sử dụng một mẫu chứa biểu thức cho đường liên kết cố định của trang (để mẫu được kết xuất lại cho mọi tác giả) và một bộ sưu tập sao lưu.

Ví dụ: việc này sẽ tạo ra một trang đơn giản chứa tất cả bài đăng của Addy!

Các điểm hạn chế

Hiện tại, chúng ta không thể dễ dàng kết nối với quy trình xây dựng của Eleventy vì quy trình này khai báo thay vì bắt buộc: bạn mô tả những gì bạn muốn thay vì cách bạn muốn. Rất khó để chạy Eleventy trong một công cụ xây dựng lớn hơn, vì bạn chỉ có thể gọi công cụ này thông qua giao diện dòng lệnh.

Tạo mẫu

web.dev sử dụng hệ thống tạo mẫu Nunjucks do Mozilla phát triển ban đầu. Nunjucks có các tính năng tạo mẫu thông thường như vòng lặp và điều kiện, nhưng cũng cho phép chúng ta xác định mã ngắn để tạo thêm HTML hoặc gọi logic khác.

Giống như hầu hết các nhóm xây dựng trang web nội dung tĩnh, chúng tôi bắt đầu từ những mã ngắn nhỏ và thêm dần theo thời gian. Đến nay, chúng tôi đã có khoảng 20 mã ngắn. Hầu hết các thành phần này chỉ tạo thêm HTML (bao gồm cả các thành phần web tuỳ chỉnh của chúng ta). Ví dụ:

{% Aside %}
See how Asides work in the web.dev codebase
{% endAside %}

Ứng dụng sẽ hiển thị như sau:

Nhưng thực tế là hàm này tạo HTML có dạng như sau:

<div class="aside color-state-info-text">
<p>See how Asides work in the web.dev codebase</p>
</div>

Mặc dù nằm ngoài phạm vi của bài đăng này, nhưng web.dev cũng sử dụng mã ngắn dưới dạng một loại ngôn ngữ lập trình siêu dữ liệu. Mã ngắn chấp nhận các đối số, trong đó một trong các đối số là nội dung được chứa. Bạn không bắt buộc phải trả về bất kỳ nội dung nào bằng mã ngắn, vì vậy, bạn có thể sử dụng mã ngắn để tạo trạng thái hoặc kích hoạt một số hành vi khác. 🤔💭

Lên nội dung

Như đã đề cập trước đó, vì web.dev là trang web tĩnh nên nó có thể được phân phát và sử dụng mà không cần JavaScript cũng như bởi các trình duyệt cũ không hỗ trợ type="module" hoặc mã hiện đại khác của chúng tôi. Đây là một phần cực kỳ quan trọng trong phương pháp của chúng tôi để giúp mọi người có thể tiếp cận web.dev.

Tuy nhiên, mã của chúng ta cho trình duyệt hiện đại bao gồm hai phần chính:

  1. Mã tự khởi động, bao gồm mã để định tuyến trạng thái toàn cầu, Analytics và SPA
  2. Mã và CSS cho Thành phần web giúp nâng cao dần trang web

Mã khởi động khá đơn giản: web.dev có thể tải các trang mới dưới dạng một ứng dụng một trang (SPA), vì vậy, chúng ta sẽ cài đặt một trình nghe toàn cục để nghe các lượt nhấp vào các phần tử <a href="..."> cục bộ. Mô hình SPA giúp chúng tôi duy trì trạng thái chung về phiên hiện tại của người dùng, nếu không mỗi lượt tải trang mới sẽ kích hoạt lệnh gọi đến Firebase để truy cập vào trạng thái đã đăng nhập của người dùng.

Chúng tôi cũng chỉ định một số điểm truy cập khác nhau vào trang web của mình dựa trên URL mà bạn đã truy cập và tải URL chính xác bằng import() động. Điều này giúp giảm số byte mà người dùng cần trước khi trang web được cải thiện bằng mã.

Thành phần web

Thành phần web là các phần tử tuỳ chỉnh đóng gói chức năng thời gian chạy được cung cấp trong JavaScript và được xác định bằng tên tuỳ chỉnh như <web-codelab>. Thiết kế này phù hợp với các trang web chủ yếu là tĩnh như web.dev: trình duyệt của bạn quản lý vòng đời của một phần tử khi HTML của trang web được cập nhật, thông báo chính xác cho mọi phần tử khi chúng được đính kèm hoặc tách khỏi trang. Còn các trình duyệt lỗi thời chỉ bỏ qua hoàn toàn các Thành phần web và hiển thị mọi thứ còn lại trong DOM.

Mỗi Thành phần web là một lớp có các phương thức bao gồm connectedCallback(), disconnectedCallback()attributeChangedCallback(). Các phần tử tuỳ chỉnh của web.dev chủ yếu kế thừa từ LitElement, cung cấp một cơ sở đơn giản cho các thành phần phức tạp.

Mặc dù web.dev sử dụng Thành phần web trên nhiều trang, nhưng không có nơi nào cần thiết hơn như trên trang Đo lường. Hai phần tử cung cấp phần lớn chức năng mà bạn thấy trên trang này:

<web-url-chooser-container></web-url-chooser-container>
<web-lighthouse-scores-container></web-lighthouse-scores-container>

Các phần tử này tạo ra các phần tử khác cung cấp thêm chức năng. Quan trọng là các phần tử này chỉ là một phần của mã nguồn Markdown thông thường và nhóm nội dung của chúng tôi có thể thêm chức năng mở rộng vào bất kỳ trang nào, chứ không chỉ nút Đo lường.

Thành phần web của chúng ta thường sử dụng mô hình Thành phần vùng chứa do React phổ biến, mặc dù mô hình này hiện đã hơi lỗi thời. Mỗi phần tử -container kết nối với trạng thái toàn cục của chúng ta (do unistore cung cấp), sau đó hiển thị một phần tử hình ảnh, từ đó tiếp tục hiển thị các nút DOM thực tế có kiểu hoặc chức năng tích hợp khác.

Sơ đồ cho thấy mối quan hệ giữa trạng thái toàn cục và các phần tử HTML sử dụng trạng thái đó.
Trạng thái toàn cục và thành phần web

Các Thành phần web phức tạp nhất của chúng tôi tồn tại để trực quan hoá trạng thái và hành động chung. Ví dụ: web.dev cho phép bạn kiểm tra trang web yêu thích của mình rồi rời khỏi trang Đo lường. Nếu quay lại, bạn sẽ thấy tác vụ vẫn đang diễn ra.

Các thành phần đơn giản của chúng tôi chỉ làm tăng cường nội dung tĩnh hoặc tạo hình ảnh trực quan tuyệt vời (ví dụ: mỗi biểu đồ đường là một <web-sparkline-chart> riêng), không có mối quan hệ với trạng thái toàn cục.

Hãy trò chuyện

Nhóm kỹ sư web.dev (Rob, Ewa, MichaelSam) sẽ sớm cung cấp thêm thông tin chuyên sâu về kỹ thuật.

Chúng tôi hy vọng rằng việc tìm hiểu cách chúng tôi làm việc đã giúp bạn có thêm ý tưởng cho các dự án của riêng mình. Hãy liên hệ với chúng tôi trên Twitter nếu bạn có câu hỏi hoặc yêu cầu về chủ đề cho blog này!