처음에 해보려했던 이유는 모두가 한 번씩 해보길래 따라서 해봐야지.. 라는 생각에서 출발했습니다. 그러나 한 번 해보고 나서 이렇게 해보는게 여러가지 생각을 해보게 하는 트리거가 되게 끔 한다는 것을 알았습니다. 또한 무거운 CRA 보다는 가볍고 스스로가 원하는 대로 커스텀한 webpack 을 만들어서 배포와 개발을 진행할 수 있다는 것을 느꼈습니다.
위에서 말한 여러가지 생각들을 공유해보려합니다.
여러 프레임워크를 쓸때 우리도 모르게 이 삼총사들의 도움을 받고있습니다. 그러나 이들은 프레임 워크를 쓰는 사용자 입장에서는 알수없도록 물 밑에서 작동하고 있기때문에 react 만 써보신 분이라면 각각이 어떤 역할을 하는지 알아채기 어려울 것입니다.
webpack
모듈 번들러
라고 설명이 되어있습니다. 우리는 성격이 비슷한 기능들을 하나의 의미 있는 파일로 관리하는 단위
를 모듈이라고 합니다. 또, bundle 이라는 뜻은 묶음
이라는 의미를 가지고 있습니다. 풀어서 설명하면, 파일들을 하나로 병합하거나 묶어주는 녀석이라는 뜻을 유추해 볼 수 있겠네요!웹 애플리케이션을 구성하는 자원(HTML, CSS, Javscript, Images 등)을 모두 각각의 모듈로 보고 이를 조합해서 병합된 하나의 결과물을 만드는 도구
라고 정의하고 있습니다.빌드, 번들링, 변환 이 세 단어 모두 같은 의미입니다.
babel
babel은 webpack 과 다르게 트랜스파일러
입니다.
트랜스 파일러는 말그대로 트랜스(Trans)
+ piler
변환 해주는 도구입니다.
브라우져 마다 지원하는 js의 버젼이 다르기 때문에 JSX 나 ES6+ 로 작성된 JS 코드들을 ES5코드로 변환 하는 과정이 필요합니다. 그 역할을 해주는 것이 트랜스파일러
이며 그 중에 하나가 babel 입니다.
loader
loader 의 역할은 json 과 js 밖에 해석하지 못하는 webpack 을 위해서 css 나 HTML 등 다른 자원들을 변환 할 수 있도록 하는 속성입니다.
test
: 로더를 적용할 파일 유형 (일반적으로 정규 표현식 사용)
use
: 해당 파일에 적용할 로더의 이름
babel-loader
dependencies와 devDependencies의 차이점은 실제 상품에서 사용할 패키지와 개발용 패키지의 차이이다.
즉, 개발 시 필요한 라이브러리들은 devDependencies에 적어주고, (개발자가 필요한것)
진짜 기술스펙으로 사용되어야할 라이브러리들은 dependencies에 설치해준다.
즉, 어떤 Library가 프로젝트의 컴파일(빌드) 타임에 필요하면, devDependencies에 넣고, 런타임에도 계속 쓰이는 것이면 dependencies에 넣는다.
mkdir {프로젝트 이름}
cd {프로젝트 이름}
npm init -y // package.json 생성
npm install --save -D webpack webpack-dev-server webpack-cli html-webpack-plugin// webpack
npm install --save -D babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript //babel
npm install --save react react-dom //react
npm install --save @types/react @types/react-dom //typescript
tsc --init // 타입스크립트 전역으로 설치시
{
"compilerOptions": {
"outDir": "./dist",
"target": "es5",
"module": "esnext",
"jsx": "react",
"noImplicitAny": true,
"allowSyntheticDefaultImports": true,
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
},
"include": [
"src"
]
}
module.exports = {
presets: ['@babel/preset-react', '@babel/preset-env', '@babel/preset-typescript'],
};
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const mode = process.env.NODE_ENV || 'development';
module.exports = {
mode,
devServer: {
historyApiFallback: true,
inline: true,
port: 3000,
hot: true,
publicPath: '/',
},
entry: {
app: path.join(__dirname, 'index.tsx'),
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
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: './public/index.html',
}),
new webpack.HotModuleReplacementPlugin(),
],
};
webpack-dev-server
: 웹팩 데브 서버로 빌드한 결과물이 파일 탐색기에서 보이진 않지만 정상적으로 애플리케이션에 로딩되어 돌아도록 합니다. CRA 에서 start 를 입력해도 번들된 파일이 생성되지 않는 이유가 이녀석 때문이죠.
devServer: {
historyApiFallback: true,
inline: true,
port: 3000,
hot: true,
publicPath: '/',
},
위의 조건들을 변경하면서 dev 서버 환경을 바꿀 수 있습니다.
HtmlWebpackPlugin
: index.html 템플릿을 기반으로 빌드 결과물을 추가해 주기위한 plug-in 입니다.
entry
: webpack 이 코드를 번들링하기 위해서 알아야하는 복잡하게 얽힌 코드들의 맨 처음 시작점
output
: 번들링한 결과물 파일이름과 위치 설정
module
: 다양한 로더들을 불러올수 있는 곳입니다. test
는 로더를 적용할 파일 유형 (일반적으로 정규 표현식 사용) 을 적고 use
에는 해당 파일에 적용할 로더의 이름을 적습니다.
위의 webpack 의 엔트리 설정해준 것에 따라서 파일을 생성하고 만들어줍니다.
index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './src/App';
ReactDOM.render(
<React.StrictMode>
<div>요호</div>
<App/>
</React.StrictMode>,
document.getElementById('root')
);
App.tsx
import React from 'react'
function App() {
return (
<div>
어~
</div>
)
}
export default App
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>
</body>
</html>
index.html
에는 반드시 root
라는 id
값을 가진 div
를 생성해 줘야 한다.
"scripts": {
"dev": "webpack server --mode development --open --hot",
"build": "webpack --mode production",
"prestart": "cross-env NODE_ENV=production npm run build",
"start": "webpack --mode development"
},
보통 nodeJS 에서 NODE_ENV 의 env 변수를 조작해서 dev 모드와 production 를 구분하게 되는데 윈도우는 scripts 명령어로 env 변수를 바꿀수 없기때문에 설치하는 모듈이다.
npm run dev
를 실행하면 localhost:3000
에서 dev 서버가 열립니다.