cra 없이 webpack 설정하는 법은 시중에 많이 나와있음
참고한 블로그 추가함
https://webpack.kr/concepts/ <= 진심 잘 나와 있어서 깜짝 놀람
하고 싶은 거
1. react + ts + scss
2. webpack으로 development / product 서버 나누기
3. 코드 스플리팅 사용 <= 근데 처음부터 의도한 건 아니었음
만났던 오류
1. 간단하게 설정하고 서버 킬 때 나온 메세지 (실행 불가 상태는 x)
번들 파일 무거우니까 코드 스플리팅하라는 경고 메세지
근데 이제 서버 켰는데 왜 무거운건지... 이미 압축되어서 가벼워졌는데...
암튼 하라니까 일단 설정함
코드 스플리팅으로 가져오게 lazy, suspense 추가
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Suspense } from 'react';
const LazyRouter = React.lazy(() => import('./Router'));
const App: React.FC = () => (
<Suspense fallback={<div>Loading...</div>}>
<LazyRouter />
</Suspense>
);
const root = createRoot(document.getElementById('root'));
root.render(<App />);
tsconfig 추가
// tsconfig.json
....
"esModuleInterop": true,
"moduleResolution": "node"
moduleResolution: 'node'
TypeScript가 모듈을 해석하는 방식이 Node.js의 모듈 해석 방식과 동일하게 만듭니다. 이는 다음과 같은 이유로 중요합니다:
- 동적 임포트: 코드 스플리팅을 위해 사용되는 동적 임포트(import())는 ES 모듈 시스템의 일부입니다. Node.js의 모듈 해석 방식을 따르면 TypeScript가 이러한 동적 임포트를 제대로 해석할 수 있습니다.
- 모듈 경로 확인: 동적 임포트를 사용할 때 모듈 경로를 올바르게 확인하는 것이 중요합니다. Node.js 방식의 모듈 해석을 따름으로써, TypeScript는 node_modules 디렉토리 및 프로젝트의 모듈을 올바르게 찾을 수 있습니다.
esModuleInterop: true
TypeScript가 CommonJS 모듈과 ES 모듈 간의 상호 운용성을 개선하는 데 도움이 됩니다
- 호환성: 많은 Node.js 모듈이 CommonJS 형식으로 작성되어 있습니다. esModuleInterop 옵션을 사용하면 이러한 모듈을 ES 모듈처럼 임포트할 수 있으며, 이는 코드 스플리팅 시 동적 임포트 구문과의 호환성을 높입니다.
- 간결한 구문: esModuleInterop 옵션이 활성화되면, CommonJS 모듈을 임포트할 때 더 간결한 ES 모듈 구문(import defaultExport from 'module')을 사용할 수 있습니다. 이는 코드 스플리팅 시 동적 임포트 구문을 사용할 때에도 동일하게 적용됩니다.
코드 스플리팅은 컴포넌트를 하나씩 가져오는 게 아니라
코드를 잘게 나누어서 가져오는 거임
그러다보니까 노드 가져오는 설정을 좀 더 딴딴히 해야했던 듯
2. dev, prod, common.js 나누다가 알게된 거
스크립트 파일
"test": "jest",
"dev": "webpack-dev-server --config webpack.dev.js", <= 개발용 서버
"build": "webpack --config webpack.prod.js", <= 프로덕트용 빌드
"serve": "node server.js" <= 프로덕트용 빌드 후 로컬 확인용
개발서버랑 프로덕트 서버랑 똑같은 기본 구조는 webpack.common.js에 넣음
// webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
},
module: {
rules: [
// 바벨용 rules
{
test: /\.(js|jsx|ts|tsx)$/, // 해당 파일명으로 끝나면 babel-loader가 처리
exclude: /node_modules/, // node_modules는 대상에서 제외
loader: 'babel-loader', // 바벨 로더 추가
},
// CSS 처리 위한 설정
{
test: /\.scss$/, // SCSS 파일 처리
use: ['style-loader', 'css-loader', 'sass-loader'], // 스타일, CSS, Sass 로더 사용
},
],
},
// 다른 목적으로 플러그인을 여러 번 사용하도록 설정할 수 있으므로 new 연산자로 호출하여 플러그인의 인스턴스를 만들어야 합니다.
plugins: [
new HtmlWebpackPlugin({
template: './index.html', // index.html 템플릿 설정
}),
],
resolve: {
// resolve: import 할 때 확장자를 생략
extensions: ['.jsx', '.js', '.tsx', '.ts'],
},
optimization: {
minimize: true, // 번들 최소화 설정
splitChunks: {
minSize: 10000,
maxSize: 250000,
},
},
};
빌드 환경은 js 파일만 인식하기 때문에 css 규칙 넣어줌
이때 바벨용 로더랑 css 로더 분리해줌... 하고 싶어서 한게 아니라 그게 규칙이라고 함
sass-loader: SCSS 파일을 CSS로 변환합니다.
css-loader: 변환된 CSS를 JavaScript 모듈로 해석합니다.
style-loader: JavaScript 모듈로 해석된 CSS를 <style> 태그로 삽입하여 브라우저에서 스타일을 적용합니다.
그리고 dev 파일
//dev
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
module.exports = merge(common, {
mode: 'development',
devServer: {
static: {
directory: path.join(__dirname, 'dist'),
},
compress: true, // Gzip 압축을 활성화
hot: true, // 핫 모듈 교체 활성화
port: 9000,
},
});
webpack-dev-server 모듈 받으면 쓸 수 있는 devServer를 열고 싶었던 이유는
빌드시간 오래 걸리는 거 + 저장할 때 바로바로 새로고침 이유로 핫로딩을 원했음 <= 빌드 파일을 정적으로 만드는 게 아니라 메모리에 두고 사용해서 빠름
장점들 밑에 정리함
- 핫 모듈 교체 (HMR, Hot Module Replacement):
- HMR이 없는 경우: 코드 변경 시 페이지 전체를 새로고침해야 합니다. 이는 개발 속도를 느리게 하고, 상태가 초기화될 수 있습니다.
- HMR이 있는 경우: 코드 변경 시 변경된 모듈만 교체되므로, 페이지 전체를 새로고침하지 않아도 됩니다. 이는 빠른 피드백과 더 나은 개발 경험을 제공합니다.
- 실시간 리로딩 (Live Reloading):
- Live Reloading이 없는 경우: 파일을 수동으로 새로고침해야 합니다.
- Live Reloading이 있는 경우: 파일이 변경될 때 자동으로 페이지를 새로고침합니다.
- Gzip 압축:
- 압축 없는 경우: 파일이 압축되지 않고 전송되므로, 파일 크기가 크다면 로딩 속도가 느려질 수 있습니다.
- 압축 있는 경우: 파일이 Gzip 압축되어 전송되므로, 네트워크 전송량이 줄어들고 로딩 속도가 빨라집니다.
그리고 gzip 설정의 단점도 일단 가져옴
웹팩에서 Gzip 압축을 적용할 때, 일반적으로 텍스트 기반 파일(예: JavaScript, HTML, CSS 등)을 압축 대상으로 삼습니다
이미 압축된 파일 형식(예: 이미지, 비디오 등)은 추가적인 압축 효과가 적기 때문에 대상에서 제외하는 것이 좋습니다.
이를 위해 웹팩에서 compression-webpack-plugin을 사용할 수 있습니다.
- 이미지 파일 제외 이유
이미지 파일(예: JPEG, PNG 등)은 이미 압축된 형식이기 때문에
추가로 Gzip 압축을 적용해도 크기가 거의 줄어들지 않거나 오히려 더 커질 수 있습니다.
따라서 이미지 파일은 Gzip 압축 대상으로 지정하지 않는 것이 일반적입니다.
plugins: [
new CompressionPlugin({
test: /\.(js|css|html)$/, // 압축할 파일 형식 지정
filename: '[path][base].gz', // 출력 파일 이름 설정
algorithm: 'gzip', // 압축 알고리즘 설정
threshold: 10240, // 파일 크기가 10KB 이상일 때만 압축
minRatio: 0.8, // 최소 압축 비율 설정
}),
],
이런 설정도 가능하다고 함
정적으로 쓰는 이미지 엄청 무거우면 한번 해볼 법한...
아무튼 devServer 쓰면 빌드 파일 메모리에 두고 쓰는 건데 굳이
static: {
directory: path.join(__dirname, 'dist'),
},
이 설정이 필요할까?
- 정적 파일 제공: 프로젝트에는 JavaScript 번들 외에도 이미지, 폰트, HTML 파일 등 정적 파일이 있을 수 있습니다. 이러한 파일들을 static 옵션을 통해 제공할 수 있습니다.
- 개발 편의성: 개발 중에 직접적으로 디스크에 저장된 파일을 확인해야 하는 경우가 있을 수 있습니다. 이때, static 디렉토리를 설정해 두면 편리하게 접근할 수 있습니다.
- 정적 파일 서빙 테스트: 프로덕션 환경에서의 파일 서빙을 테스트하고 싶을 때, static 옵션을 통해 실제로 파일이 어떻게 제공되는지 확인할 수 있습니다.
라고 함
static 설정이 있다고 해서 HMR이 작동하지 않는 것은 아니라고함
그러니까
my-project/
├── public/
│ ├── images/
│ │ └── logo.png
│ └── index.html
├── src/
│ ├── index.tsx
│ └── App.tsx
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
개발 서버는 빌드 파일만 바라보고 있기 때문에
핫로딩을 쓴다면 이미지를 못 찾음
이럴 때 static설정으로 올려줘서 이미지 찾게 해준다는 거 같음
3. 스크립트 파일 이유
"test": "jest",
"dev": "webpack-dev-server --config webpack.dev.js", <= 개발용 서버
"build": "webpack --config webpack.prod.js", <= 프로덕트용 빌드
"serve": "node server.js" <= 프로덕트용 빌드 후 로컬 확인용
빌드 확인하려고... 따로 serve 넣음
다른 사람들 이렇게 안 쓰는 거 같긴한데;;;;
그래도 배포 전에 확인하는 게 좋은 거 아닌가...
그래서 프로덕트용 빌드 후에 빌드 파일을 실행시킬 수 있는 스크립트를 만듦
/** ==================================
프로덕션 빌드 확인용, npm run serve
================================== **/
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;
// 정적 파일 제공
app.use(express.static(path.join(__dirname, 'dist')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});
app.listen(port, () => {
console.log(`Server is running at http://localhost:${port}`);
});
express로 서버 열어서 실행하도록...
개발 때만 써서 npm install express --save-dev 처리함
사실 jest 연습하려고 판 레포인데... ㅠ
다음 주말이나... 평일에 추가할 예정
https://github.com/Joeunji0119/testCode
'TIL' 카테고리의 다른 글
jest (0) | 2024.06.26 |
---|---|
이미지 public에 넣기 vs src에 넣고 import하기 ++ 이미지 suspense로 감싸서 가져오기 (0) | 2024.06.24 |
이산수학 필기노트 (0) | 2024.06.10 |
컴퓨터의 이해 필기노트 (0) | 2024.06.02 |
리액트 기초 (0) | 2024.04.25 |
댓글