GN⁺: VanillaJSX.com 웹사이트 출시
(vanillajsx.com)바닐라 JSX의 사례
JSX가 DOM 요소를 반환한다면?
-
ClickMe
함수는 버튼을 생성하고 클릭 횟수를 표시하는 기능을 가짐 - 버튼을 클릭할 때마다 텍스트가 업데이트됨
export default function ClickMe() {
let i = 0;
const el = <button>Click me</button> as HTMLButtonElement;
el.onclick = (e) => {
el.textContent = `Clicked ${++i} times`;
};
return el;
}
재사용 가능성
-
ClickMe
컴포넌트를 여러 번 사용하여 각기 다른 상태를 유지할 수 있음
import ClickMe from "./sample1.js";
export default () => <>
<p><ClickMe /></p>
<p><ClickMe /></p>
<p><ClickMe /></p>
</>;
상호작용 DOM 트리 생성
-
TodoInput
과TodoList
클래스를 사용하여 할 일 목록을 관리할 수 있음 - 항목을 추가하고 클릭하여 제거할 수 있음
function TodoInput(attrs: { add: (v: string) => void }) {
const input = <input /> as HTMLInputElement;
input.placeholder = 'Add todo item...';
input.onkeydown = (e) => {
if (e.key === 'Enter') {
attrs.add(input.value);
input.value = '';
}
};
return input;
}
class TodoList {
ul = <ul class='todolist' /> as HTMLUListElement;
add(v: string) {
const item = <li>{v}</li> as HTMLLIElement;
item.onclick = () => item.remove();
this.ul.append(item);
}
}
export default () => {
const list = new TodoList();
list.add('foo');
list.add('bar');
return <>
<TodoInput add={(v) => list.add(v)} />
{list.ul}
</>;
};
대량 데이터 처리
-
FindNames
함수는 대량의 데이터를 처리하고 필터링하여 결과를 표시함 - 입력 값에 따라 실시간으로 일치하는 항목을 업데이트함
import { data } from "../fetch-dataset.js";
export default function FindNames() {
const status = <p style='margin:1em 0' /> as HTMLParagraphElement;
const results = <ul /> as HTMLUListElement;
const input = <input value='eri(c|k)a?' autocomplete='new-password' oninput={updateMatches} /> as HTMLInputElement;
updateMatches();
function updateMatches() {
const matched = (data.entries().filter(([k]) => k.match(input.value)).toArray());
const matches = (Iterator.from(matched).map(match => <Item regex={input.value} match={match} />).take(30));
results.replaceChildren(...matches);
status.textContent = `${matched.length} / ${data.size}`;
}
return <div class='sample4'>
{input}
{status}
{results}
</div>;
}
function Item(attrs: { match: [string, number], regex: string }) {
const [name, count] = attrs.match;
const total = <small style='color:#fff3'>({count})</small>;
return <li>
<span innerHTML={highlight(name, attrs.regex)} /> {total}
</li>;
}
function highlight(str: string, regex: string) {
if (!regex) return str;
const r = new RegExp(`(${regex})`, 'gi');
return str.replace(r, '<span class="match">$1</span>');
}
imlib의 소개
-
imlib
는 immaculatalibrary.com을 위해 개발된 라이브러리임 - minigamemaker.com과 현재 읽고 있는 웹사이트를 구축하는 데 사용됨
- 기존의 상태가 충분하지 않아 개발되었으며, 앱을 만드는 데 가장 선호하는 방법임
GN⁺의 정리
- 이 글은 JSX를 사용하여 DOM 요소를 직접 생성하고 상호작용하는 방법을 설명함
- 기존의 가상 DOM을 사용하지 않고도 효율적으로 대량 데이터를 처리할 수 있는 방법을 제시함
-
imlib
라이브러리는 간단하고 직관적인 방식으로 앱을 개발할 수 있게 해줌 - 비슷한 기능을 가진 다른 프로젝트로는 React, Vue.js 등이 있음
Hacker News 의견
-
프로젝트에 관심을 가져줘서 고마움
- 지난 10년간 SSGs 상태에 불만을 느껴 프로젝트를 시작함
- 주로 정적 웹사이트를 만들며, 간단하고 직관적인 것을 원했음
- JSX가 적합해 보였지만 React 같은 JSX 프레임워크의 복잡성에 지침
- JSX를 문자열로 렌더링하는 SSG를 만들었고, 이를 브라우저에서 DOM 요소로 렌더링하도록 확장함
- 일부 레이아웃에서는 공유 컴포넌트로 잘 작동함
- SEO에도 잘 작동함
- IDE 지원이 완벽하지 않음
-
실제 DOM 노드를 반환하면 JSX의 큰 장점이 사라짐
- DOM의 설명을 반환해야 새로운 상태로 템플릿을 재평가하고 효율적으로 업데이트할 수 있음
- 예제는 명령형 DOM API를 사용하여 업데이트함
- VDOM의 주요 이점은 템플릿에서 항목을 반복하는 것임
- VDOM의 문제는 느린 디핑(diffing)임
-
JSX의 기원은 Facebook의 XHP에서 비롯됨
- XHP는 E4X에서 영감을 받음
-
최종 예제가 Firefox에서 작동하지 않음
- Edge에서는 작동하지만 Firefox에서는 오류 발생
-
Vanilla TSX와 매우 유사함
- Vanilla TSX로 작성된 앱 예제 제공
-
Action Script 3을 떠올리게 함
- XML이 언어의 핵심이었고, 재미있었지만 ES4가 되지 못함
- Typescript와 JSX로 비슷한 수준에 도달하는 데 10년 이상 걸림
-
예제들은 시간이 지나면서 변경될 수 있는 props를 가진 컴포넌트를 보여주지 않음
- 더 복잡한 앱으로 확장하는 데 어려움이 있을 것 같음
-
나도 실제 DOM 노드를 생성하는 jsx 템플릿 표현식을 기반으로 한 UI 라이브러리를 만듦
- 모델 객체를 속성에 바인딩하여 명령형 이벤트 핸들러 보일러플레이트를 제거함
- 좋은 아이디어라고 생각함
-
JSX의 매력을 이해하지 못함
- 루프, 변수 삽입 등을 자동으로 제공하는 다른 방법이 더 쉬움
-
Imba를 추천함
- JS 개발자들이 Faang 마케팅에 쉽게 넘어가서 인기가 없는 것 같음