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

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

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

บทนำ

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

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

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

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

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

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

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

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

คอลเล็กชัน

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

ตัวอย่างเช่น หน้าเว็บง่ายๆ ที่มีโพสต์ทั้งหมดของ Addy

ข้อจำกัด

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

เทมเพลต

web.dev ใช้ระบบเทมเพลต Nunjucks ที่ Mozilla เป็นผู้พัฒนาขึ้น Nunjucks มีฟีเจอร์เทมเพลตทั่วไป เช่น ลูปและเงื่อนไข และยังให้เรากำหนดคำสั่งสั้นที่สร้าง 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 ยังใช้โค้ดย่อเป็นภาษาเมตาโปรแกรมประเภทหนึ่งด้วย รหัสย่อยอมรับอาร์กิวเมนต์ โดยอาร์กิวเมนต์หนึ่งคือเนื้อหาที่รวมอยู่ ไม่จำเป็นต้องให้ Shortcode แสดงผลใดๆ จึงสามารถใช้ Shortcode เพื่อสร้างสถานะหรือทริกเกอร์ลักษณะการทำงานอื่นๆ ได้ 🤔💭

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

มาแชทกัน

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

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