웹팩4 + 리액트는 구글에 참 많은 자료가 있다. 리액트 + 타입스크립트도 많다. 웹팩4 + 리액트 + 타입스크립트도 있다. 그런데 웹팩5 + 타입스크립트 + 리액트 초기세팅에 대한 자료는 별로 없다!
있는데 못찾았을 가능성이 더 큼...자료가 있어도 한번에 정리해놓은 자료는 별로 없는 것 같아서 블로그에 정리해 봅니다. 미래의 나에게 도움이 되길😆
터미널에 다음 명령어로 폴더를 생성해 줍니다.
mkdir <폴더 이름>
터미널에 명령어를 입력해서 리액트를 설치해 줍니다.
npm install --save react react-dom
타입스크립트를 설치하면 이전에 설치했던 라이브러리의 type들이 필요하기 때문에 react와 react-dom의 @types도 설치해줍니다.
npm install --save typescript
npm install --save-dev @types/react @types/react-dom
웹팩은 모던 자바스크립트 애플리케이션을 위한 정적 모듈 번들러입니다. 이 포스트는 초기 세팅을 설명하기 때문에 웹팩에 대한 자세한 설명은 넘어가도록 하겠습니다. 웹팩과 로더들을 설치해줍니다.
npm install --save-dev webpack webpack-cli webpack-dev-server babel-loader css-loader file-loader html-loader html-webpack-plugin style-loader url-loader
바벨을 설치해줍니다.
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
.babelrc 파일을 만들어줍니다.
//.babelrc
{
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"]
}
터미널에 다음 명령어로 tsconfig.json 파일을 생성해줍니다.
tsc --init
tsconfig.json 파일은 프로젝트를 컴파일 하는 방법에 대한 옵션을 설정할 수 있습니다.
//tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["dom", "ES2015", "ES2016", "ES2017", "ES2018", "ES2019", "ES2020"],
"allowJs": true,
"jsx": "react",
"outDir": "./dist",
"isolatedModules": true,
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
옵션 | 설명 |
---|---|
compilerOptions | 컴파일 옵션을 정의 |
target | 컴파일된 코드가 es5 환경에서 실행되도록 정의 |
module | 컴파일된 코드가 어떤 모듈 시스템을 사용할지 정의 |
lib | 현재 프로젝트에서 사용할 수 있는 특정 기능에 대한 문법(타입)을 추가 |
allowJs | js파일을 허용 |
jsx | preserve, react-native, react, react-jsx, react-jsxdev와 같은 jsx코드 생성을 지정 |
outDir | 컴파일된 파일이 어디에 저장될지 경로를 정함 |
isolatedModules | 각 파일을 별도의 모듈로 변환 |
strict | 모든 타입 체킹 옵션 활성화 |
esModuleInterop | commonjs 모듈 형태로 이루어진 파일을 es2015 모듈 형태로 불러올 수 있게 해줌 |
forceConsistentCasingInFileNames | 동일한 파일에 대해 대소문자가 일치하지 않는 참조를 허용하지 않음 |
include | 어떤 파일을 컴파일할 것인지 설정 |
exclude | 어떤 파일을 컴파일에서 제외할 것인지 설정 |
() => return 'a'
같은 es6문법으로 작성된 코드를 function() return 'a'
같은 es5 문법으로 컴파일 해줍니다.export default App
이라는 코드는 export.default = App
로 변환됩니다. es2015로 설정하면 export default App
코드가 그대로 유지됩니다.저는 제가 원하는 옵션만 활성화 해줬지만, tsconfig에는 훨씬 많은 옵션을 설정할 수 있습니다. tsc --init
으로 tsconfig.json 파일을 생성했다면 파일 안에 사용할 수 있는 옵션들과 설명이 적혀있습니다. 읽어보시고 원하는 옵션이 있다면 활성화해서 사용하세요!
폴더에 webpack.config.js 파일을 만들어줍니다. 만든 파일에 아래의 코드를 입력해주세요.
//webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/index.tsx',
output: {
path: path.join(__dirname, 'build'),
filename: '[name].[contenthash].js',
chunkFilename: '[name].bundle.js',
publicPath: '/',
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /nodeModules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/, //폰트 파일이 로더될 수 있도록 함
use: [
{
loader: 'file-loader',
options: {
name: 'fonts/[name]-[hash].[ext]',
},
},
],
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: false,
name: 'images/[name]-[hash].[ext]',
},
},
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
},
],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.json'],
},
plugins: [new HtmlWebpackPlugin({ template: './public/index.html' })],
}
이름 | 설명 |
---|---|
output | 파일이 번들되면 어디로 보낼지 설정하는 옵션 |
path | 번들 파일이 저장될 디렉토리 이름 |
filename | 웹팩 실행 후 생성된 새로운 번들 파일에 대해 설정할 이름 |
chunkFile | ChunkFile의 이름을 설정 |
pulicPath | 어플리케이션의 기본 경로 설정 |
module | 파일 번들링 규칙을 지정하는 옵션 |
rules | 모듈이 생성되는 방식을 수정 |
test | 특정 로더의 대상이 되어야 하는 파일 확장자 |
exclude | 번들러가 무시해야 하는 파일 지정 |
loader | 사용할 로더 종류 배열로 작성하면 배열의 순서대로 실행됨 |
resolve | 모듈 해석에 대한 설정 |
extensions | 확장자를 순서대로 해석함 |
plugins | plugin을 추가할 수 있음 |
HtmlWebpackPlugin | 웹팩이 html 파일 템플릿을 알 수 있도록 하는 플러그인 |
저는 개발용 웹팩 설정을 따로 만들어 주는게 더 편해서 파일을 하나 만들어 주도록 하겠습니다.
webpack.config.dev.js라는 이름으로 만들었습니다.
//webpack.config.dev.js
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.tsx',
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].bundle.js',
publicPath: '/',
path: path.resolve(__dirname, 'build'),
},
devtool: 'inline-source-map',
devServer: {
https: true,
host: 'localhost',
compress: true,
hot: true,
port: 3000,
open: true,
client: {
progress: true,
},
},
stats: {
cachedModules: false,
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'fonts/[name]-[hash].[ext]',
},
},
],
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: false,
name: 'images/[name]-[hash].[ext]',
},
},
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
},
],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.json'],
},
plugins: [new HtmlWebPackPlugin({ template: './public/index.html' })],
};
이름 | 설명 |
---|---|
devtool | 소스 맵이 생성되는지 여부와 생성 방법을 제어 |
inline-source-map | 원본 소스와 난독화된 소스를 매핑 |
devServer | webpack-dev-server의 동작을 변경할 수 있는 옵션 |
https | https를 사용할지 http를 사용할지 설정 |
host | host 이름 설정 |
compress | 제공되는 모든 항목에 대해 gzip 압축 활성화 |
hot | 웹팩으로 빌드한 결과물이 웹 애플리케이션에 실시간으로 반영될 수 있게 하는 설정 |
port | port 번호 설정 |
open | 서버가 시작된 후 브라우저(예, 크롬)을 열도록 하는 옵션 |
progress | 브라우저에서 컴파일 진행률을 백분율로 보여줌 |
stats | 표시되는 번들 정보를 제어할 수 있는 옵션 |
cachedModules | 빌드되지 않고 캐시된 모듈에 대한 정보를 추가하지 않음 |
두 파일을 모두 작성이 끝나면 package.json
파일 script에 다음 코드를 작성해 줍니다.
//package.json
"scripts": {
"build": "webpack --config webpack.config.js",
"start": "webpack serve --config webpack.config.dev.js",
},
폴더에 public 폴더를 만들어 주고 그 안에 index.html을 작성해 줍니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, inital-scale=1.0" />
<title>React using webpack5 but without CRA</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
src 폴더를 만들어 주고 그 안에 index.tsx와 App.tsx파일을 작성해 줍니다.
//index.tsx
import React from 'react';
import ReactDom from 'react-dom';
import App from './App';
ReactDom.render(<App />, document.getElementById('root'));
//App.tsx
import React, { useState } from 'react';
function App() {
const [click, setClick] = useState('');
const clickButton = () => {
setClick('click');
};
return (
<>
<p>Hello, World!!!!!</p>
<button onClick={clickButton}>button</button>
{click}
</>
);
}
export default App;
터미널에 npm start를 입력하여 앱을 실행 해줍니다.
npm start
앱이 정상적으로 실행되었습니다!✨
참고
https://velog.io/@thyoondev/CRA%EC%97%86%EC%9D%B4-React-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0Webpack5
https://velog.io/@xortm854/Typescript-React-Webpack-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95-4%ED%8E%B8-Webpack-%EC%84%A4%EC%A0%95%EC%9D%84-%ED%95%B4%EB%B3%B4%EC%9E%90
https://joshua1988.github.io/web-development/webpack/caching-strategy/
https://webpack.js.org/
잘못된 부분이 있으면 댓글로 남겨주시면 감사하겠습니다.👍