webpack이나 babel에 추가적인 설정을 위해서 cra 를 사용하지 않고 react 프로젝트를 직접 구성해야 할 때가 있다.
이 때를 위해 CRA 없이 React 프로젝트를 구성해보자.
해당 프로젝트 : https://github.com/easdkr/react-widthout-cra
GitHub - easdkr/react-widthout-cra
Contribute to easdkr/react-widthout-cra development by creating an account on GitHub.
github.com
사용한 주요 패키지의 버전
- babel : 7.18.5
- react : 18.2.0
- webpack:5.73.0
- webpack-cli:4.10.0
- webpack-dev-server:4.9.2
1. 프로젝트 초기화
npm init -y
2. React 패키지 설치
yarn add react react-dom
3. typescript, react type 패키지 설치
yarn add -D typescirpt @types/react @types/react-dom
4. typescript config 초기화
node_modules/.bin/tsc --init //전역으로 typescript가 설치되어있다면 그냥 tsc --init
5. tsconfig.json 설정
tsconfig.json
{
"compilerOptions": {
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"lib": ["DOM", "ES2015", "ES2016", "ES2017", "ES2018", "ES2019", "ES2020", "ES2021", "ES2022"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"jsx": "preserve", /* Specify what JSX code is generated. */
/* Modules */
"module": "ESNext", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
"baseUrl": "src", /* Specify the base directory to resolve non-relative module names. */
"types": [
"react/next",
"react-dom/next",
], /* Specify type package names to be included without being referenced in a source file. */
/* JavaScript Support */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
/* Emit */
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
/* Interop Constraints */
"isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
"allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
/* Completeness */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"exclude": ["node_modules"],
"include": ["**/*.ts", "**/*.tsx", "src"]
}
6. babel 패키지 설치
yarn add -D babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
- babel-loader : webpack에서 babel을 loader로 사용하기 위한 패키지
- babel : babel의 핵심기능을 가진 패키지
- babel/preset-env : ECMAScript2015+를 위한 프리셋 패키지인데 IE가 없어지는 지금 필요한지는 잘 모르겠다.
- babel/preset-typescript : 타입스크립트를 변환하기 위한 프리셋
7. babel config
babel.config.json
{"presets": ["@babel/preset-react", "@babel/preset-env", "@babel/preset-typescript"]}
8. webpack 패키지 설치
yarn add -D webpack webpack-cli webpack-dev-server html-webpack-plugin ts-loader
- webpack-dev-server : 개발 도중 변경사항 확인을 위한 패키지
- html-webpack-plugin : html 수정을 자동으로 하는 플러그인
- ts-loader : ts 코드를 js로 변환
9. webpack 설정 파일 생성
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const prod = process.env.NODE_ENV === 'production';
module.exports = {
mode: prod ? 'production' : 'development',
devtool: prod ? 'hidden-source-map' : 'eval',
entry: './src/index.tsx',
resolve : {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
modules: [
path.join(__dirname, "src"),
"node_modules"
]
},
module : {
rules : [
{
test: /\.tsx?$/,
use: ['babel-loader', 'ts-loader']
},
]
},
output : {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js'
},
plugins:[
new webpack.ProvidePlugin({
React: 'react',
}),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new webpack.HotModuleReplacementPlugin(),
],
devServer : {
historyApiFallback: true,
port : 3000,
hot: true,
compress:true,
static: {
directory: path.join(__dirname, 'public')
}
},
}
webpack 5의 설정 관련 사항은 https://webpack.kr/configuration/mode/ 여기서..
여기서 resolve.modules 설정은 절대경로 import 를 위해 추가함
10. package.json scripts 수정
package.json
...
"scripts": {
"dev": "webpack serve --mode development --open --hot",
"build": "webpack --mode production",
"prestart": "npm run build",
"start": "webpack --mode development"
},
...
11. 엔트리 포인트 코드 작성
src/index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>React without cra</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const rootDom = document.getElementById('root');
if (!rootDom) throw new Error('Failed to find the root element');
const root = ReactDOM.createRoot(rootDom);
root.render(
<App/>
)
src/App.tsx
import Button from "Components/Button";
import React from "react";
export default function App() {
return (
<>
<Button>Test</Button>
</>
)
};
*Button 컴포넌트는 예제 프로젝트 github 참고하고 아무 컴포넌트나 띄워보자!
'FrontEnd > react' 카테고리의 다른 글
Typescript, MUI (Material UI v5), React hook form 함께 사용하기 (with Generic) (2/2) (0) | 2022.09.04 |
---|---|
Typescript, MUI (Material UI v5), React hook form 함께 사용하기 (with Generic) (1/2) (0) | 2022.09.03 |
StoryBook 경로 설정하기 (0) | 2022.06.24 |
styled-components html이나 body tag에 스타일 적용하기 (0) | 2022.06.13 |
React 프로젝트 구조화 (0) | 2022.06.13 |