👔
(프롱이)프로젝트 환경 설정
요약
create-react-app
, Typescript
ESlint
, Prettier
emotion/styled
storybook
axios
1) create-react-app & Typescript
tsconfig.json
2) ESLint & Prettier 설정
package.json
- 설치 완료 후 아래의
devDependencies
가 추가된다.
.eslintrc.js
- 자동 생성된
.eslintrc.js
코드를 아래와 같이 수정하여 rule을 추가한다.
.prettierrc
- 루트 폴더에
.prettierrc
파일 생성 후 아래 코드를 작성한다.
3) emotion, styled
- javascript 파일 내부에서 스타일 적용 패키지
craco(create-react-app-config-override)
- 위의 패키지 3개만 추가하면 styled 패키지를 사용할 때 마다
/** @jsxImportSource @emotion/react */
fragma 주석을 추가해야 되는데, 이를 해결하기 위해 craco
를 설치한다.
craco.config.js
- 루트 폴더에 craco.config.js 파일을 생성하여 아래와 같이 추가한다.
package.json
- package.json 파일에서 scripts 부분을
react-scripts
에서 craco
로 변경한다.
4) Storybook
- UI 컴포넌트를 모아 문서화하고 보여주는 오픈소스 Tool
storybook 설치 후 start 오류
- storybook 설치 후 react-scripts와 storybook의 babel-loader 버전이 달라서 yarn start로 로컬 환경 Open이 되지 않는 현상이 발생한다.
- package.json 파일에 아래 코드를 추가하여 해결할 수 있다.
5) Axios
- 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리
6) .env
ESLint
설치 후 package.json과 yarn.lock에서의 package version 차이가 발생해서 yarn start 같은 로컬 환경이 Open되지 않는다.
- 루트 폴더에 .env 파일을 생성 후 아래 코드를 추가한다.
최종 package.json
yarn create react-app yas --template typescript
{
"compilerOptions": {
"target": "es6", // 기본값: es5 => es6로 수정
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
],
}
yarn add -D eslint prettier
yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser // ESLint Rule 추가 플러그인
yarn add -D eslint-config-airbnb // airbnb ESLint 규칙
yarn add -D eslint-config-prettier eslint-plugin-prettier // prettier Rule 플러그인
yarn add -D eslint-plugin-react eslint-plugin-react-hooks // airbnb ESLint 규칙
yarn add -D eslint-plugin-jsx-a11y eslint-plugin-import // airbnb ESLint 규칙
// ...
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"eslint": "^8.3.0",
"eslint-config-airbnb": "^19.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.27.1",
"eslint-plugin-react-hooks": "^4.3.0",
"prettier": "^2.5.0"
}
// ...
module.exports = {
env: {
browser: true,
node: true, // node: true, commonjs: true 추가
commonjs: true, // 사전 정의된 static 메서드를 인식할 수 없어서 에러 발생하는 것에 대해 ESLint 경고가 발생하지 않도록 추가
es2021: true,
},
extends: [
'airbnb',
'plugin:react/recommended',
'plugin:jsx-a11y/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:@typescript-eslint/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2018,
sourceType: 'module',
},
plugins: ['react', '@typescript-eslint'],
rules: {
'linebreak-style': 0,
'import/prefer-default-export': 0,
'import/extensions': 0,
'no-use-before-define': 0,
'import/no-unresolved': 0,
'react/react-in-jsx-scope': 0,
'import/no-extraneous-dependencies': 0,
'no-shadow': 0,
'react/prop-types': 0,
'react/jsx-one-expression-per-line': 0,
'func-names': ['error', 'as-needed'],
'react/jsx-filename-extension': [
2,
{
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
],
'object-curly-newline': [
'error',
{
ExportDeclaration: {
multiline: true,
minProperties: 2,
},
},
],
'jsx-a11y/no-noninteractive-element-interactions': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
},
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
},
};
{
"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80,
"arrowParens": "always",
"orderedImports": true,
"bracketSpacing": true,
"jsxBracketSameLine": false
}
yarn add @emotion/react // emotion
yarn add --dev @emotion/babel-plugin // babel
yarn add @emotion/styled // styled
// ...
"dependencies": {
"@emotion/react": "^11.6.0",
"@emotion/styled": "^11.6.0",
// ...
yarn add -D @craco/craco
yarn add -D @emotion/babel-preset-css-prop
module.exports = {
babel: {
presets: ["@emotion/babel-preset-css-prop"]
}
}
// ...
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "craco eject"
},
// ...
npx -p @storybook/cli sb init
// package.json
// ...
"resolutions": { "babel-loader": "8.1.0" }
// ...
SKIP_PREFLIGHT_CHECK=true
{
"name": "yas",
"version": "0.1.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.6.0",
"@emotion/styled": "^11.6.0",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"axios": "^0.24.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"typescript": "^4.1.2",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "craco eject",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -s public"
},
"resolutions": { "babel-loader": "8.1.0" },
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"overrides": [
{
"files": [
"**/*.stories.*"
],
"rules": {
"import/no-anonymous-default-export": "off"
}
}
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@craco/craco": "^6.4.2",
"@emotion/babel-plugin": "^11.3.0",
"@emotion/babel-preset-css-prop": "^11.2.0",
"@storybook/addon-actions": "^6.3.12",
"@storybook/addon-essentials": "^6.3.12",
"@storybook/addon-links": "^6.3.12",
"@storybook/node-logger": "^6.3.12",
"@storybook/preset-create-react-app": "^3.2.0",
"@storybook/react": "^6.3.12",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"eslint": "8.3.0",
"eslint-config-airbnb": "^19.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.27.1",
"eslint-plugin-react-hooks": "^4.3.0",
"prettier": "^2.5.0"
}
}