Setting to create React Project
React κ°λ° νκ²½ μΈν
π κΈ°λ³Έ νκ²½ μΈν
νλ‘μ νΈ ν΄λ μμ±
mkdir [proeject name]
cd [proeject name]npm global μ€μΉ
npm install -g npmnode version μΈν
node --version > .node-versionnpm μ΄κΈ°ν
npm init -yπ Typescript μ€μΉ λ° μ€μ
npm i -D typescriptTypescript μ€μ νμΌ μμ±
npx tsc --inittsconfig.json νμΌμμ jsx νλͺ© μμ
{
"jsx": "react-jsx"
}π ESLint μ€μΉ λ° μ€μ
npx eslint --init
$ > To check syntax, find problems, and enforce code style
$ > JavaScript modules (import/export)
$ > React
$ > Yes(TypeScript)
$ > Browser
$ > Use a popular style guide
$ > XO
$ > JavaScript
$ > Yes
$ > npmAirbnb μ€νμΌ μ μ©νκΈ°(optional)
TypeScriptμμ Airbnb μ§μνμ§ μκΈ° λλ¬Έμ, κΈ°μ‘΄μ μ€μΉν XOλ₯Ό μμ νκ³ Airbnb μ€νμΌμ μ μ©νλ€.
npm uninstall eslint-config-xo
npm uninstall eslint-config-xo-typescript
npm i -D eslint-config-airbnb
npm i -D eslint-plugin-import
npm i -D eslint-plugin-react
npm i -D eslint-plugin-react-hooks
npm i -D eslint-plugin-jsx-a11y
# install by one line
npm i -D eslint-config-airbnb eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y.eslintrc.js νμΌ μμ
module.exports = {
env: {
browser: true,
es2021: true,
jest: true, // jest μ€μ μ 미리 ν΄λ
},
extends: [
'airbnb',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react/jsx-runtime',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['react', 'react-hooks', '@typescript-eslint'],
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
},
rules: {
indent: ['error', 2],
'no-trailing-spaces': 'error',
curly: 'error',
'brace-style': 'error',
'no-multi-spaces': 'error',
'space-infix-ops': 'error',
'space-unary-ops': 'error',
'no-whitespace-before-property': 'error',
'func-call-spacing': 'error',
'space-before-blocks': 'error',
'keyword-spacing': ['error', { before: true, after: true }],
'comma-spacing': ['error', { before: false, after: true }],
'comma-style': ['error', 'last'],
'comma-dangle': ['error', 'always-multiline'],
'space-in-parens': ['error', 'never'],
'block-spacing': 'error',
'array-bracket-spacing': ['error', 'never'],
'object-curly-spacing': ['error', 'always'],
'key-spacing': ['error', { mode: 'strict' }],
'arrow-spacing': ['error', { before: true, after: true }],
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: [
'**/*.test.js',
'**/*.test.jsx',
'**/*.test.ts',
'**/*.test.tsx',
],
},
],
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
},
],
'react/jsx-filename-extension': [
2,
{
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
],
'jsx-a11y/label-has-associated-control': ['error', { assert: 'either' }],
},
};prettier μΆ©λ λ°©μ§(optional)
npm install --save-dev eslint-config-prettier.eslintrc.js νμΌ μμ
extends: [
'airbnb',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react/jsx-runtime',
'prettier',
],.eslintignore νμΌ μμ±
/node_modules/
/dist/
/.parcel-cache/π React μ€μΉ
npm i react react-dom
npm i -D @types/react @types/react-domsrc ν΄λ μμ±
mkdir srcApp.tsx νμΌ μμ±: ./src/App.tsx
export default function App() {
return <div>Hello, world!</div>;
}main.tsx νμΌ μμ±: ./src/main.tsx
import ReactDOM from 'react-dom/client';
import App from './App';
function main() {
const element = document.getElementById('root');
if (!element) {
return;
}
const root = ReactDOM.createRoot(element);
root.render(<App />);
}
main();index.html νμΌ μμ±: ./index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./src/main.tsx"></script>
</body>
</html>π Parcel μ€μΉ λ° μ€μ
npm i -D parcelparcel-reporter-static-files-copy μ€μΉ
npm install -D parcel-reporter-static-files-copy.parcelrc μμ±: ./.parcelrc
{
"extends": ["@parcel/config-default"],
"reporters": ["...", "parcel-reporter-static-files-copy"]
}static folder μμ±: ./static
νλ‘μ νΈ root path μ static ν΄λ μμ±
μ μ μ΄λ―Έμ§ λ± μ μ₯ ν΄λ
mkdir staticpackage.json μμ
main μμ ν μλμ μ½λ μΆκ°
"source": "./index.html",scripts μμ± μμ (*jestλ μΆν μ€μΉ)
"scripts": {
"start": "parcel --port 8080",
"build": "parcel build",
"check": "tsc --noEmit",
"lint": "eslint --fix --ext .js,.jsx,.ts,.tsx .",
"test": "jest",
"coverage": "jest --coverage --coverage-reporters html",
"watch:test": "jest --watchAll"
},π νλ‘μ νΈ κ΅¬λ ν
μ€νΈ
# λ‘컬 μ€ν
npm run start
# λΉλ
npx parcel build
# μ μ μλ² μ€ν
npx servor ./distπ Jest μ React Testing Library μ€μΉ
npm i -D jest @types/jest
npm i -D @swc/core @swc/jest jest-environment-jsdom
npm i -D @testing-library/react @testing-library/jest-dom@5.16.4jest.config.js: ./jest.config.js
module.exports = {
// ν
μ€νΈ νκ²½ μ€μ
testEnvironment: 'jsdom',
// Jestλ₯Ό μ€ννκΈ° μ μ€μ νμΌ
setupFilesAfterEnv: ['<rootDir>/src/jest.setup.js'],
// νΈλμ€νμΌλ¬ μ€μ
transform: {
'^.+\\.(t|j)sx?$': [
'@swc/jest',
{
jsc: {
parser: {
syntax: 'typescript',
jsx: true,
decorators: true,
},
transform: {
react: {
runtime: 'automatic',
},
legacyDecorator: true,
decoratorMetadata: true,
},
},
},
],
},
};jest.setup.js νμΌ μμ±: ./src/jest.setup.js
μΌλ¨ μμ±λ§ ν΄λκ³ , λμ€μ νμν λ μ½λ μΆκ°
eslintrc.js νμΌ μμ
module.exports = {
env: {
browser: true,
es2021: true,
jest: true, // μΆκ°(μ΄μ μ€μ μμ 미리 ν΄λμμ§λ§ ν λ² λ νμΈ)
},
...
}ν
μ€νΈ ꡬλ ν
μ€νΈ
npm run test
# μλμ κ°μ΄ νμ¬ λ§λ€μ΄μ§ ν
μ€νΈ νμΌμ΄ μλ€κ³ λμ€λ©΄ μλ£
No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In /.../workspace/react-project
9 files checked.
testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 0 matches
testPathIgnorePatterns: /node_modules/ - 9 matches
testRegex: - 0 matches
Pattern: - 0 matchesLast updated