web.dev Engineering Blog #1: วิธีสร้างเว็บไซต์และใช้คอมโพเนนต์ของเว็บ

นี่เป็นโพสต์แรกในบล็อกด้านวิศวกรรมของ web.dev ในอีกไม่กี่เดือนข้างหน้า เราหวังว่าจะได้แชร์ข้อมูลเชิงลึกที่นำไปใช้ได้จริงจากงานของเรา ดังนั้นให้รอดูโพสต์ด้วยแท็กบล็อกด้านวิศวกรรม เราจะพูดถึงขั้นตอนการสร้างสำหรับเว็บไซต์แบบคงที่และ (ไม่บังคับ) JavaScript เบื้องหลังคอมโพเนนต์เว็บของเรา

web.dev มีเนื้อหาเกี่ยวกับการสร้างประสบการณ์การใช้งานเว็บที่ทันสมัยและให้คุณวัดประสิทธิภาพของเว็บไซต์ได้ ผู้ใช้ที่เชี่ยวชาญอาจทราบว่าหน้าการวัดผลของเราเป็นเพียงอินเทอร์เฟซสำหรับ Lighthouse ซึ่งมีอยู่ในเครื่องมือสำหรับนักพัฒนาเว็บของ Chrome ด้วย การลงชื่อเข้าใช้ web.dev ช่วยให้คุณดำเนินการตรวจสอบ Lighthouse ในเว็บไซต์เป็นประจำได้ เพื่อดูว่าคะแนนเปลี่ยนแปลงไปอย่างไรเมื่อเวลาผ่านไป ฉันจะกลับมาดูหน้าการวัดผลในภายหลังเนื่องจากเห็นว่าค่อนข้างพิเศษ 🎊

เกริ่นนำ

โดยพื้นฐานแล้ว web.dev เป็นเว็บไซต์แบบคงที่ที่สร้างขึ้นจากคอลเล็กชันไฟล์ Markdown เราเลือกใช้ Eleventy เนื่องจากเป็นเครื่องมือที่ยืดหยุ่นและมีประสิทธิภาพ ซึ่งช่วยให้เปลี่ยน Markdown เป็น HTML ได้อย่างง่ายดาย

นอกจากนี้เรายังใช้แพ็กเกจ JavaScript สมัยใหม่ที่เราแสดงในเบราว์เซอร์ที่รองรับ type="module" เท่านั้น ซึ่งรวมถึง async และ await นอกจากนี้ เรายังยินดีใช้ฟีเจอร์ที่รองรับเบราว์เซอร์ที่อัปเดตอยู่เสมอ แต่ไม่ใช่เวอร์ชันเก่าที่มีส่วนน้อย เนื่องจากเราเป็นเว็บไซต์แบบคงที่ ดังนั้น JavaScript จึงไม่จำเป็นในการอ่านเนื้อหา

เมื่อกระบวนการบิลด์ ซึ่งเกี่ยวข้องกับการสร้าง HTML แบบคงที่และรวม JavaScript กับ Rollup เสร็จสมบูรณ์แล้ว คุณสามารถโฮสต์ web.dev กับเซิร์ฟเวอร์แบบคงที่แบบง่ายสำหรับการทดสอบได้ เว็บไซต์เกือบคงที่เลย แต่เรามีความต้องการพิเศษบางอย่างที่ยังได้รับประโยชน์จากเซิร์ฟเวอร์ Node.js ที่กำหนดเอง ซึ่งรวมถึงการเปลี่ยนเส้นทางสำหรับโดเมนที่ไม่ถูกต้อง รวมทั้งโค้ดเพื่อแยกวิเคราะห์ภาษาที่ผู้ใช้ต้องการสำหรับฟีเจอร์การปรับให้เป็นสากลที่กำลังจะเปิดตัว

การสร้างแบบคงที่

แต่ละหน้าบน web.dev จะเขียนด้วยมาร์กดาวน์ ทุกหน้าจะมีประเด็นด้านหน้า ซึ่งอธิบายข้อมูลเมตาเกี่ยวกับแต่ละโพสต์ ระบบจะนำเข้าข้อมูลเมตานี้ไปยังเลย์เอาต์ของแต่ละหน้า ซึ่งจะสร้างส่วนหัว แท็ก และอื่นๆ ตัวอย่าง

