"๐™Ž๐™ขเธก๐™ก๐™ก๐™š๐™จ๐™ฉ๐™š๐™™๐™ž๐™ฃ๐™œ": ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ 29% ๋” ์ž‘๊ฒŒ ๋งŒ๋“ค๊ธฐ

15009 ๋‹จ์–ด webdevshowdevwebcomponentsjavascript
WebComponents.Dev ์‚ฌ์ดํŠธ ๋ธ”๋กœ๊ทธ51 ways/languages to make a <my-counter> Web Component

๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋Š” File Size Ranking์—์„œ 1์œ„๋ฅผ ์ฐจ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.



ํ•˜์ง€๋งŒ... ์ €๋Š” Svelte ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ตœ์ ํ™”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Svelte์™€์˜ ๋น„๊ต์— ์ „์ ์œผ๋กœ ๋ฐ˜๋Œ€ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ "์ปดํŒŒ์ผ๋Ÿฌ ์žฌ์ƒ"

๋„ค์ดํ‹ฐ๋ธŒ HTMLElement ์ฝ”๋“œ๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
(๋‹ค๋ฅธ ๋ชจ๋“  ์†Œ์Šค ๋ฒ„์ „๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž„)



gzip


WebComponents DEV์˜ ์›๋ณธ
476B*

๋‚ ์”ฌํ•œ
1884๋…„

๋ฆฌํŒฉํ† ๋ง
355B - ์ ˆ๊ฐ์•ก: 25%

์ตœ์ ํ™”
339 B - ์ ˆ๊ฐ์•ก: 29%



*) Web Components DEV ์‚ฌ์ดํŠธ์—์„œ๋Š” ํŒŒ์ผ์ด 505๋ฐ”์ดํŠธ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
GitHub.io์— ๋ณต์‚ฌํ•œ ๋‚ด ๋ณด๊ณ ์„œ๋Š” 476๋ฐ”์ดํŠธ์ž…๋‹ˆ๋‹ค.

์›๋ณธ <my-counter> = 476๋ฐ”์ดํŠธ:





๋ฆฌํŒฉํ„ฐ๋ง ์ฝ”๋“œ



