웹 구성 요소를 사용하지 않는 이유

27033 단어 htmlwebcomponents
dev.to에 올린 첫 번째 게시물에 대해 나는 괜찮고 안전하며 논쟁이 없는 주제인 웹 구성 요소를 써야 한다고 생각한다.
내가 이 글을 쓰는 것은 주로 미래의 나를 위해서이다. 그래서 다음에 어떤 사람이 나에게 왜 웹 구성 요소 의심론자인지, 왜 Svelte 기본적으로 사용자 정의 요소로 컴파일할 수 없는지 물었을 때 나는 지적해야 할 것이 있다.(이것은 CEs로 번역할 수 있고 CEs를 소비할 수 있다. 이것은 Custom Elements Everywhere의 만점에서 증명할 수 있다.)
이 모든 것은 웹 구성 요소에서 하는 힘든 일에 대한 비판으로 간주되어서는 안 된다.내가 이 문장에서 약간의 잘못을 저질렀을지도 모르지만, 이런 상황에서 나는 정정을 환영한다.
나도 네가 웹 구성 요소를 사용해서는 안 된다고 말한 것은 아니다.그들은 확실히 효과적인 용례가 있다.나는 단지 내가 왜 이렇게 하지 않는지 설명할 뿐이다.

1. 점진적 개선