---
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...

ส่วนหน้านี้จะช่วยให้เราสามารถกำหนดพร็อพเพอร์ตี้ที่กำหนดเอง เช่น ผู้แต่ง วันที่เผยแพร่ และแท็ก 11ty แสดงส่วนด้านหน้าได้อย่างสะดวกว่าเป็นข้อมูลในเกือบทุกปลั๊กอิน เทมเพลต หรือบริบทอื่นๆ ที่เราต้องการทำสิ่งอัจฉริยะ ออบเจ็กต์ข้อมูลยังมีสิ่งที่ Eleventy อธิบายไว้ว่าเป็นการเรียงซ้อนข้อมูล ซึ่งเป็นข้อมูลที่หลากหลายที่ดึงมาจากแต่ละหน้า จากการจัดวางที่หน้าเว็บใช้ และจากข้อมูลที่พบในโครงสร้างโฟลเดอร์แบบลำดับชั้น

โดยเลย์เอาต์ที่ไม่ซ้ำกันแต่ละแบบจะอธิบายเนื้อหาประเภทต่างๆ และรับค่าจากเลย์เอาต์อื่นๆ ได้ ใน web.dev เราใช้ฟีเจอร์นี้เพื่อจัดเฟรมเนื้อหาประเภทต่างๆ (เช่น โพสต์และ Codelab) อย่างถูกต้อง ในขณะที่ยังคงแชร์เลย์เอาต์ HTML ระดับบนสุดไว้ 1 แบบ

คอลเล็กชัน

Eleventy เป็นวิธีการสร้างคอลเล็กชันเนื้อหาที่กำหนดเองโดยใช้โปรแกรม วิธีนี้ช่วยให้เราสร้างการรองรับการใส่เลขหน้าและสร้างหน้าเว็บเสมือน (หน้าเว็บที่ไม่มีไฟล์ Markdown ที่ตรงกันในดิสก์) สำหรับผู้เขียนโพสต์ได้ ตัวอย่างเช่น เราสร้างหน้าของผู้เขียนโดยใช้เทมเพลตที่มีนิพจน์สำหรับลิงก์ถาวร (เพื่อให้เทมเพลตแสดงผลอีกครั้งสำหรับผู้แต่งทุกคน) และคอลเล็กชันสนับสนุน

ซึ่งส่งผลให้เกิดหน้าแบบง่ายที่มีโพสต์ของ Addy ทั้งหมด เป็นต้น

ข้อจำกัด

ตอนนี้เราไม่สามารถทำตามกระบวนการบิลด์ของ Eleventy ได้อย่างง่ายดายเพราะเป็นการดำเนินการที่ประกาศ ไม่ใช่ความจำเป็น กล่าวคือคุณต้องอธิบายสิ่งที่คุณต้องการ ไม่ใช่สิ่งที่ต้องการ การเรียกใช้ Eleventy ซึ่งเป็นส่วนหนึ่งของเครื่องมือสร้างขนาดใหญ่นั้นทำได้ยาก เนื่องจากสามารถเรียกใช้ได้ผ่านอินเทอร์เฟซบรรทัดคำสั่งเท่านั้น

เทมเปิล

web.dev ใช้ระบบเทมเพลต Nunjucks ซึ่งพัฒนาโดย Mozilla ซึ่งเป็นต้นฉบับ Nunjucks มีฟีเจอร์เทมเพลตโดยทั่วไป เช่น ลูปและเงื่อนไข และยังให้เรากำหนด shortcode ที่สร้าง HTML เพิ่มเติมหรือเรียกใช้ตรรกะอื่น