JSFiddle ์œ„์˜ ํƒญJavaScript์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.
  • ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด์€ ํ›Œ๋ฅญํ•˜์ง€๋งŒ ๋ฌด์˜๋ฏธํ•œ ๊ณต๋ฐฑ๊ณผ \n ์ค„๋ฐ”๊ฟˆ์ด ์—ฌ์ „ํžˆ ์ถ•์†Œ๋œ ํŒŒ์ผ์— ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋ฐ”์ดํŠธ๋ฅผ ๋นจ์•„๋“ค์ž…๋‹ˆ๋‹ค.
  • innerHTML์„ ํ•œ ๋ฒˆ๋งŒ ์›ํ•  ๋•Œ createElement('template')๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
  • .
  • connectedCallback์— ํ…œํ”Œ๋ฆฟ/์ปจํ…์ธ ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค(์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Œ)
  • .
  • super() ์ด ๋ฒ”์œ„
  • ๋ฅผ ์„ค์ •ํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • attachShadow() ์„ค์ • ๋ฐ ๋ฐ˜ํ™˜ this.shadowRoot

  • ๋ชจ๋“  ๊ฒƒ์„ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        constructor() {
            super()
                .attachShadow({ mode: 'open' })
                .innerHTML = "<style>*{font-size:200%}...
    


  • ํ•œ ๋ฒˆ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ MyCounter ํด๋ž˜์Šค ์ •์˜๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

        customElements.define('my-counter', class extends HTMLElement {}
    


  • ๊ฑฐ์˜ ๋ชจ๋“  51๊ฐœ์˜ ์˜ˆ์ œ๋Š” ์ธ๋ผ์ธ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ(ํ‘œ๊ธฐ๋ฒ•)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

        render() {
            return html`
            <button @click="${this.dec}">-</button>
            <span>${this.count}</span>
            <button @click="${this.inc}">+</button>
            `;
        }
    


  • ๊ทธ๋Ÿผ ์šฐ๋ฆฌ๋„ ํ•  ์ˆ˜ ์žˆ์–ด
  • ์š”์†Œ์—์„œ inc() ๋ฐ dec() ๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํ›„๋“œ์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ˆ˜ํ–‰ํ•จ)
  • ๋ฒ„ํŠผ์˜ id ์ฐธ์กฐ๊ฐ€ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  •     <button onclick="this.getRootNode().host.inc()">
        <button onclick="this.getRootNode().host.dec()">
    


  • ๊ตฌ์„ฑ ์š”์†Œ๋Š” shadowRoot๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํƒ€์ผ๊ณผ ๋‚ด์šฉ์„ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค. ShadowDOM
  • ์— ์กด์žฌํ•˜๋Š” ์œ ์ผํ•œid์„ ๋Œ€์ƒ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ <span id="count">์˜ <span>๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


  • ๋ชจ๋“  ๋ฆฌํŒฉํ„ฐ๋งconnectedCallback์€ ๋ฒ”์œ„ innerHTML์„ 0์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

        connectedCallback() {
            this.update(this.count);
        }
    

    HTML์—์„œ ๊ธฐ๋ณธ๊ฐ’ 0์„ ์„ค์ •ํ•˜๋ฉด connectedCallback์ด ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

        "<span>0</span>"+
    


  • ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•˜๊ณ  ; CSS์—์„œ


  • ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ถ”๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— HTML ์†์„ฑ์—์„œ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋”ฐ์˜ดํ‘œ๋ฅผ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค.

        <button onclick=this.getRootNode().host.inc()>
        <button onclick=this.getRootNode().host.dec()>
    




  • ๋ฆฌํŒฉํ„ฐ๋ง๋œ ์ฝ”๋“œ = 355๋ฐ”์ดํŠธ:



    customElements.define("my-counter", class extends HTMLElement {
        constructor() {
          super()
            .attachShadow({ mode: "open" })
            .innerHTML =
            "<style>" +
            "*{font-size:200%}"+
            "span{width:4rem;display:inline-block;text-align:center}" +
            "button{width:4rem;height:4rem;border:none;border-radius:10px;background-color:seagreen;color:white}" +
            "</style>" +
            "<button onclick=this.getRootNode().host.dec()>-</button>" +
            "<span>0</span>" +
            "<button onclick=this.getRootNode().host.inc()>+</button>";
          this.count = 0;
        }
        inc() {
          this.update(++this.count);
        }
        dec() {
          this.update(--this.count);
        }
        update(count) {
          this.shadowRoot.querySelector("span").innerHTML = count;
        }
      }
    );
    





    ์ตœ์ ํ™”๋œ ์ฝ”๋“œ = 339๋ฐ”์ดํŠธ:



    ์ด ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋” ์ข‹๊ณ  ๋” ์ž‘๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • inc , dec ๋ฐ update ๋ฉ”์„œ๋“œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • DRY(Don't Repeated Yourself)๋Š” ์ฝ”๋“œ ์œ ์ง€ ๊ด€๋ฆฌ ๊ด€์ ์—์„œ ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ „๋‹ฌ ๋ฐ ์„ฑ๋Šฅ PoV์—์„œ DRY๊ฐ€ ๋˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. GZip์€ ๋ฐ˜๋ณต์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹คcount๋Š” 2๊ฐœ์˜ ์š”์†Œ(๋ฒ„ํŠผ ๋ฐ ์ŠคํŒฌ)์—๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
    ๋‘ ์š”์†Œ ๋ชจ๋‘์— * {font-size:200%}๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋” ํฐ ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜์ง€๋งŒ GZipped ํŒŒ์ผ์€ ๋” ์ž‘์•„์ง‘๋‹ˆ๋‹ค!
    (๊ทธ๋ฆฌ๊ณ  CSS ํŒŒ์„œ๋Š” ํ•  ์ผ์ด ์ ์Šต๋‹ˆ๋‹ค.)
  • font-size:200%๋Š” .count-- > ์ •์˜๋ฅผ ๋‹ซ๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ ๊ณต๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ตœ์†Œํ™”๊ธฐ๊ฐ€ onclick ์ด์Šค์ผ€์ดํ”„ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ 4๋ฐ”์ดํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • -๋Š” <span>
  • ๋กœ ๋Œ€์ฒด ๊ฐ€๋Šฅ
  • <p>๊ฐ€ ์ƒํƒœ
  • ์ด๋ฏ€๋กœ this.count = 0;๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • <p>0</p> ๋ฐ seagreen๋ฅผ ๋” ์งง์€ white ํ‘œ๊ธฐ๋ฒ•์œผ๋กœ ๋ฐ”๊พธ๋ฉด ์ด ๊ฒฝ์šฐ ์ถ”๊ฐ€ ๋ฐ”์ดํŠธ๊ฐ€ ์ ˆ์•ฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์— #์ด ์•„์ง ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ถ”๊ฐ€ GZip ์ธ์ฝ”๋”ฉ ๋น„ํŠธ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

  • customElements.define(
      "my-counter",
      class extends HTMLElement {
        constructor() {
          super().attachShadow({
            mode: "open",
          }).innerHTML =
            "<style>" +
            "p{font-size:200%;width:4rem;display:inline-block;text-align:center}" +
            "button{font-size:200%;width:4rem;height:4rem;border:none;border-radius:10px;background:seagreen;color:white}" +
            "</style>" +
            "<button onclick=this.getRootNode().host.count-- >-</button>" +
            "<p>0</p>" +
            "<button onclick=this.getRootNode().host.count++>+</button>";
        }
        set count(p) {
          this.shadowRoot.querySelector("p").innerHTML = p;
        }
        get count() {
          return ~~this.shadowRoot.querySelector("p").innerHTML;
        }
      }
    );
    



    ์ฐธ๊ณ : ์ธ๋ผ์ธ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋ฉด 6๋ฐ”์ดํŠธ๋ฅผ ๋” ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ๊ทธ๋Ÿฌ๋‚˜ ์ฝ”๋“œ ์œ ์ง€ ๋ณด์ˆ˜์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์–ด๋ ค์›€์„ ๊ฒช์Šต๋‹ˆ๋‹ค.

    .innerHTML = 
    "<button style=font-size:200%;width:4rem;height:4rem;border:none;border-radius:10px;background:seagreen;color:white onclick=this.getRootNode().host.count-- >-</button>" +
    "<p style=font-size:200%;width:4rem;display:inline-block;text-align:center>0</p>" +
    "<button style=font-size:200%;width:4rem;height:4rem;border:none;border-radius:10px;background:seagreen;color:white onclick=this.getRootNode().host.count++>+</button>"
    



    ์ตœ์†Œํ˜• ๊ฒฐ๋ก 



    ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•˜๋ฉด ๋” ์ž‘๊ณ  ๋” ์ข‹์•„์ง‘๋‹ˆ๋‹ค.



    gzip


    original by WebComponents.DEV
    476B*

    ๋‚ ์”ฌํ•œ
    1884๋…„

    ๋ฆฌํŒฉํ† ๋ง
    355B - ์ ˆ๊ฐ์•ก: 25%

    ์ตœ์ ํ™”
    339 B - ์ ˆ๊ฐ์•ก: 29%

    ์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