DEV Community

Cover image for  CustomElement ใน Svelte3 ง่ายๆ แค่ปลายนิ้ว
thinny
thinny

Posted on

CustomElement ใน Svelte3 ง่ายๆ แค่ปลายนิ้ว

Web components คืออะไร

web component คือชุดของ API แพลตฟอร์มเว็บที่ช่วยให้คุณสร้างแท็ก HTML ที่กำหนดเองใช้ซ้ำได้และห่อหุ้มเพื่อใช้ในเว็บเพจและเว็บแอป คอมโพเนนต์และวิดเจ็ตแบบกำหนดเองขึ้นอยู่กับมาตรฐานส่วนประกอบของเว็บทำงานบนเบราว์เซอร์ที่ทันสมัยและสามารถใช้กับ Library JavaScript ที่เข้ากันได้กับ HTML

ส่วนประกอบของ web component จะประกอบไปด้วย 4 ประการ หลักๆ

  • custom Elements specification
  • shadow DOM specification
  • HTML Template specification
  • ES Module specification

web component meta-specification ศึกษาข้อมูลเพิ่มเติมได้ที่

custom HTML tags

class AutonomousButton extends HTMLElement {
  ...
}
customElements.define("autonomous-button", AutonomousButton);
Enter fullscreen mode Exit fullscreen mode

การเรียกใช้งาน

<autonomous-button>Click Me :)</autonomous-button>
Enter fullscreen mode Exit fullscreen mode

เราสามารถ extends HTMLElements อื่นๆได้ เช่น HTMLButtonElement

class CustomizedButton extends HTMLButtonElement {
  ...
}
customElements.define("customized-button", CustomizedButton, { extends: "button" });
Enter fullscreen mode Exit fullscreen mode

การเรียกใช้งาน

<button is="customized-button">Click Me :)</button>
Enter fullscreen mode Exit fullscreen mode

Shadow DOM

Shadow DOM เป็นการกำหนดวิธีใช้สไตล์ที่ห่อหุ้มและมาร์กอัปในส่วนประกอบของเว็บ ความสามารถในการซ่อนโครงสร้างมาร์กอัปสไตล์และพฤติกรรมและแยกออกจากโค้ดอื่น ๆ บนเพจเพื่อไม่ให้ส่วนต่างๆขัดแย้งกัน เช่นว่า ถ้าชื่อ styles ภายในและภายนอก เป็นชื่อเดียวกัน ถ้าอยู่ภายใต้ Shadow DOM จะมองเป็นคนละชื่อ และภายใน Shadow DOM จะไม่มี side effect ไปหาภายนอกเช่นกัน

<!--- HTML element --->
<div class="element"></div>
Enter fullscreen mode Exit fullscreen mode
/** attachted shadow DOM */
const header = document.createElement('element');
const shadowRoot = header.attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<h1>Hello Shadow DOM</h1>';
Enter fullscreen mode Exit fullscreen mode

ใช้ const shadowRoot = header.attachShadow({mode: 'open'}); เพื่อ attachShadow เข้าไปใน element

<div class="element">
   #shadow-root (open)
   <h1>Hello Shadow DOM</h1>
</div>
Enter fullscreen mode Exit fullscreen mode

ES Module

ESM ย่อมาจาก ES Modules เป็นข้อเสนอของ Javascript ในการใช้ระบบโมดูลมาตรฐาน ซึ่งในอนาคต Library ของ Javascript ต้องปรับให้เข้ากับมาตรฐาน ESM ทั้งหมด วิธีสังเกตุการใช้งานจะมี type="module" ใน tag script
หรือสามารถ import ด้วย นามสกุล .mjs หรือเราสามารถกหนด ใน package.json โดยระบุ type="module" ก็ได้

/** import syntax */
import "https://example.com/module.mjs";
Enter fullscreen mode Exit fullscreen mode
/** package.json */
{
  ...
  "type": "module"
}
Enter fullscreen mode Exit fullscreen mode
<!-- import module script -->
<script type="module" src="modules/module.js"></script>

<script type="module">
  import {awesomeExplosion} from '@awesome-things/awesome-explosion';
</script>
Enter fullscreen mode Exit fullscreen mode

ทีมา integration-with-the-javascript-module-system

เราพอรู้จัก webcomponent กันแล้วใช่ไหมครับ คราวนี้เรามาดูกันว่า ด้วยความเรียบง่ายของ svelte ที่เขียน code ได้สั้นและกระชับ จะเอามาสร้าง webcomponent ได้อย่างไร รับรองว่าแค่กระดิกนิ้ว ก็เสร็จได้โดยง่าย

การทำ CustomElement ใน Svelte

Alt Text

สมมุติเราสร้าง structure ตามภาพนะครับ

📦src
┣ 📂web_components
┃ ┣ 📂Button
┃ ┃ ┣ 📜Button.svelte
┃ ┃ ┗ 📜index.js
┣ 📜App.svelte
┣ 📜main.js
┗ 📜styles.svelte

โค้ดใน component เราจะประมาณนี้

/** Button.svelte */
<svelte:options tag="sv-button" />

<script>
  import { onMount } from "svelte";
  onMount(() => {
    console.log("button web component mounted");
  });
  const alertClick = () => {
    alert("alert Button");
  };
</script>

