[React] CRA 쓰지 않고 리액트 개발환경 구축 | webpack.config.js
리액트로 개발을 하는 사람이라면 직접 개발환경을 구축하기보다는 npx create-react-app my-app 이라는 명령어로 개발환경을 구축하는 경우가 많을 것 같다. 나는 리액트를 처음 시작할 때, 개발환경을 직접 구축할 수 있다는 생각을 하지 못했고 위의 명령어를 사용하는 것이 리액트를 사용하는 방법이라고만 알고 있었다. 그런데 리더님이 넘겨주신 자료를 보며, babel과 webpack을 포함하여 직접 리액트의 개발환경을 구축할 수 있다는 사실을 알게 되었다. CRA로 개발환경을 구축하면 편리하다는 장점이 있지만, 사용하지 않는 기능까지 포함하여 모듈의 크기가 크다는 단점을 꼽을 수 있다.
프론트엔드 스터디의 1주차 과제로 리액트 개발환경 구축하기를 하고 이를 계기로 webpack에 대한 궁금증이 커졌는데 유튜브에서 생활코딩 이고잉님의 webpack 관련하여 영상을 보니 왜 이렇게 쓰는 지 몰랐던 코드들이 조금씩 눈에 들어오기 시작했다.
https://www.youtube.com/playlist?list=PLuHgQVnccGMChcT9IKopFDoAIoTA-03DA
총 11개의 강의로 구성되어 있는데, 영상 하나당 길이가 길지 않아서 금방 다 볼 수 있었다.
그리고 웹팩의 공식문서는 감사하게도 한글로 번역을 해주신 분들이 있고, 잘 정리되어 있어서 한번 훑어봐야겠다!
리액트 개발환경을 구축할 때 리더님이 주신 노션문서를 보고서 그대로 따라서 쳤는데 node.js와 관련된 공부도 조금씩 해야하나 싶었다.
일단 webpack.config.js 파일을 생성한다.
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
require라는 함수를 여기서 처음 써봤는데, webpack을 사용하기 위해서 구성하는데 필요한 코드를 이렇게 맨 위에 적어준다.
리액트는 index.html의 body에서 하나의 div element 안에다가 블럭을 하나하나 조립하는 것이라고 생각한다. 그리고 이를 코드가 시작되는 지점, entry point가 index.js로 정하고 시작한다. 블럭, 그러니까 모듈을 import 해줬으면 export를 통해서 쓰는 걸 webpack을 통해서 구성해준다.
module.exports = {
entry: './src/index.tsx',
mode: 'development',
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
modules: [path.join(__dirname, 'src'), 'node_modules'] // Configure a absolute path
},
module: {
rules: [
{
test: /.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /.css$/,
use: ['style-loader', 'css-loader']
}
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new HtmlWebPackPlugin({
template: 'public/index.html',
filename: './index.html'
})
],
devServer: {
static: {
directory: path.join(__dirname, 'public')
},
compress: true,
host: 'localhost',
port: 3000
}
};
module.exports = {
entry: './src/index.tsx',
mode: 'development',
entry: module의 시작점(entry)의 속성을 적어주는데 기본값으로는 './src/index.js'지만, 리액트와 타입스크립트의 조합으로 쓸 것이기 때문에 './src/index/tsx'로 적어준다.
mode: 모드의 기본값은 'production'이고 'development'과 'none'이 더 있는데 웹팩에 내장된 환경별 최적화를 할 수 있다고 한다.
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
modules: [path.join(__dirname, 'src'), 'node_modules'] // Configure an absolute path
},
resolve: extensions에 넣어준 옵션의 확장자를 확인하고, 상대경로보다 절대경로로 하는 게 더 편해서 'src' 폴더 안에 있는 파일들은 절대경로로 사용할 수 있도록 옵션을 넣어주었다.
module: {
rules: [
{
test: /.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /.css$/,
use: ['style-loader', 'css-loader']
}
]
},
module: rules에 객체 배열을 넣어주었는데, 타입스크립트로 쓰여진 것을 자바스크립트로, 그리고 ES2015 자바스크립트의 문법으로 쓰여진 경우, 이를 모든 브라우저에서 잘 작동할 수 있도록 역시 바벨을 사용하게끔.
밑에 쓰여진 항목은 웹사이트의 코드를 네트워크가 받아올 때 css를 따로 받아오는 것이 아니라, 엔트리 포인트 안에서 스타일링까지 불러올 수 있도록 쓰여진 것. 이고잉님 강의를 들었을 때, uses 옵션의 순서도 중요하다고 언급하셨다. .css 확장자를 찾아서 css-loader로 불러오고 이를 style 태그 안에 넣는 작업을 style-loader가 한다고 한다.
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
output: 시작 지점이 있으면 끝나느 지점도 있어야 하는데, 이를 dist 이름의 디렉토리 안에 'bundle.js' 파일을 만든다.
plugins: [
new HtmlWebPackPlugin({
template: 'public/index.html',
filename: './index.html'
})
],
plugins: 웹팩의 기본 구성이고 로더가 할 수 없는 다른 작업을 수행할 목적으로 제공된다고 한다. 여기에서 HtmlWebPackPlugin은 script를 사용하여 'bundle.js' 파일을 포함하는 index.html 파일을 생성한다.
참조
- 프론트엔드 스터디 리더 탐정토끼님의 리액트 개발환경 구축 관련 문서 | https://dawn-bulb-f4b.notion.site/1-b2512c597f724fcd8f25475ad87878a6
- 생활코딩 이고잉님의 webpack 강의 모음 | https://www.youtube.com/playlist?list=PLuHgQVnccGMChcT9IKopFDoAIoTA-03DA
- 웹팩 한글문서 | https://webpack.kr/