เช่นเดียวกับทีมส่วนใหญ่ที่สร้างเว็บไซต์เนื้อหาแบบคงที่ เราเริ่มต้นจากโค้ดย่อเล็กๆ และเพิ่มรหัสย่อลงไปเรื่อยๆ ซึ่งจนถึงตอนนี้ก็ราว 20 ตัวอักษรแล้ว รูปแบบเหล่านี้ส่วนใหญ่จะสร้าง HTML เพิ่มเติมเท่านั้น (รวมถึงคอมโพเนนต์เว็บที่กำหนดเองของเรา) ตัวอย่าง

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

ซึ่งจะมีลักษณะดังนี้

แต่จริงๆ แล้วการสร้าง HTML มีลักษณะเช่นนี้

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

แม้ว่าไม่อยู่ในขอบเขตของโพสต์นี้ แต่ web.dev ยังใช้รหัสย่อเป็นภาษาเมตาโปรแกรมภาษาหนึ่งด้วย โค้ดย่อจะยอมรับอาร์กิวเมนต์ โดยหนึ่งในอาร์กิวเมนต์เป็นเนื้อหาที่มี รหัสย่อไม่จำเป็นว่าจะต้องส่งคืนสิ่งใด จึงสามารถนำรหัสเหล่านั้นไปใช้สร้างสถานะหรือทริกเกอร์การทำงานบางอย่างได้ 🤔💭

การเขียนสคริปต์

ดังที่กล่าวไว้ก่อนหน้านี้ เนื่องจาก web.dev เป็นเว็บไซต์แบบคงที่จึงให้บริการและใช้งานได้โดยไม่ต้องมี JavaScript และเบราว์เซอร์รุ่นเก่าที่ไม่รองรับ type="module" หรือโค้ดสมัยใหม่อื่นๆ ของเรา ซึ่งเป็นส่วนสำคัญอย่างยิ่งในแนวทางของเราในการทำให้ทุกคนเข้าถึง web.dev ได้

อย่างไรก็ตาม โค้ดสำหรับเบราว์เซอร์ที่ทันสมัยประกอบด้วย 2 ส่วนหลัก ได้แก่

  1. โค้ด Bootstrap ซึ่งประกอบด้วยรหัสสำหรับสถานะส่วนกลาง, Analytics และการกำหนดเส้นทาง SPA
  2. โค้ดและ CSS สำหรับคอมโพเนนต์เว็บที่ช่วยปรับปรุงเว็บไซต์อย่างต่อเนื่อง

โค้ด Bootstrap ค่อนข้างตรงไปตรงมา นั่นคือ web.dev สามารถโหลดหน้าเว็บใหม่ๆ เป็นแอปพลิเคชันหน้าเว็บเดียว (SPA) เราจึงติดตั้ง Listener ส่วนกลางที่คอยฟังการคลิกองค์ประกอบ <a href="..."> ในเครื่อง รูปแบบ SPA ช่วยให้เรารักษาสถานะโดยรวมเกี่ยวกับเซสชันปัจจุบันของผู้ใช้ไว้ ไม่เช่นนั้นการโหลดหน้าเว็บใหม่แต่ละครั้งจะทริกเกอร์การเรียก Firebase เพื่อเข้าถึงสถานะการลงชื่อเข้าใช้ของผู้ใช้

นอกจากนี้ เรายังระบุจุดเข้าต่างๆ 2 จุดในเว็บไซต์ของเราตาม URL ที่คุณคลิก และโหลดจุดที่ถูกต้องโดยใช้ import() แบบไดนามิก ซึ่งจะช่วยลดจำนวนไบต์ที่ผู้ใช้ของเราต้องใช้ก่อนที่จะปรับปรุงเว็บไซต์ด้วยโค้ด

คอมโพเนนต์ของเว็บ

คอมโพเนนต์เว็บคือองค์ประกอบที่กำหนดเองซึ่งห่อหุ้มฟังก์ชันรันไทม์ที่ให้ไว้ใน JavaScript และระบุโดยชื่อที่กำหนดเอง เช่น <web-codelab> การออกแบบทำงานได้ดีกับเว็บไซต์แบบคงที่ส่วนใหญ่ เช่น web.dev โดยเบราว์เซอร์จะจัดการวงจรการใช้งานขององค์ประกอบเมื่อ HTML ของเว็บไซต์มีการอัปเดต เพื่อแจ้งให้คุณทราบถึงองค์ประกอบต่างๆ เมื่อมีการแนบหรือแยกออกจากหน้าเว็บอย่างถูกต้อง และเบราว์เซอร์ที่ล้าสมัยจะไม่สนใจคอมโพเนนต์ของเว็บ รวมถึงแสดงผลสิ่งที่ค้างอยู่ใน DOM

