← Kirjoitukset

Yhden tiedoston Preact-komponentit

Yhden tiedoston Preact-komponenttien yksinkertaisuus ja miten ne tekevät kehityksestä suoraviivaisempaa.

Yksi asia, josta olen aina pitänyt Vue:ssa, on sen Single-File Component (SFC) -lähestymistapa. Yhdessä .vue-tiedostossa logiikka, templaatti ja tyylit asuvat rinnakkain. Kaikki, mikä kuuluu komponenttiin, on samassa paikassa — komponentteja on helppo ymmärtää, refaktoroida ja siirtää.

Halusin saman tunteen Preactilla työskennellessäni.

Preact ei määrittele valmiiksi Vue-tyylistä yhden tiedoston formaattia, mutta se on tarpeeksi joustava omiin käytäntöihin. Tämä artikkeli kuvaa omaa tapaani rakentaa yhden tiedoston Preact-komponentteja Vue SFC:istä inspiroituneena — ilman build-vaihetta, kääntäjiä tai framework-tason abstraktioita.

Tavoite

  • Pidä logiikka, markup ja tyylit yhdessä tiedostossa
  • Vältä monimutkaista työkaluketjua tai build-vaihetta
  • Pysy idiomaattisessa Preactissa
  • Tee komponenteista helppolukuisia ja siirrettäviä

Ydinajatus

Yhden tiedoston Preact-komponentti sisältää tavallisen Preact-funktiokomponentin, sen markupin ja tyylit vierekkäin.

Ainoa custom-apu on hyvin pieni css-template-tag helper. Sen enempää magiaa ei tarvita.

Minimaalinen esimerkki

// ExampleComponent.ts
import { html } from "htm/preact"
import { useState } from "preact/hooks"
import { css } from "/utils/markup"

export function MyComponent() {
  const [count, setCount] = useState(0)

  const view = html`
    <div data-scope="MyComponent">
      <h1>Hello World</h1>
      <p>Count: ${count}</p>
      <button onClick=${() => setCount((c) => c + 1)}>
        Increment
      </button>
    </div>
  `

  const style = css`
    @scope ([data-scope="MyComponent"]) to ([data-scope]) {
      h1 {
        color: var( --primary-600);
      }
    }
  `

  return [view, style]
}

css-apuri

css-apuri on tarkoituksella yksinkertainen. Se on template tag, joka palauttaa <style>-elementin raakaa CSS:ää sisältäen.

// /utils/css.ts
import { h, type JSX } from "preact"

export function css(
  strings: TemplateStringsArray,
  ...values: Array<string | number | null | undefined>): JSX.Element {
  let content = ""

  for (let i = 0; i < strings.length; i++) {
    content += strings[i]
    if (i < values.length && values[i] != null) {
      content += values[i]
    }
  }

  return h("style", {
    dangerouslySetInnerHTML: { __html: content.trim() }
  })
}

Ei runtimea, ei hashauksia eikä muunnosvaihetta. Mitä kirjoitat, se päätyy DOM:iin.

Miksi pidän tästä

  • Kolokaatio — logiikka, markup ja tyylit samassa paikassa
  • Yksinkertaisuus — ei custom build-putkia tai kääntäjiä
  • Ennustettavuus — tavallisia Preact-komponentteja
  • Helppo refaktorointi — siirrä tai poista komponentti yhtenä tiedostona

Tuntuma on lähellä Vue SFC -filosofiaa, mutta toteutus on kokonaan käyttäjätason käytäntöä.

Lopuksi

Preact ei pakota tiettyyn komponenttimuotoon — ja se on vahvuus. Pienellä apurilla ja modernilla CSS:llä saat Vue SFC:ien parhaat puolet Preact-ekosysteemissä.