Deno 및 JSX를 사용하여 서버에서 HTML 생성

서버에서 html을 생성하려면 템플릿 엔진이 필요합니다.
EJS , handlebars 등을 사용할 수 있지만 부분 및 레이아웃으로 작업하는 대신 구성 요소를 만들 수 있는 템플릿 엔진을 선호합니다.

다행스럽게도 Deno는 swc 덕분에 JSX를 기본적으로 지원합니다. JSX는 Javascript의 구문 확장입니다. 이는 JSX이 React.createElement()와 같은 실제 자바스크립트 호출로 변환됨을 의미합니다(자세한 내용은 아래 참조). 이것은 좋지만 Deno는 React에 대해 알지 못하므로 추가 작업이 필요합니다.

먼저 간단한 Deno 애플리케이션을 만들어 시작할 것입니다.
이 코드를 main.js에 입력합니다.

import { serve } from "https://deno.land/[email protected]/http/server.ts";

const server = serve({ port: 8000 });
const headers = new Headers();
headers.append("Content-Type", "text/html; charset=UTF-8");

for await (const req of server) {
  req.respond({
    status: 200,
    headers,
    body: `
      <!DOCTYPE html>
      <html>
        <head>
          <title>Hello</title>
          <link 
            href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" 
            rel="stylesheet">
        </head>
        <body>
          <h1 class="text-3xl m-2">Hello world</h1>
          <button 
            class="border bg-indigo-600 text-white px-2 py-1 rounded m-2">
            Useless button
          </button>
        </body>
      </html>`,
  });
}

deno run --allow-net ./main.js 로 시작할 수 있습니다. 이제 localhost:8000에서 브라우저를 열고 html 페이지를 볼 수 있습니다.

목표는 이 html 템플릿 문자열을 JSX 구성 요소로 바꾸는 것입니다.

반응 16



첫 번째 구성 요소pages/home.jsx를 만들 차례입니다.
지금은 완전한 html이 포함된 단일 구성 요소입니다.

import React from "https://jspm.dev/[email protected]";

export default function () {
  return (
    <html>
      <head>
        <title>Hello</title>
        <link
          href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css"
          rel="stylesheet"
        />
      </head>
      <body>
        <h1 className="text-3xl m-2">Hello world</h1>
        <button
          className="border bg-indigo-600 text-white px-2 py-1 rounded m-2"
        >
          Useless button
        </button>
      </body>
    </html>
  );
}


이제 main.js에서 이 구성 요소를 사용할 때입니다.

import { serve } from "https://deno.land/[email protected]/http/server.ts";
import ReactDOMServer from 'https://jspm.dev/[email protected]/server';
import home from "./pages/home.jsx"

function render(jsx) {
  return ReactDOMServer.renderToString(jsx());
}

const server = serve({ port: 8000 });
const headers = new Headers();
headers.append("Content-Type", "text/html; charset=UTF-8");

for await (const req of server) {
  req.respond({
    status: 200,
    headers: headers,
    body: render(home),
  });
}


여기에는 JSX 함수를 실행하고 결과를 문자열로 렌더링하는 새로운 렌더링 함수가 포함됩니다.
renderToString 대신 renderToStaticMarkup 을 사용할 수도 있습니다.

이제 React 16에서 작동하는 JSX 예제가 있습니다!

React 17은 작성 시점not yet에서 지원됩니다. 문제는 React 17에서 JSX가 새로운 것으로 변환된다는 것입니다. React를 가져올 필요성을 피하기 위해 더 이상 React.createElement가 아닙니다.

처음에 Skypack CDN에서 React 16을 로드하려고 시도했지만 this issue 때문에 작동하지 않습니다.

프리액트



React 대신 Preact를 사용하는 것도 가능합니다.

JSX는 React.createElement()로 변환되므로 React를 다른 클래스로 대체해야 합니다.
이를 수행하는 방법에는 두 가지가 있습니다.
  • JSX pragma 포함
  • tsconfig.json 포함

  •  /** @jsx h */
    import { h } from "https://cdn.skypack.dev/preact";
    

    첫 번째 줄은 JSX pragma입니다. 이것은 h 대신 React 를 사용하는 것을 의미합니다.
    그러나 tsconfig.json를 사용할 수도 있으므로 어디에서나 pragma가 필요하지 않습니다.
    구성에 대한 링크로 Deno를 실행해야 합니다deno run --config ./tsconfig.json ....

    {
        "compilerOptions": {
            "jsx": "react",
            "jsxFactory": "h",
        }
    }
    

    main.js의 렌더링 기능은 다음과 같습니다.

    import renderToString from "https://cdn.skypack.dev/[email protected]";
    
    function render(jsx) {
      return renderToString(jsx());
    }
    


    결과



    최종 버전에서는 레이아웃과 버튼을 위한 추가 구성 요소를 만들었습니다.

    페이지/home.jsx

    import React from "https://jspm.dev/[email protected]";
    import Layout from "../components/layout.jsx";
    import Button from "../components/button.jsx";
    
    export default function () {
      return (
        <Layout title="Hello">
          <h1 className="text-3xl m-2">Hello world</h1>
          <Button>
            Useless button
          </Button>
        </Layout>
      );
    }
    


    구성 요소/button.jsx

    import React from "https://jspm.dev/[email protected]";
    
    export default function ({ children }) {
      return (<button
        className="border bg-indigo-600 text-white px-2 py-1 rounded m-2"
      >
        {children}
      </button>);
    }
    


    구성 요소/layout.jsx

    import React from "https://jspm.dev/[email protected]";
    
    export default function ({ children, title }) {
      return (
        <html>
          <head>
            <title>{title}</title>
            <link
              href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css"
              rel="stylesheet"
            />
          </head>
          <body>
            {children}
          </body>
        </html>
      );
    }
    


    이것이 Deno에서 JSX를 시작하는 데 도움이 되기를 바랍니다. 이것은 단순한 예일 뿐이며 deps.ts 및 Typescript를 사용하는 것과 같이 개선해야 할 부분이 많습니다. 하지만 이 예제는 JSX에 초점을 맞추려고 합니다.

    모든 코드here를 찾을 수 있습니다.

    좋은 웹페이지 즐겨찾기