ui 컴포넌트 버전 1을 만든다.
ui 컴포넌트 버전 2를 만든다.
ui 컴포넌트 버전 3을 만든다.
ui 라이브러리를 사용하다가 버그가 발견되면??
- node_modules, packagelock.json 삭제
- yarn set version berry
- yarn
- package.json 스크립트 yarn으로 변경
"workspaces":[
"packages/**/*",
"services/**/*"
],
yarn add @hojoon/themes 로 설치하면 끝
"build": "nx build",
"graph": "nx run-many --target=build --graph"
yarn berry 설정까지만 하고 모노레포 처음 만들고 너무 기분 좋아서 일단 깃허브에 푸쉬하고 말았는데 갑자기 test로 만든 리액트 프로젝트에서 모듈 에러가 나고 그래서 몇시간 삽질했다.
이후에는 prettier, eslint, tsconfig 설정도 안먹어서 모노레포랑 yarn berry 프로젝트 포기할까 했지만 괜히 혼자 겁먹은게 잘못이었다.
왜냐면 강의 몇분만 더 들으면 설정하는법 다알려주기 때문!
루트 폴더에 tsconfig.base.json 파일을 만들고 다른 패키지에서 루트에 있는 tsconfig.base.json 파일의 설정을 상속받는다.
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"declaration": true,
"strict": true,
"moduleResolution": "node",
"jsx": "react-jsx"
}
}
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist"
}
}
루트폴더의 packages.json
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.48.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-json-format": "^2.0.1",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-storybook": "^0.6.13",
"nx": "^17.2.8",
"prettier": "^3.1.1",
"typescript": "^5.3.3"
}
이렇게 설치하고 .eslintrc.js, .prettierrc 파일을 만들어주고 개발환경을 세팅해줄 텐데 대부분의 사람들이 vscode랑 prettier가 충돌이 나서 빨간 에러가 뜰거다. 나도 떠서 삽질많이함
yarn dlx @yarnpkg/sdks vscode
이러면 이제 에러도 해결된다.
yarn init
yarn add esbuild@0.16.17
const { build } = require("esbuild");
const run = ({ entryPoints = ["src/index.ts"], pkg, config = {} }) => {
const dev = process.argv.includes("--dev");
const minify = !dev;
const watch = process.argv.includes("--watch");
const external = Object.keys({
...pkg.dependencies,
...pkg.peerDependencies,
});
const baseConfig = {
entryPoints,
bundle: true,
minify,
sourcemap: true,
outdir: "dist",
target: "es2019",
watch,
external,
...config,
};
Promise.all([
build({
...baseConfig,
format: "esm",
}),
build({
...baseConfig,
format: "cjs",
outExtension: {
".js": ".cjs",
},
}),
]).catch(() => {
console.error("Build failed");
process.exit(1);
});
};
module.exports = run;
-package.json 설정
{
"name": "@hojoon/esbuild-config",
"packageManager": "yarn@4.0.2",
"main": "index.js",
"files": [
"index.js"
],
"scripts": {
"build": "echo \"hojoon!\"",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"esbuild": "0.16.17"
}
}
yarn add --dev @hojoon/esbuild-themes
import run from "@hojoon/esbuild-config";
import pkg from "./package.json" assert { type: "json" };
run({
pkg,
});
yarn build @hojoon/themes
yarn graph
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist"
}
}
2.build.js vanilla-extract plugin 세팅
import run from "@hojoon/esbuild-config";
import pkg from "./package.json" assert { type: "json" };
import { vanillaExtractPlugin } from "@vanilla-extract/esbuild-plugin";
const config = {
plugins: [vanillaExtractPlugin()],
};
run({
pkg,
config,
});
yarn init
yarn workspace @hojoon/storybook dlx storybook init --type react
yarn storybook
yarn add --dev @hojoon/themes @hojoon/react-components-layout
import "@hojoon/themes/themes.css"
import "@hojoon/react-components-layout/style.css";
import { Block as _Block } from "@hojoon/react-components-layout";
export default {
title: "React Components/Layout/Block",
component: _Block,
tags: ["autodocs"],
parameters: {
layout: "centered",
},
};
export const BlockStory = {};
"dev": "yarn build:js --watch && yarn build:type --watch"
"dev:all": "yarn dev:storybook & yarn dev:packages",
"dev:storybook": "nx storybook @hojoon/storybook",
"dev:packages": "nx run-many --target=dev --projects='@hojoon/react-components-*'"
yarn dev all
yarn add -dev stroybook-addon-root-attributes
getAbsolutePath("storybook-addon-root-attributes"),
import "@hojoon/themes/themes.css";
/** @type { import('@storybook/react').Preview } */
const preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
rootAttributesTooltip: true,
rootAttributes: [
{
root: "body",
attribute: "class",
defaultState: {
name: "light",
value: "theme-light",
},
states: [
{
name: "dark",
value: "theme-dark",
},
],
},
],
},
};
export default preview;
const initTheme = () => {
const isDarkTheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
if (isDarkTheme) {
document.body.classList.add("theme-dark");
}
const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
mediaQueryList.addEventListener("change", (e) => {
if (e.matches) {
document.body.classList.add("theme-dark");
} else {
document.body.classList.remove("theme-dark");
}
});
};
initTheme();
생소해서 너무 어렵기도 하지만 해보지 않았던거라 또 나름 공부하는 재미가 있다. 몰랐던 스크립트 작성이나 의존 관계들, 패키지 디펜던시에 좀 가까워지는듯?