이것은 갈수록 지나친 관점일 수도 있지만, 나는 사이트가 가능한 한 자바스크립트를 사용하지 않아야 한다고 생각한다.웹 구성 요소가 없습니다.
이것은 본질적으로 상호작용하는 것에 있어서 매우 좋다. 예를 들어 사용자 정의 폼 요소(<cool-datepicker>를 사용하지만 네비게이션 표시줄에 있어서는 좋지 않다.또는 URL을 구축하는 모든 논리를 봉인하는 간단한 <twitter-share> 요소를 고려한다.다음과 같이 서버에 표시되는 HTML을 생성할 수 있습니다 build it in Svelte.
<a target="_blank" noreferrer href="..." class="svelte-1jnfxx">
  Tweet this
</a>
다시 말하면 bog 표준<a> 요소는 접근할 수 있는 모든 영광을 가진다.
JavaScript가 활성화되면 새 탭이 아닌 작은 팝업 창이 열립니다.그러나 없다면, 그것은 여전히 정상적으로 일할 수 있다.
그에 비해 웹 구성 요소 HTML은 이렇게 보인다...
<twitter-share text="..." url="..." via="..."/>
...만약 JS가 비활성화되거나 어떤 방식으로 손상되거나 사용자가 사용한 브라우저가 오래된 브라우저라면 이것은 쓸모가 없고 접근할 수 없습니다.class="svelte-1jnfxx" 섀도우 없는 DOM 패키징 스타일을 지원합니다.이것이 바로 나의 다음 점을 끌어냈다.

2. CSS 입력, 오류...JS 회사


스타일 패키지에 섀도우 DOM을 사용하려면 <style> 요소에 CSS를 포함해야 합니다.사용자 정의 요소를 정의하는 JavaScript 모듈에서 문자열 형식의 CSS를 사용할 수 있는 유일한 방법은 FOUC를 피하려는 경우입니다.
"JavaScript를 줄이십시오."라고 요약할 수 있는 성능 제안과 배치됩니다.특히 JS 커뮤니티의 CSS는 CSS를 .css 파일에 넣지 않아 비판을 받았지만 이제는 우리가 왔다.
앞으로 우리는 CSS ModulesConstructable Stylesheets를 사용하여 이 문제를 해결할 것이다.우리는 음영 DOM 내부의 스타일을 설계하기 위해 ::theme::part 을 사용할 수 있습니다.하지만 이것도 문제가 없는 것은 아니다.

3. 플랫폼 피로



리치 해리스
@rich_harris

비록 이것은 나를 매우 화나게 한다. 우리는 여러 해 동안 이 기능이 미래의 추세라고 허풍을 떨었지만,'지금'을 따라잡기 위해서는 플랫폼에 이 모든 새로운 기능을 가득 채우고 기존 브라우저 주위의 호성하를 깊이 있게 해야 한다
17:2019년 6월 19일 오후 55시
0
삼.
본고를 작성할 때 Chromiumbug trackerhttps://crbug.com에 61000개의 미결 문제가 있었는데 이것은 현대 웹 브라우저 구축의 커다란 복잡성을 반영했다.
매번 우리가 플랫폼에 새로운 기능을 추가할 때마다 우리는 복잡성을 증가시킨다. 버그를 위한 새로운 표면 구역을 만들고 크롬의 새로운 경쟁 상대가 나타날 가능성이 점점 낮아진다.
이것 또한 개발자들에게 복잡성을 가져왔다. 그들은 이러한 새로운 특성을 배우도록 격려받았다. (그중 일부, 예를 들어 HTML 가져오기나 원시 사용자 정의 요소 규범은 구글 밖에서 영원히 유행하지 않고 결국 다시 삭제된다)

4.Polyfills


모든 브라우저를 지원하려면 다각형으로 채워야 합니다. 아무런 도움도 되지 않습니다.Constructable Stylesheets에 실린 문헌은 구글(헤이, 제이슨!)이 쓴 것으로 도움이 되지 않는다.그것들이 크롬만의 기능이라는 것은 언급하지 않았다. (편집: 내가 하나 pull request 를 연 후에 이것은 이미 복구되었다.)three spec editors 모두 구글의 것이다.Webkitseem to have some doubts의 디자인에 관한 몇 가지 측면.

5. 구성


구성 요소는 시간 간격의 내용을 언제 나타낼지 여부를 제어하는 데 매우 유용하다.네트워킹이 표시되는 경우 <html-include> element 을 사용하여 문서를 표시하려는 경우:
<p>Toggle the section for more info:</p>
<toggled-section>
  <html-include src="./more-info.html"/>
</toggled-section>
서프라이즈이 부분을 열지 않았어도 브라우저가 요청한 이미지 more-info.html 와 연결된 다른 자원이 있습니다.
사용자 정의 요소에 틈새 내용이 급하게 나타나기 때문이다.대부분의 경우 시간 간격 내용이 렌더링을 지연시키기를 원합니다.웹 표준과 일치하기 위해 Svelte v2는 eager 모델을 사용했는데 그 결과 이것은 주요한 좌절의 원천이다. 예를 들어 우리는 같은 효과의React 공유기를 만들 수 없다.Svelte v3에서 사용자 정의 요소 조합 모델을 포기하고 다시 돌아오지 않습니다.
불행히도 이것은 DOM의 기본적인 특징일 뿐이다.이것은 우리로 하여금 생각하게 한다...

6, 아이템과 속성 혼동


아이템과 속성은 기본적으로 같죠?
const button = document.createElement('button');

button.hasAttribute('disabled'); // false
button.disabled = true;
button.hasAttribute('disabled'); // true

button.removeAttribute('disabled');
button.disabled; // false
내 말은, 거의:
typeof button.disabled; // 'boolean'
typeof button.getAttribute('disabled'); // 'object'

button.disabled = true;
typeof button.getAttribute('disabled'); // 'string'
그리고 몇몇 이름은 일치하지 않습니다...
div = document.createElement('div');

div.setAttribute('class', 'one');
div.className; // 'one'

div.className = 'two';
div.getAttribute('class'); // 'two'
...그것들은 전혀 대응하지 않는 것 같다.
input = document.createElement('input');

input.getAttribute('value'); // null
input.value = 'one';
input.getAttribute('value'); // null

input.setAttribute('value', 'two');
input.value; // 'one'
그러나 문자열 형식 (HTML) 과 DOM 사이의 변환에서 당연히 뭔가를 잃어버리기 때문에 우리는 이런 괴벽을 참을 수 있다.그것들의 수량은 유한하고 기록되어 있기 때문에 적어도 충분한 시간과 인내심만 있으면 그것들을 이해할 수 있다.
웹 구성 요소가 이 점을 바꾸었다.속성과 도구 간의 관계를 더 이상 보장하지 않을 뿐만 아니라, 웹 구성 요소의 저자로서, 당신은 (대략 그렇죠?)양자를 지지해야 한다.이것은 당신이 이런 일을 볼 수 있다는 것을 의미한다.
class MyThing extends HTMLElement {
  static get observedAttributes() {
    return ['foo', 'bar', 'baz'];
  }

  get foo() {
    return this.getAttribute('foo');
  }

  set foo(value) {
    this.setAttribute('foo', value);
  }

  get bar() {
    return this.getAttribute('bar');
  }

  set bar(value) {
    this.setAttribute('bar', value);
  }

  get baz() {
    return this.hasAttribute('baz');
  }

  set baz(value) {
    if (value) {
      this.setAttribute('baz', '');
    } else {
      this.removeAttribute('baz');
    }
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === 'foo') {
      // ...
    }

    if (name === 'bar') {
      // ...
    }

    if (name === 'baz') {
      // ...
    }
  }
}
때때로 속성 접근기를 호출하는 상반된 상황을 볼 수 있습니다.어쨌든 인체공학은 재난적이다.
그에 비해 프레임워크는 간단하고 명확한 방식으로 데이터를 구성 요소에 전달한다.

