การเผยแพร่และการรองรับบน browser
การเผยแพร่ขึ้น npm
หัวข้อที่มีชื่อว่า “การเผยแพร่ขึ้น npm”web component ก็เป็นเพียง JavaScript module ตัวหนึ่ง เผยแพร่ด้วยวิธีเดียวกับ ES module package ทั่วไป ตัวอย่าง package.json แบบขั้นต่ำ:
{ "name": "my-counter", "version": "1.0.0", "type": "module", "main": "./dist/my-counter.js", "module": "./dist/my-counter.js", "exports": { ".": "./dist/my-counter.js" }, "files": ["dist"], "keywords": ["web-components", "custom-element"]}ผู้ใช้ติดตั้งด้วย npm install my-counter แล้ว import เพียงครั้งเดียว (การ import แบบ side-effect ก็เพียงพอที่จะลงทะเบียน tag):
import 'my-counter';// <my-counter> is now usable anywhere in the documentCustom Elements Manifest
หัวข้อที่มีชื่อว่า “Custom Elements Manifest”Custom Elements Manifest (custom-elements.json) เป็นไฟล์ JSON ที่เครื่องอ่านได้ ซึ่งทำเอกสารกำกับ custom element ทุกตัวในแพ็กเกจ ไม่ว่าจะเป็น tag name, properties, attributes, events และ CSS custom properties เครื่องมืออย่าง Storybook, IDEs และแดชบอร์ดของ design system ต่างนำไฟล์นี้ไปใช้ทำ auto-complete และเอกสารประกอบ
สร้างไฟล์นี้ได้ด้วย CLI @custom-elements-manifest/analyzer:
npm install --save-dev @custom-elements-manifest/analyzernpx cem analyze --globs "src/**/*.js"ตัวอย่างส่วนหนึ่งของผลลัพธ์ที่ได้:
{ "schemaVersion": "1.0.0", "modules": [{ "kind": "javascript-module", "path": "src/my-counter.js", "declarations": [{ "kind": "class", "name": "MyCounter", "customElement": true, "tagName": "my-counter", "attributes": [ { "name": "label", "type": { "text": "string" } } ], "members": [ { "kind": "field", "name": "count", "type": { "text": "number" } } ] }] }]}การกำหนดเวอร์ชัน
หัวข้อที่มีชื่อว่า “การกำหนดเวอร์ชัน”ปฏิบัติตาม semantic versioning การเปลี่ยนแปลงที่ถือว่าเป็น breaking changes ใน custom element ได้แก่:
- การลบหรือเปลี่ยนชื่อ attribute, property หรือ event
- การเปลี่ยน tag name ของ element
- การเปลี่ยนรูปร่างของอ็อบเจกต์
detailใน custom event
ส่วนการเปลี่ยนแปลงที่ไม่ใช่ breaking ได้แก่ การเพิ่ม attribute ที่เป็น optional ตัวใหม่ การเพิ่ม CSS custom properties ใหม่ หรือการเพิ่ม public methods ใหม่
การรองรับบน browser และ baseline
หัวข้อที่มีชื่อว่า “การรองรับบน browser และ baseline”ณ ปี 2025 Custom Elements v1, Shadow DOM v1 และ HTML Templates ได้รับการรองรับใน browser หลักทุกตัว ทั้ง Chrome, Firefox, Safari และ Edge (ทุกเวอร์ชันปัจจุบันและเวอร์ชันก่อนหน้าส่วนใหญ่) ป้าย “Baseline Widely Available” ครอบคลุมทั้งสามเสาหลักนี้
ข้อยกเว้นหนึ่งเดียว: customized built-ins (element ที่ extend built-in อย่าง HTMLButtonElement ด้วย is="...") ไม่ รองรับใน Safari ควรเลือกใช้ autonomous custom elements (extends HTMLElement) เพื่อความเข้ากันได้สูงสุด
ตัว Lit เองรองรับ Chrome 104+, Firefox 121+, Safari 16.4+ สำหรับแอปที่ใช้งานจริงซึ่งต้องรองรับ browser เก่า แพ็กเกจ @webcomponents/polyfills จะช่วยอุดช่องว่างเหล่านั้นได้
เดโมที่รันได้
หัวข้อที่มีชื่อว่า “เดโมที่รันได้”เดโมด้านล่างแสดง badge element ที่เผยแพร่ได้แบบง่าย ๆ ซึ่งสะท้อน “ความรู้สึกของแพ็กเกจที่เผยแพร่แล้ว” คือสิ่งที่ผู้ใช้จะเห็นพอดีหลังติดตั้ง component ของคุณจาก npm
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
เผยแพร่เป็น unbundled ES module พร้อมประกาศ Lit เป็น peerDependencies | Bundler ฝั่ง consumer สามารถ dedupe และ tree-shake Lit ได้เต็มที่ ลดโอกาสโหลดซ้ำ | ต้องพึ่งพาว่า consumer มี bundler ที่ resolve ESM ได้ถูกต้อง |
| Bundle/minify Lit เข้าไปในไฟล์ package ของตัวเอง | ใช้งานได้ทันทีแม้ consumer ไม่มี build step | เสี่ยงโหลด Lit runtime ซ้ำหลายชุดเมื่อหน้าเดียวมี component จากหลาย vendor ทำให้ bundle บวม |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- Bundle Lit runtime เข้าไปในทุก component ที่เผยแพร่ แทนที่จะประกาศเป็น shared dependency — ถ้าหน้าเว็บใช้ component จากหลาย vendor ผู้ใช้จะโหลด Lit ซ้ำหลายชุดโดยไม่รู้ตัว ทำให้ bundle บวมเกินจำเป็น
- เผยแพร่เฉพาะไฟล์ที่ minify/bundle แล้วเท่านั้น (ไม่มี unbundled ESM ให้เลือก) — ทำลายความสามารถ tree-shaking และ code-splitting ของ bundler ฝั่ง consumer
- ลืมระบุ browser support หรือ polyfill requirement ไว้ใน README — ผู้ใช้ที่ต้อง support browser เก่าจะไม่รู้ว่าต้องติดตั้ง
@webcomponents/polyfillsเพิ่มเอง
💡 ตัวอย่างจากของจริง
Home Assistant — เผยแพร่และดูแล custom elements จำนวนมากที่ใช้ Lit เป็น shared dependency ตัวเดียวทั่วทั้งแอป แทนที่จะ bundle Lit แยกในแต่ละ element
Google Material Web — เผยแพร่แต่ละ component เป็น unbundled ES module แยกตัว ทำให้ consumer เลือก import และ tree-shake เฉพาะส่วนที่ใช้ได้