Na obsah stránky

Jednoduše a rychle: LinkeDOM

Aleš Roubíček | | # permalink

Pokud chcete v Node.js pracovat s HTML dokumenty, máte v podstatě dvě možnosti jak to mainstreamově udělat – cheerio a JSDOM. Cheerio je klon jQuery pro Node.js, který najdete třeba jako základ scraperů na platformě Apify. JSDOM je těžkotonážní framework, který se snaží simulovat browser v kontextu Node.js. Většinou se používá pro testování frontentových komponent bez nutnosti spouštět celý browser. Sic.

Obě možnosti považuju za nedobré. Ať už kvůli paměťové náročnosti a obecné neefektivnosti, která se vzahuje na obě jmenovaná řešení, tak nestandartní API, jaké představuje cheerio. Máme nějaké lepší možnosti?

LinkeDOM

Ano. Máme. Je jím knihovna LinkeDOM, která si od začátku klade za cíl být efektivní (jak na paměť, tak cykly procesoru) a mít API velmi blízké DOM standardu. Dosahuje toho díky chytré volbě vhodných datových struktur pro reprezentaci stromové povahy DOMu – triple-linked lists – a nelpění na plné implementaci DOM standardu.

Obecně se dá říct, že většina výkonových problémů dnešních webových aplikací lěží v doméně reprezentace stavu pomocí nevhodných datových struktur a přístupu k nim. Zdravíme všechny poor-man immutability knihovny pro menežování stavu nejen Reactích aplikací. 👋🖕🏼

Ale zpátky k LinkeDOMu. Jak už jsem naznačil jde o knihovnu, která primárně cílí na Node.js. Exportuje však i ESM moduly, které nejsou závislé na internals Node.js a jsou tak použitelné i v kontextu Web Workerů v Browseruv Cloudflare nebo v běhovém prostředí Deno.

Na co se hodí?

Jedním z cílů LinkeDOM je rychlý SSR, ale dá se použít i pro efektivní testování komponent nebo web scraping ve vysokém scale s rozumnými náklady.

Jak ho tedy použít?

Použití je celkem přímočaré – importujeme ES modul linkedom a z něj použijeme funkci parseHTML:

import { parseHTML } from "https://esm.sh/linkedom";

Dále funkci parseHTML předáme vstupní HTML dokument:

const { document, customElements, HTMLElement } = parseHTML(`<!DOCTYPE html>
  <html lang="en">
    <head>
      <title>Hello from Deno</title>
    </head>
    <body>
      <h1>Hello from Deno</h1>
      <form>
        <input name="user">
        <button>
          Submit
        </button>
      </form>
    </body>
  </html>
`);

To nám vrátí „sandbox“ globálního kontextu (aka window), kde najdete podporované části DOM standardu. Super je, že můžete sdílet kód pro práci s DOMem mezi serverem i klientem. Kód, který si můžete odladit v DevTools browseru, bez problémů přenesete na server. Co LinkeDOM nepodporuje, jsou dynamické vlastnosti:

const input = document.querySelector("input[name=user]");
console.log(input.name);

Tohle vám v browseru vypíše "user", ale v LinkeDOM je to undefined. V tomto případě musíte použít metodu getAttribute:

const input = document.querySelector("input[name=user]");
console.log(input.getAttribute("name"));

Vzhledem k tomu, že všechny atributy stejně nejsou dynamické ani v browseru, je lepší jít ukecěnajší cestou tak jako tak. Už kvůli konzistenci.

Osobně ve svých scriptech a actorech už nepoužívám nic jinýho. Existující actory Hlídače shopů postupně na LinkeDOM překlápíme při nutné údržbě, kvůli změnám sledovaných webů. Kód je pak pro nás přehlednější při údržbě a efektivnější v provozu. A to se vyplatí!

Našli jste v článku chybu? Máte námět na reportáž? Založte mi ticket.