7. 누설 디자인


이 점은 좀 모호하지만 이상하게도 attributeChangedCallback 원소의 실례적인 방법일 뿐이다.너는 이렇게 할 수 있다.
const element = document.querySelector('my-thing');
element.attributeChangedCallback('w', 't', 'f');
속성은 변경되지 않았지만 변경된 것과 같습니다.물론 자바스크립트는 항상 많은 교란의 기회를 제공하지만, 세부 사항을 이렇게 찌르는 것을 볼 때, 나는 항상 그들이 우리에게 디자인이 정확하지 않다고 말하려고 한다고 생각한다.

8,DOM 좋지 않음


네, DOM이 나쁘다는 것을 확인했습니다.그러나 상호작용 응용 프로그램을 구축하는 데 있어서 이것은 얼마나 서투른 인터페이스인지 아무리 말해도 지나치지 않다.
몇 달 전에 나는 Write less code라는 글을 썼는데, Svelte가 React와 Vue 등 프레임워크보다 어떻게 구성 요소를 효율적으로 구축하는지 설명하기 위해서였다.하지만 DOM과 비교하지는 않았습니다.나는 마땅히 이렇게 해야 한다.
간단한attributeChangedCallback 구성 요소가 있습니다.
<script>
  export let a;
  export let b;
</script>

<input type="number" bind:value={a}>
<input type="number" bind:value={b}>

<p>{a} + {b} = {a + b}</p>
그게 다야.이제 웹 구성 요소와 같은 것을 구축합시다.
class Adder extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: 'open' });

    this.shadowRoot.innerHTML = `
      <input type="number">
      <input type="number">
      <p></p>
    `;

    this.inputs = this.shadowRoot.querySelectorAll('input');
    this.p = this.shadowRoot.querySelector('p');

    this.update();

    this.inputs[0].addEventListener('input', e => {
      this.a = +e.target.value;
    });

    this.inputs[1].addEventListener('input', e => {
      this.b = +e.target.value;
    });
  }

  static get observedAttributes() {
    return ['a', 'b'];
  }

  get a() {
    return +this.getAttribute('a');
  }

  set a(value) {
    this.setAttribute('a', value);
  }

  get b() {
    return +this.getAttribute('b');
  }

  set b(value) {
    this.setAttribute('b', value);
  }

  attributeChangedCallback() {
    this.update();
  }

  update() {
    this.inputs[0].value = this.a;
    this.inputs[1].value = this.b;

    this.p.textContent = `${this.a} + ${this.b} = ${this.a + this.b}`;
  }
}

customElements.define('my-adder', Adder);
그래
또한 <Adder a={1} b={2}/>a 를 동시에 변경하면 두 개의 단독 업데이트가 발생합니다.틀은 통상적으로 이 문제의 영향을 받지 않는다.

9. 글로벌 네임스페이스


우리는 이 문제를 지나치게 토론할 필요가 없다.한동안 사람들은 하나의 공유 명칭 공간을 사용하는 위험을 잘 이해해 왔다.

10. 이것들은 모두 이미 해결된 문제이다


가장 큰 좌절은 우리가 이미 매우 좋은 구성 요소 모델을 가지고 있다는 것이다.우리는 여전히 공부하고 있지만, 기본적인 문제는 구성 요소를 대상으로 DOM을 조작함으로써 보기와 일부 상태의 동기화를 유지하는 것이다. 이미 여러 해 동안 해결되었다.
그러나, 우리는 플랫폼을 위해 새로운 기능을 추가하고 있으며, 단지 웹 구성 요소가 우리가userland에서 이미 할 수 있는 것과 같도록 하기 위해서이다.
자원이 제한되어 있기 때문에, 한 임무에 쓴 시간은 다른 임무에 쓴 시간이 없다는 것을 의미한다.개발자들은 어느 정도 관심을 가지지 않지만 웹 구성 요소에 많은 노력을 기울였다.만약 이런 정력을 다른 곳에 쓴다면 인터넷은 어떤 성과를 거둘 수 있을까?

좋은 웹페이지 즐겨찾기