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 trên blog kỹ thuật của web.dev. Trong những tháng tới, chúng tôi hy vọng sẽ chia sẻ thông tin chi tiết hữu ích từ công việc của mình — vì vậy, hãy xem các bài đăng có thẻ Blog về kỹ thuật! Ở đây, chúng ta sẽ đề cập đến quy trình xây dựng cho trang web tĩnh và (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. Người dùng thông thái có thể đã nhận ra rằng trang Đo lường chỉ là một giao diện cho Lighthouse, cũng có trong Công cụ cho nhà phát triển của Chrome. 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 thường 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ẽ xem lại trang Đo lường sau 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ừ 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ụ tinh tế, dễ mở rộng, giúp bạn dễ dàng chuyển Markdown thành HTML.

Chúng tôi cũng sử dụng các gói JavaScript hiện đại mà chúng tôi 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 sẵn sàng sử dụng các tính năng được các trình duyệt luôn cập nhật hỗ trợ, chứ không phải bởi một số ít các phiên bản cũ. Vì chúng tôi là một trang web tĩnh nên không bắt buộc phải có JavaScript để đọc nội dung của chúng tôi.

Sau khi quy trình xây dựng (bao gồm việc tạo HTML tĩnh và nhóm JavaScript với Rollup) hoàn tất, web.dev có thể được lưu trữ bằng một máy chủ tĩnh đơn giản để thử nghiệm. Trang web gần như hoàn toàn tĩnh, nhưng chúng tôi có một số nhu cầu đặc biệt vẫn được hưởng lợi từ máy chủ Node.js tuỳ chỉnh. 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ữ mà người dùng ưu tiên cho một tính năng quốc tế hoá sắp tới.

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ó nội dung chính, giúp mô tả siêu dữ liệu về mỗi bài đăng. Siêu dữ liệu này được nhập 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 đề nổi bật này cho phép chúng ta xác định các thuộc tính tuỳ ý như tác giả, ngày xuất bản và thẻ. Eleventy thuận tiện hiển thị vấn đề chính dưới dạng dữ liệu trong hầu hết mọi trình bổ trợ, mẫu hoặc bối cảnh khác mà chúng ta muốn làm gì đó thông minh. Đối tượng dữ liệu cũng chứa những gì được Eleventy mô tả là luồng dữ liệu – nhiều dữ liệu được lấy từ mỗi trang riêng lẻ, từ bố cục mà trang sử dụng và từ dữ liệu được tìm thấy 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 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 để tạo khung cho các loại nội dung khác nhau một cách chính xác (như bài đăng và lớp học lập trình) trong khi vẫn dùng chung 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 lập trình để tạo các tập hợp nội dung tuỳ ý. Việc này cho phép chúng tôi xây dựng tính năng hỗ trợ phân trang và tạo các trang ảo (các trang không có tệp Markdown trùng khớp trên ổ đĩa) cho tác giả bài đăng. Ví dụ: chúng tôi xây dựng 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 (để mẫu được hiển thị 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 dẫn đến 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 tôi khó có thể dễ dàng nắm bắt quy trình xây dựng của Eleventy vì quy trình này mang tính khai báo, thay vì bắt buộc: bạn mô tả điều mình muốn chứ không phải theo 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ì hệ thống chỉ có thể gọi Eleventy qua giao diện dòng lệnh.

Tạo khuôn

web.dev sử dụng hệ thống mẫu Nunjucks do Mozilla phát triển ban đầu. Nunjucks có các tính năng mẫu điển hình 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 ra 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 với quy mô nhỏ và thêm các mã ngắn theo thời gian — khoảng 20 mã cho đến nay. Hầu hết các công cụ 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 tôi). Ví dụ:

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

Mã sẽ có dạng như sau:

Nhưng thực ra HTML đang tạo ra 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 làm 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 bên trong. Các mã ngắn không bắt buộc phải trả về bất cứ thứ gì, vì vậy bạn có thể sử dụng chúng để 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à một trang web tĩnh nên có thể được phân phát và sử dụng mà không cần JavaScript và 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 ta. Đây là một phần cực kỳ quan trọng trong hướng tiếp cận của chúng tôi nhằm giúp mọi người dễ dàng truy cập vào web.dev.

Tuy nhiên, mã của chúng tôi cho các 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ã cho trạng thái chung, Analytics và định tuyến SPA
  2. Mã và CSS cho Thành phần web để dần cải thiệ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 trang đơn (SPA), vì vậy, chúng ta cài đặt một trình nghe chung để theo dõi 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, vì 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 chúng tôi dựa trên URL bạn đã nhấn và tải đúng một URL bằng import() động. Việc này giúp giảm bớt số byte mà người dùng cần trước khi trang web được nâng cao 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 các tên tuỳ chỉnh như <web-codelab>. Thiết kế này phù hợp với các trang web tĩnh chủ yếu 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ác trình duyệt cũ chỉ bỏ qua hoàn toàn Thành phần web và hiển thị bất kỳ thứ gì 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, một phần tử cung cấp 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 đến thành phần web hơn 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 thêm các phần tử 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 trong mã nguồn Markdown thông thường của chúng tôi 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, không chỉ nút Đo lường.

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

Sơ đồ thể hiện 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 toàn cục.
Trạng thái chung 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á các hành động và trạng thái chung. Ví dụ: web.dev cho phép bạn kiểm tra trang web yêu thích rồi chuyển khỏi trang Đo lường. Nếu quay lại, bạn sẽ thấy việc cần làm vẫn đang diễn ra.

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

Trò chuyện nhé

Nhóm kỹ thuật web.dev (Rob, Ewa, MichaelSam) sẽ sớm liên hệ lại để cung cấp thêm thông tin chuyên sâu về kỹ thuật.

Chúng tôi hy vọng khi biết cách chúng tôi làm mọi thứ, bạn sẽ có thêm ý tưởng cho các dự án của mình. Đừng ngại 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!