คอมโพเนนต์เว็บแต่ละรายการเป็นคลาสที่มีเมธอด ได้แก่ connectedCallback(), disconnectedCallback() และ attributeChangedCallback() องค์ประกอบที่กำหนดเองของ web.dev ส่วนใหญ่รับค่ามาจาก LitElement ซึ่งเป็นฐานที่เรียบง่ายสำหรับคอมโพเนนต์ที่ซับซ้อน

แม้ว่า web.dev จะใช้คอมโพเนนต์ของเว็บในหลายๆ หน้า แต่จริงๆ แล้วมีความจำเป็นมากกว่าในหน้าวัดผล องค์ประกอบ 2 อย่างต่อไปนี้เป็นฟังก์ชันการทำงานจำนวนมากที่คุณเห็นในหน้านี้

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

องค์ประกอบเหล่านี้จะสร้างองค์ประกอบเพิ่มเติมที่มีฟังก์ชันการทำงานมากกว่า ที่สำคัญองค์ประกอบเหล่านี้เป็นเพียงส่วนหนึ่งของซอร์สโค้ดปกติของ Markdown และทีมเนื้อหาของเราสามารถเพิ่มฟังก์ชันการทํางานเพิ่มเติมลงในหน้าใดก็ได้ ไม่ใช่แค่โหนด Measure

คอมโพเนนต์เว็บของเรามักจะใช้โมเดลคอมโพเนนต์คอนเทนเนอร์ ซึ่งได้รับความนิยมจาก React แม้ว่าโมเดลนี้จะจบเพียงเท่านี้ก็ตาม องค์ประกอบ -container แต่ละรายการจะเชื่อมต่อกับสถานะส่วนกลางของเรา (ให้บริการโดย unistore) จากนั้นแสดงผลองค์ประกอบภาพ ซึ่งต่อมาจะแสดงผลโหนด DOM จริงที่มีการจัดรูปแบบหรือฟังก์ชันอื่นๆ ในตัว

แผนภาพที่แสดงความสัมพันธ์ระหว่างสถานะส่วนกลางกับองค์ประกอบ HTML ที่ใช้องค์ประกอบนี้
สถานะส่วนกลางและคอมโพเนนต์ของเว็บ

คอมโพเนนต์เว็บที่ซับซ้อนที่สุดของเรามีไว้เพื่อแสดงภาพการดำเนินการและสถานะทั่วโลก ตัวอย่างเช่น web.dev ช่วยให้คุณตรวจสอบเว็บไซต์โปรดแล้วออกจากหน้าวัดผลได้ หากคุณกลับมา คุณจะเห็นว่างานนี้ยังดำเนินอยู่

องค์ประกอบง่ายๆ ของเราจะช่วยเพิ่มประสิทธิภาพให้เนื้อหาคงที่เพียงอย่างเดียว หรือสร้างการแสดงภาพที่น่าทึ่ง (เช่น กราฟเส้นแต่ละเส้นจะเป็น <web-sparkline-chart> ของตัวเอง) ซึ่งไม่มีความเกี่ยวข้องกับรัฐทั่วโลก

มาแชทกัน

ทีมวิศวกรของ web.dev (Rob, Ewa, Michael และ Sam) จะติดตามผลด้วยการเจาะลึกทางเทคนิคเพิ่มเติมในเร็วๆ นี้

เราหวังว่าการได้ฟังเกี่ยวกับวิธีที่เราทำสิ่งต่างๆ จะช่วยให้คุณได้ไอเดียสำหรับโครงการของคุณเอง ติดต่อเราทาง Twitter หากคุณมีคำถามหรือคำขอหัวข้อสำหรับบล็อกนี้