ES Modules & Import Maps: Back to the Future

웹 페이지를 만드는 것이 html 파일을 만드는 것을 의미했던 때가 있었지만 요즘에는 node_modules의 바닥 없는 구덩이 없이는 프런트엔드를 구축하는 것이 불가능해 보입니다. 글쎄요, 곧 그렇지 않을 수도 있다는 것을 알게 되었고, 자연스럽게 그것을 나머지 여러분과 공유하고 싶은 충동을 느낍니다.

HTML로 시작



HTML5의 베어본 페이지는 다음과 같습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

</body>
</html>


Hint: I got this template by typing html:5 in my VSCode thanks to Emmet abbreviations



모듈 추가



이제 예를 들어 Preact 프레임워크를 추가하고 싶다고 가정해 보겠습니다.
다음과 같이 할 수 있습니다.

 <body>
    <div id="app"></div>
    <script type="module">
       import { h, Component, render } from "https://esm.sh/[email protected]";
      import htm from "https://esm.sh/[email protected]";

      // Initialize htm with Preact
      const html = htm.bind(h);

      function App(props) {
        return html`<h1>Hello ${props.name}!</h1>`;
      }

      render(html`<${App} name="World" />`, document.getElementById("app"));
    </script>
  </body>


브라우저에서 간단한 파일로 페이지를 열고 실제로 작동하는지 확인할 수 있습니다. 이것이 바로 스크립트 태그에 type="module"를 추가하여 정의되는 최신 ECMAScript 모듈의 힘입니다.

이러한 간단한 페이지의 경우 잘 작동하지만 페이지를 더 추가하면 빠르게 작업하기가 어려워질 수 있습니다.

다른 것을 만들어 봅시다:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Counter</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module">
      import { h, Component, render } from "https://esm.sh/[email protected]";
      import { useState } from "https://esm.sh/[email protected]/hooks";
      import htm from "https://esm.sh/[email protected]";
      const html = htm.bind(h);

      function Counter() {
        const [count, setCount] = useState(0);
        return html`<button onClick=${() => setCount((n) => n + 1)}>
          Count: ${count}
        </button>`;
      }

      render(html`<${Counter}/>`, document.getElementById("app"));
    </script>
  </body>
</html>


중단되는 변경을 방지하기 위해 종속성의 정확한 버전을 지정하는 것이 좋지만 이러한 변경을 업데이트하는 것은 엉망이 될 것입니다.

아니오! import-map !

지도 가져오기



가져오기 맵은 별칭으로 특정 가져오기를 찾을 위치를 브라우저에 알려주는 JSON입니다. 예를 들어 다음 콘텐츠로 가져오기 맵을 만들 수 있습니다.

{
  "imports": {
    "preact": "https://esm.sh/[email protected]",
    "preact/": "https://esm.sh/[email protected]/",
    "htm": "https://esm.sh/[email protected]"
  }
}


다음과 같이 두 페이지에 모두 포함하십시오.

<body>
    <div id="app"></div>
    <script type="importmap">
      {
        "imports": {
          "preact": "https://esm.sh/[email protected]",
          "preact/": "https://esm.sh/[email protected]/",
          "htm": "https://esm.sh/[email protected]"
        }
      }
    </script>
    <script type="module">
      import { h, Component, render } from "preact";
      import { useState } from "preact/hooks";
      import htm from "htm";

      // Initialize htm with Preact
      const html = htm.bind(h);

      function App(props) {
        return html`<h1>Hello ${props.name}!</h1>`;
      }

      render(html`<${App} name="World" />`, document.getElementById("app"));
    </script>
  </body>


꽤 깔끔하죠? 또한 이를 사용하여 자신의 구성 요소를 참조하고 긴 경로를 피할 수 있습니다. 아, 미래가 밝다!

... 하지만 아직 거기에 도달한 것은 아닙니다.

안타깝게도 가져오기 맵은 아직 비공식 초안이므로 json 파일에서 외부 가져오기 맵을 포함하는 것과 같은 일부 중요한 기능이 지원되지 않거나 일부 브라우저(예: Safari)에서 지원되지 않습니다supported at all.

하지만 지금 바로 사용하고 싶습니다!



나는 당신의 말을 듣고 있습니다!

그리고 좋은 소식이 있습니다. ESM을 지원하고 지도를 즉시 가져올 수 있는 성숙한 JavaScript 런타임deno이 있습니다. 예를 들어 fresh 프레임워크는 함께 작업하는 것이 즐겁습니다.

저는 최근에 Hugo의 Fresh로 내 blog를 마이그레이션했으며 너무 오랫동안 연기해 온 일부 동적 기능을 마침내 구현하기를 기다릴 수 없습니다.

좋은 웹페이지 즐겨찾기