
처음에 해보려했던 이유는 모두가 한 번씩 해보길래 따라서 해봐야지.. 라는 생각에서 출발했습니다. 그러나 한 번 해보고 나서 이렇게 해보는게 여러가지 생각을 해보게 하는 트리거가 되게 끔 한다는 것을 알았습니다. 또한 무거운 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 서버가 열립니다.