하나의 게시글에 작성하고 싶었으나, 내용이 너무 길어져 1편에 이어서 작성한다.
npm i -D typescript @types/react @types/react-dom
- typescript : 타입스크립트
- @types/react : React 라이브러리에 대한 타입 선언 파일
- @types/react-dom : React DOM 라이브러리에 대한 타입 선언 파일
타입 선언 파일(d.ts)
타입스크립트 코드에서 타입 추론을 도와주는 파일이다.
존재하는 대부분의 라이브러리는 자바스크립트로 작성되었고, 타입스크립트는 해당 코드에서 변수, 함수의 타입을 알 수 없다. 그래서d.ts
확장자를 가지는 선언 파일을 통해 알려주어야 한다.
npm i -D @babel/preset-typescript
- @babel/preset-typescript : 타입스크립트를 사용할 때 필요한 플러그인들의 집합이다.
1편에서 웹팩 설정을 할 때webpack.config.js
파일 하나만 사용했다. mode:development
를 사용했던 것을 기억할 것이다. 이번에는 webpack에서 production
모드와 development
모드를 분리하여 각각 세팅한 뒤, webpack.common.js
파일로 합칠 것이다.
npm i -D webpack-merge
- webpack-merge : 웹팩 설정 파일을 병합해주는 라이브러리이다.
npm i -D ts-loader
- ts-loader : 웹팩에서 타입스크립트 코드를 처리하기 위한 로더이다.
1편에 이어 여기까지 진행했다면 package.json
이 다음과 같을 것이다.
{
"name": "frontend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack serve --mode development --open --hot",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.2"
},
"devDependencies": {
"@babel/core": "^7.22.9",
"@babel/preset-env": "^7.22.9",
"@babel/preset-react": "^7.22.5",
"@babel/preset-typescript": "^7.22.5",
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"babel-loader": "^9.1.3",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.8.1",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.3",
"style-loader": "^3.3.3",
"ts-loader": "^9.4.4",
"typescript": "^5.1.6",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-merge": "^5.9.0"
}
}
tsc --init
명령어를 통해 타입스크립트 설정 파일인 tsconfig.json
을 초기화 하자.
tsc
tsc는 타입스크립트 컴파일러의 명령어이다.
tsc
명령어를 통해 프로젝트 내의 내의 타입스크립트 파일들은tsconfig.json
에 설정된 대로 자바스크립트 파일로 변환된다.
명령어를 입력했다면, 수많은 주석으로 이루어진 tsconfig.json
이 프로젝트 최상위 디렉터리에 생성되었을 것이다.
tsconfig.json
은 자신이 원하는 스타일로 컴파일러의 옵션을 설정 할 수 있다.
각각의 옵션에 관한 내용은 아직 잘 모르니까, 여기를 참고해서 공부해야겠다.
기본 코드는 지우고 다음 코드를 tsconfig.json
에 붙여넣자
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["dom", "ES2015", "ES2016", "ES2017", "ES2018", "ES2019", "ES2020"],
"allowJs": true,
"jsx": "react-jsx", //중요
"sourceMap": true,
"outDir": "./dist", //중요
"isolatedModules": true,
"strict": true,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"@components/*": ["components/*"],
"@pages/*": ["pages/*"]
},
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
}
}
- jsx : 타입스크립트가 jsx문법인 React 컴포넌트를 어떻게 처리할 지 결정한다.
jsx : "preserve"
옵션은 컴파일러에게 jsx문법을 변환하지 말라는 옵션이다. 이 옵션때문에 30분동안 문제점을 찾았다..- outDir : 컴파일된 자바스크립트 파일이 출력되는 디렉터리
@babel/preset-typescript
라이브러리를 추가로 설치했기 때문에 babel.config.js
를 다음 코드로 변경해준다.
module.exports = {
presets: [
"@babel/preset-react",
"@babel/preset-env",
"@babel/preset-typescript",
],
};
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const path = require("path");
module.exports = {
entry: "./src/index.tsx", //변경되었음을 눈치 챌 것
resolve: {
extensions: [".js", ".jsx", ".ts", ".tsx"],
},
module: {
rules: [
{
test: /\.tsx?$/,
use: ["babel-loader", "ts-loader"],
},
{
test: /\.(png|jpe?g|gif)$/,
use: [
{
loader: "file-loader",
},
],
},
],
},
output: {
path: path.join(__dirname, "/dist"),
filename: "bundle.js",
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
new CleanWebpackPlugin(),
],
};
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "development",
devtool: "eval",
devServer: {
historyApiFallback: true,
port: 3000,
hot: true,
},
});
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "production",
devtool: "hidden-source-map",
});
추가된 옵션은 다음과 같다.
- resolve : 웹팩에서 모듈을 해석하는 규칙으로, 어떤 확장자를 처리할 지 지정한다.
- devtool : 웹팩이 생성하는 소스맵을 제어하는 옵션이다. 소스맵이란 웹팩 번들링 결과물과 원본 소스간의 매핑 정보를 제공한다.
eval
옵션은 소스맵을 빠르게 생성하지만 용량이 크다.hidden-source-map
옵션은 가장 느리지만 외부에서 리액트 구조를 확인할 수 없으므로 배포 단계에서 사용된다.
package.json
의 스크립트를 다음과 같이 설정한다.
...
"scripts": {
"dev": "webpack-dev-server --config webpack.dev.js --open --hot",
"build": "webpack --config webpack.prod.js",
"start": "webpack --config webpack.dev.js"
},
...
npm run dev
명령어를 통해 웹팩 개발 서버를 실행 가능하다.
src폴더 내부의 App.jsx
-> App.tsx
, index.jsx
->index.tsx
로 변경해준다.
그리고 타입스크립트가 동작하는지 궁금하므로, App.tsx
를 다음처럼 변경했다.
import React from "react";
const add = (a: number, b: number): number => a + b;
const App = () => {
return <div className="container">React!</div>;
};
export default App;
npm run dev
명령어를 실행하면 정상적으로 동작한다!
Create-React-App의 소중함을 깨달았다. 웹팩을 이용하여 직접 개발 환경을 설정하고, 글을 쓰면서 좀 더 이해하는 계기가 되었지만 여전히 완벽히 이해할려면 멀었다고 생각한다. 이것저것 도전해보자~