<button on:click={alertClick}>Button</button>

Enter fullscreen mode Exit fullscreen mode

ตัวที่บอกว่า component เราคือ web_component
<svelte:options tag="sv-button" /> ชื่อที่เป็น customElement เราคือ sv-button คำสั่ง svelte:options เป็นคำสั่งคอยบอก compiler ของ svelte ว่า tag="sv-button" ทำให้เป็น customElement ให้หน่อย

ที่มา svelte-options

ยังไม่จบแค่นี้ เรายังต้องมา config rollup.config.js อีกเล็กน้อย
Alt Text

/** rollup.config.js */

import svelte from "rollup-plugin-svelte";
import path from "path";
let basePath = path.join(__dirname, "./src/web_components");

export default {
       input: `${basePath}/Button/Button.svelte`,
       output: {
     format: "es",
     dir: "public/build",
       },
       ...
       plugins:[
          svelte({
        compilerOptions: {
        customElement: true
            }
      }),
       ]
}
Enter fullscreen mode Exit fullscreen mode

จากภาพด้านบนเราจะเห็นว่า เรามีการ รับ input input: ${basePath}/Button/Button.svelte แล้วมีการกำหนด output เป็น ESM format ซึ่งทำให้ไฟล์ webcomponent ของเราเป็นไปมาตรฐานของ. web component spec กำหนดปลายทางไปที่ dir: "public/build"

จากนั้นเราลอง build ดูจะได้โครงสร้างประมาณนี้ ตัวที่บอกให้ build component ธรรมดาเป็น web component คือ customElement: true แต่ว่าต้องไปกำหนด svelte:options ด้วยนะ ใน component ที่เราต้องการ

Alt Text
จะเห็นว่าโครงสร้างมันอยู่ในระดับเดียวกันหมด ถ้ามา component หลายตัวคงวุ่นวายน่าดู งั้นเรามาจะระเบียบโครงสร้างหลัง Build กันใหม่

import multiInput from "rollup-plugin-multi-input";

export default {
   ...
   plugins: [
      ...,
      multiInput({
    relative: "src/",
    transformOutputPath: (output, input) => {
       return output;
        },
      }),
  ],
}
Enter fullscreen mode Exit fullscreen mode

เมื่อเพิ่ม plugin นี้เข้าไปมันจะ build โครงสร้างให้เป็นไปตาม src ที่เราได้ทำเอาไว้ มาลอง build กันดูอีกรอบ
Alt Text

พอเรามาแกะโครงสร้าง web component ที่ผ่านการ build มาแล้ว
Alt Text
จะเห็นมีการ ทำ customElement ตาม spec ของ web component
แถมยังมีการ export component ออกมาตาม ESM syntax ด้วย ถ้ายังนั้นก็หมายความเราสามารถเอาไป import ให้ใช้งานได้ เพราะ modern browser รู้จัก syntax แบบนี้อยู่แล้ว

Alt Text
เวลาใช้ก็ import web component ที่เราได้ build ไว้นะครับ
<script type="module" defer src='/build/web_components/Button/Button.js'></script>
ที่สำคัญอย่าลืม type="module" นะครับ เดี่ยวมันจะด่าเรา
ส่วนตอนจะเรียกใช้ก้แค่ ใส่ชื่อ cutomElement เขาไปได้เลยครับ

<sv-button></sv-button>
Enter fullscreen mode Exit fullscreen mode

พอได้ตามที่ต้องการแล้ว ถึงเวลารัน yarn start/ npm run start
Alt Text

จากนั้น ลองกดไปที่ปุ่ม 1 ครั้งครับมีการ alert เป็นไปตามที่เราได้เขียนไว้เลยครับ

const alertClick = () => {
    alert("alert Button");
};

Enter fullscreen mode Exit fullscreen mode

Alt Text

เพียงเท่านี้เราก้ได้ webcomponent ที่เขียนจาก svelte มาใช้แล้วครับ
Alt Text

จะเห็นว่า การสร้าง component ธรรมดา จนกลายมาเป็น web component ที่พร้อมใช้งาน ผ่านการ config น้อยมาก ง่ายมากด้วย นี่ยังไม่ได้พูดถึงการ build webcomponent แบบหลายไฟล์รวมกัน ซึ่ง javascript framework ตัวอื่นทำได้ยากมากกว่าจะได้ web component มาใช้งานอันนึง บางทีอาจจะต้องเอา component มา wrap อีก นั่นเป็นเพราะว่าด้วยข้อจำกัดของ javascript ด้วย
svelte จึงเป็นทางเลือกอีกทางหนึ่ง ที่เหมาะสำหรับนักพัฒนาที่จะเอามาทำเป็น webcomponent แจกจ่าย หรือใช้งานภายในองค์กร เพราะเขียนโค้ดน้อยมาก config ก็ไม่ยากเลย

ขอบคุณที่ท่านที่อ่านมาจนจบ ฝากกด Subscribe กด Share link ด้วยนะครับ

สำหรับใครที่อ่านแล้วยังไม่เข้าใจ แล้วอยากเรียนรู้ svelte. ตั้งแต่เริ่ม แบบ step by step สามารถศึกษาเพิ่มเติมได้ที่

Svelte: Framework Not Framework — (ตอนที่ 1) แรกรู้จัก

Top comments (0)