Skip to content

custardcream98/custard-library

Repository files navigation

custard-library

리액트 라이브러리 실험을 위한 모노레포입니다. 각종 아이디어, 구현해보고 싶은 것을 개발합니다.

Table of Contents

라이브러리 목록

전역 상태관리 라이브러리를 직접 만들어보자

@custardcream/very-simple-store

웹 데모

프로젝트 바로가기

간단한 방법으로 구현한 전역 상태관리 라이브러리입니다.

VSCode Bootstrap IntelliSense

vscode-bootstrap-intellisense

프로젝트 바로가기

VSCode에서 Bootstrap 4를 사용할 때 IntelliSense를 제공해주는 VSCode Extension입니다.

현업 프로젝트에서 Bootstrap을 커스텀해 사용하고 있는데 커스텀한 Stylesheet에 대해 IntelliSense를 제공해주는 Extension이 없어서 조금씩 개발하고 있습니다.

모노레포 설정

pnpm workspace를 사용해 환경을 구성했습니다. 모노레포 구조, 설정하는 과정에서 알게 된 사실들을 정리하겠습니다.

packages

  • eslint-config-custom: 커스텀 ESLint 룰을 모아둡니다. base.js, react.js 등으로 분리해 관리합니다. 사용하는 측에서는 devDependency로 추가하고 ESLint config에서 extend하면 됩니다. (예시) 패키지마다 조금씩 다른 설정을 할 수 있도록 이렇게 관리하기로 했습니다.

apps

  • web: 라이브 데모를 위한 Next.js 앱입니다.
  • storybook: 개발 용이성을 위해 Storybook 앱을 따로 만들었습니다. packages의 패키지를 직접 import하지 않고, concurrently를 사용해 Storybook 앱 실행과 build를 동시에 진행토록 해 빌드한 결과물을 사용합니다. 번들러로는 vite를 선택했습니다.

rollup.config.mjs

ESM을 사용하고자 .mjs 확장자를 사용하고, --bundleConfigAsCjs 옵션을 썼습니다. TypeScript로 작성도 가능했으나, 좀 더 간편한 설정을 위해 JavaScript로 했습니다.

  • 사용한 플러그인
    • @rollup/plugin-node-resolve: external module resolver입니다.
    • @rollup/plugin-terser: minify를 위한 terser입니다.
    • @rollup/plugin-typescript: TS 트랜스파일을 위한 플러그인입니다. babel을 사용하지 않고 이 플러그인을 썼습니다.
    • rollup-plugin-dts: TS declare file 생성을 위한 플러그인입니다. 코드 빌드 후 따로 빌드합니다.
    • @rollup/plugin-babel: JSX 트랜스파일을 위해 사용한 babel 플러그인입니다. @babel/preset-react를 사용하며, @babel/plugin-transform-runtime으로 필요한 polyfill만 사용토록 했습니다. (레퍼런스)
    • rollup-plugin-styles: css, scss module 사용을 위해 추가한 플러그인입니다. 커스텀 style inject 함수를 정의해 사용했습니다. (customStyleInjector)

rollup.vscode.config.mjs

오직 CJS로만 빌드되는 VSCode Extension 프로젝트를 위한 별도 설정입니다.

TypeScript

tsconfig를 구조화해 패키지마다 필요한 설정만을 가져갈 수 있도록 하고자 했습니다.

  • tsconfig.base.json: 기본적으로 사용하는 config입니다.
  • tsconfig.cssModule.json: css module을 위한 ts plugin을 추가하는 config입니다. 빌드시에는 style.d.ts에서 정의된 declare를 사용하지만, 개발 환경에서는 이 플러그인 덕분에 css module로 정의된 스타일에 대해 타입 체킹과 auto complete가 제공됩니다.
  • tsconfig.eslint.json: ESLint용 config입니다.
  • tsconfig.paths.json: 프로젝트별 alias, pacakges의 alias를 추가하는 config입니다.

각 패키지, 앱은 위의 config를 extend해 설정됩니다.

참고: tsc --showConfig로 컴파일러가 보는 최종 tsconfig를 확인할 수 있습니다.

Troubleshooting: Storybook tsconfig array extends issue

apps/storybook의 tsconfig에서는 extendstsconfig.base.json만 넣고, paths 프로퍼티를 하드코딩 했습니다. (tsconfig.paths.json도 같이 extends하지 못하고) extends에 배열을 넣을 수 없었기 때문입니다.

array extends는 추가된지 얼마 되지 않은 기능입니다. Storybook이 사용하는 esbuild 관련 라이브러리인 esbuild-register에서 tsconfig resolver로 tsconfig-paths를 사용하는데, tsconfig-paths쪽은 업데이트 됐는데 esbuild-register쪽에서 tsconfig-paths의 버전을 업그레이드하지 않고 있습니다.

때문에 esbuild-register를 의존하고 있는 Storybook에서는 이 문제를 해결할 방법이 마땅치 않은 상황입니다.

package.json에서 resolutions 프로퍼티로 tsconfig-paths의 버전을 강제로 올려보려고도 했지만, esbuild-registertsconfig-paths를 peerDependency가 아닌 devDependency로 가지고 있고, 빌드 결과물을 export하고 있어 esbuild-register 빌드를 다시 하지 않는 이상 이 방법은 사용할 수 없었습니다.

관련 esbuild-register PR

관련 Storybook issue (esbuild-register 말고 다른거 쓰면 안되냐고 징징거리는 제 코멘트를 볼 수 있습니다...)

esbuild-register는 마지막 publish가 22년 12월인 것으로 보아 근시일 내에 이 상황이 바뀌지는 않을 것 같습니다.

if문 하나 있고 없고 차이만 고치면 되는걸 패키지끼리 의존성으로 인해 해결하지 못하는겁니다. 이 경험으로 dependency를 추가할 때는 신중해야겠다는 생각을 하게 됐습니다.

똑같은 문제가 eslint-plugin-import에서도 발생했는데 이쪽은 dependency로 가지고 있어서 resolutions 프로퍼티 수정으로 해결이 가능했습니다.