나는 node와 npm을 싫어한다.

node_modules가 프로젝트마다 생기는게 싫고 webpack 설정이 싫고 타입스크립트 쓰려면 별의별것을 다 써야하고 바벨써야하고 뭐 시발 간단한 타입스크립트 프로젝트 하나 만들라면 설정하는데 시간 다잡아먹고 의욕도 떨어진다.

지금까지 deno를 node의 대용으로 사용하려고 한건 순전히 nextjs로 되어있는 걸 fresh로 바꾸려는게 목적이었는데… 4년전쯤 만들었던 게 제대로 작동 안한다는 소식을 듣고 고쳐볼까 했는데… 그게… 프론트 얼마 안해봤을 때 자바스크립트+웹팩+리액트로 한거여서 와… 보기가 너무 겁남…

여튼 그래서 deno에서도 이게 가능할까? 싶어서 여러가지 찾아봄.

번들러

원래는 디노 자체에 번들 커맨드가 있었는데, deprecated 되고… 찾아보니 esbuild를 많이 쓰는 것 같다.

deno에서 esbuild를 쓰려면 deno용 로더도 사용해야한다.

https://deno.land/x/esbuild@v0.19.10

https://deno.land/x/esbuild_deno_loader@0.8.2

번들러용 디펜던시 모아두는 파일(deps.bundle.ts)를 아래와 같이 만든다.

// deps.bundle.ts
export * as esbuild from "https://deno.land/x/esbuild@v0.19.2/mod.js";
export { denoPlugins } from "https://deno.land/x/esbuild_deno_loader@0.8.2/mod.ts";

그다음 번들할 때 사용할 스크립트를 만든다.

// bundle.ts
import { denoPlugins, esbuild } from "./deps.bundle.ts";
import { resolve } from "https://deno.land/std@0.210.0/path/mod.ts";

await esbuild.build({
  plugins: [...denoPlugins({
    configPath: resolve(Deno.cwd(), "deno.json")
  })],
  entryPoints: ["./src/index.tsx"],
  outfile: "./dist/bundle.js",
  bundle: true,
  format: "esm",
});

console.log("Done!")

esbuild.stop();

configPath는 deno.json 경로를 절대경로로 넣어줘야한다. (imports 설정)

esm.sh

ECMAScript Module(ESM)를 사용하기 위한 CDN? 이라고 해야하나?

https://esm.sh/

에서 살펴볼 수 있다. 프로젝트 생성시 위 페이지에서 CLI사용하도록 초기화하는 예시가 나와있다.

deno run -A -r https://esm.sh init

그런 다음 react와 react-dom을 설치한다.

deno task esm:add react react-dom

그러면 아래와 같이 deno.json에 추가된다.

리액트용 디펜던시를 모아둔 파일(deps.ts)를 만든다.

// deps.ts
export { default as React } from "react";
export { default as ReactDOM } from "react-dom/client";

그 다음 index.tsx, 와 Counter.tsx를 간단히 만들어본다.

// src/index.tsx
import { React, ReactDOM } from "../deps.ts";
import Counter from "./components/Counter.tsx";

const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(<Counter />)
// src/components/Counter.tsx
import { React } from "../../deps.ts";

export type CounterProps = {
  initialValue?: number
};

export default function Counter({ initialValue = 0 }: CounterProps): JSX.Element {
  const [count, setCount] = React.useState(initialValue);

  return (
    <>
      <h1>Count : {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </>
  )
}

그 다음 번들 해본다.

deno run -A bundle.ts

요런 식으로 실행된다.

이제 적당히 html을 넣어서 테스트 해본다.

잘된다.

끗.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다