본문 바로가기

③ 프레임워크·라이브러리/typescript

typescript + react + webpack setting 하기 (CRA❌)

728x90

1.프로젝트 폴더 생성 및 초기화

 

mkdir my-typescript
cd ./my-typescript
npm init -y

결과 : my-typescript 폴더 안에 package.json 파일 생성

 

 

 

2. 리액트 설치

 

npm install react react-dom

or

yarn add react react-dom

 

react : 리액트 라이브러리

react-dom : 리액트 엘리멘트 렌더링 라이브러리

 

 

3. 타입스크립트 설치

 

npm i -D typescript @types/react @types/react-dom

 

typescript : 타입스크립트 라이브러리

@types/react : 리액트를 위한 타입 정의 파일

@types/resct-dom : 리엑트 돔을 위한 타입 정의 파일

 

 

 

4. 웹팩 설치

 

npm install -D webpack webpack-cli webpack-dev-server

 

webpack : 개발자의 코드와 소스를 하나로 합쳐주는 번들러

webpack-cli : 웹팩의 커맨드를 이용해 빌드나 실행을 하기 위함

webpack-dev-server : 핫로딩 사용하기 위해 설치

 

 

 

5. 웹팩 로더와 플러그인 설치

 

npm install -D css-loader sass-loader style-loader url-loader ts-loader

 

로더 : 모듈(js, css, png 등)을 자바스크립트 코드 안으로 가져온다.

css-loader : css 확장자 파일을 찾으면 안의 내용을 처리해서 자바스크립트 코드 안으로 가져옴

sass-loader : sass,scss 확장자 파일 안의 내용을 css로 변환

style-loader : css를 html의 style태그를 생성해 넣음

url-loader: 파일 내용을 모듈에 문자열 형태로 추가

ts-loader : .ts 나 .tsx 로 끝나는 파일들을 처리하여 번들링

 

 

npm install -D html-webpack-plugin mini-css-extract-plugin

 

 

html-webpack-plugin : html 파일에 번들된 js 파일을 자동 연결해서 생성

mini-css-extract-plugin : css 파일을 별도의 파일로 추출

 

 

 

6. 웹팩 설정 webpack.config.js

 

const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const path = require('path');

module.exports = {
    entry: {
    	index: path.resolve('./index.tsx');
    }, 
    output: {
        path: path.resolve('./build'),
        filename: '[name].[contentshash].js',
        publicPath: '/',
        clean: true,
        assetModuleFilename: '[name][ext]'
    },
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './src/components'),
        },
        extensions: [".ts", ".tsx", ".js", ".jsx"]  
    },
    devtool: 'source-map',
    module: {
        rules: [
            {
                test: /\.ts(x?)$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: "ts-loader"
                    }
                ]
            },
            {
                enforce: "pre",
                test: /\.js$/,
                loader: "source-map-loader"
            },
            {
                test: /\.(scss|css)/,
                exclude: /node_modules/,
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
            {
                test: /\.(ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|otf)(\?v=[0-9]\.[0-9])?$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            name: "[hash].[ext]",
                            limit: 10000
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./public/index.html",
            templateParameters: {
                env: process.env.NODE_ENV === "development" ? "(개발용) " : "" 
            }
        }),
        new webpack.BannerPlugin({
            banner: `Build Time: ${new Date().toLocaleString()}`
        })
    ],
    devServer: {
    	static: {
        	directory: path.resolve(__dirname, 'build')
        },
        open: true,
        hot: true,
        compress: true,
        port: 5500,
        historyApiFallback: true
    }
}

 

entry : 웹팩이 번들링을 하기 위해 진입하는 입구, 객체로 할 경우 key 가 output 의 [name].js 의 name에 들어감

contentshash: 번들링 결과물에 고유 해시를 부여해서 브라우저가 해당 파일을 새로 불러올 수 있게 함

output : 번들링 결과물의 경로와 파일명 지정

output.publicPath : 번들링 과정에서 내부에서 사용된 url들의 prefix 역할, webpack-dev-server가 hdd가 아닌 ram에 있는 번들된 소스를 브라우저에게 주게 하는 역할

output.clean: 기존 파일을 삭제해 정리한 후, 다시 번들링 결과물을 경로에 넣는 옵션

output.assetModuleFilename: asset용 번들링된 결과물의 파일명 지정

resolve : module을 해석하는 방식 설정

alias : 특정 모듈의 별칭을 정할 수 있음

extentions : 확장자를 순서대로 해석. 여러 파일에서 이름이 동일하지만 다른 확장자를 가진 경우, webpack은 배열의 앞에서부터 파일을 해석하고 남은 것은 해석하지 않음.

module : loader를 넣을 객체

rule : loader를 객체로 가진 배열

test : 어떤 파일을 loader로 적용할 지 정규식으로 결정

exclude : loader에서 제외할 파일이나 폴더

use : 사용할 loader의 이름과 옵션

devtool : 번들링된 결과물에서 에러가 났을 때, 원본 소스코드에서 해당 부분을 찾을 수 있게 연결해주는 역할

plugin : 번들링 결과물에 추가하고 싶은 일이 있을 때 사용

htmlWebpackPlugin 의 template : 빌드 결과물에 사용할 index.html 의 템플릿 경로

htmlWebpackPlugin 의 templateParameters : index.html에서 사용할 변수

BannerPlugin : 빌드결과물에 배너를 생성

devServer.static.directory: 데브 서버가 호스팅할 파일의 경로

devServer.open : 서버가 올라가면, 브라우저를 열지 여부

devServer.hot: 파일 내 변경이 생기면 자동으로 빌드해 리로드할지 여부

devServer.compress: gzip 으로 압축 여부

devServer.port : 사용할 포트

devServer.historyApiFallBack : 404대신 index.html을 보여줄지 여부

 

 

 

7. 타입스크립트 설정 tsconfig.js

 

{
  "compilerOptions": {
  	"target": "ES2016",
    "module": "CommonJS",
    "noImplicitAny": true,
    "jsx": "react"
  }
}

tsconfig.js : 프로젝트의 최상위 루트에 존재하며, 프로젝트를 컴파일하는데 필요한 옵션을 제공하는 파일

target : typescript 파일을 원하는 target 버전의 javascript로 변경해줌

module : javascript 파일 간의 import 구문을 해석할 모듈 언어 설정. 

noImplicitAny : any 타입이 개발자 의도와 다르게 발생했을 때 경고

jsx : jsx 파일을 어떻게 컴파일할 것인지 결정

 

 

 

8. 최상위 인덱스 파일 index.tsx

 

import * as React from 'react';
import * as ReactDOM from 'react-dom/client';

import { Hello } from './src/Hello';

const container = document.getElementById('example')! as HTMLElement;
const root = ReactDOM.createRoot(container);
root.render(<Hello compiler='TypsScript' framework='React' />);

 

 

 

9. hello world 를 보기 위해 파일 하나 더 추가 src/Hello.tsx

 

import * as React from "react";

export interface HelloProps { compiler: string; framework: string; }

export const Hello = (props: HelloProps) => <h1>Hello from {props.compiler} and {props.framework}!</h1>;

 

 

 

10. 실행하기 위해 스크립트 추가 package.json

 

 "scripts": {
    "start": "NODE_ENV=development webpack-dev-server --mode development",
    "build": "webpack --mode production"
  },

 

 

11. 정적 파일 추가 public/index.html

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= htmlWebpackPlugin.options.templatePramaeters.env =></title>
</head>
<body>
    <div id="app"></div>
</body>
</html>

 

 

728x90