CRA 분석
CRA는 리액트 개발환경을 명령어 한 줄로 만들어주는 편안한 도구이다. 그러나 config 설정을 변경하기 어렵고, 다양한 개발환경을 커버하기 위해서 좀 무거운 감이 있다.
webpack.config.js
target: ['browserlist']
target으로 webpack이 어떤 환경을 대상으로 할지 정할 수 있다. node
이면 node 환경, electron
이면 electron 환경, browserlist
는 browserlist-config
에 설정된 환경 정보를 가져와서 타게팅한다. browserlist-config
는 package.json
의 browserslist
속성에 있다.
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
>0.2%
: 브라우저 버전 중 전세계 브라우저 사용률이 0.2%가 넘는 애들만 타겟으로 지정한다.
not dead
: dead
는 24개월간 공식 업데이트가 없는 애들을 뜻한다. ex) IE 11
, Samsung 4
등, not dead
는 걔네들을 제외한 애들만 타겟으로 지정한다.
not op_mini all
: opera_mini라는 브라우저를 타겟에서 제외한다.
last 1 ㅁㅁ version
: 해당 ㅁㅁ 브라우저의 최근 1개 버전만 지원한다.
stats: 'errors-warnings'
stats
: 번들 정보 표시 제어, 에러와 경고를 출력
devtool
배포 환경이며 shouldUseSourceMap
이 true이면 source-map
사용
개발 환경이면 cheap-module-source-map
사용
sourcemap
은 배포용으로 빌드한 파일과 원본파일을 서로 연결
배포용 파일의 특정 부분이 원본 소스의 어떤 부분인지 확인할 수 있다. (디버깅 가능하게 해줌)
output
번들 결과물을 어떻게 나타낼지 보여준다. 경로, 이름 등등
output: {
// The build folder.
path: paths.appBuild,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
assetModuleFilename: 'static/media/[name].[hash][ext]',
// webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath: paths.publicUrlOrPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
cache
생성된 webpack 모듈 및 청크를 캐시하여 빌드 속도를 개선할 수 있다.
cache: {
type: 'filesystem',
version: createEnvironmentHash(env.raw),
cacheDirectory: paths.appWebpackCache,
store: 'pack',
buildDependencies: {
defaultWebpack: ['webpack/lib/'],
config: [__filename],
tsconfig: [paths.appTsConfig, paths.appJsConfig].filter(f =>
fs.existsSync(f)
),
},
},
캐시 디렉토리인 node_modules
의 .cache
를 보면, eslintcache
와 babel-loader
로 변환된 코드들이 있다.
store : 'pack'
, store(파일 시스템에 데이터를 언제 저장할지)가 'pack' 모든 캐시된 항목에 대해 컴파일러가 사용되지 않는 상태일 때 데이터 저장
buildDependencies
: 이 디펜던시를 사용해서 파일 시스템 캐시를 무효화한다. 기본적으로 webpack과 로더가 포함 , tsconfig
는 지금 리액트가 ts
or js
기반인지 자동으로 config파일 찾아서 설정
optimization
최적화 config
minimizer
-어떤 최적화 플러그인들 사용할지 (TerserPlugin
, CssMinimizerPlugin
), minimize
- 어떤 모드일때 최소화할지 선언
Loaders
source-map-loader: 모든 js 엔트리에서 소스맵을 추출
oneof로 묶임 (요구사항에 맞는 loader를 찾으면 걔를 줌, 아무 로더도 match되지 않으면 file-loader)
@svgr/webpack: svg를 react로 임포트
url-loader: 파일을 base64 URI로 변환
file-loader: 파일 임포트를 url로 변환, output directory에 파일들 저장
babel-loader: 바벨 사용하여 코드 변환
getStyleLoaders (함수, 조건에 맞는 styleloader를 리턴)
style-loader: css를 dom에 주입
css-loader: css 읽어서 js에서 사용가능하게 변환
postcss-loader: postcss 읽어서 js에서 사용가능하게 변환
resolve-url-loader: scss, sass 읽어서 js에서 사용가능하게 변환
Plugins
HtmlWebpackPlugin: template html 파일 생성
InlineChunkHtmlPlugin (배포환경만): inline script들 chunk로 html에 주입
InterpolateHtmlPlugin: HtmlWebpackPlugin과 같이 써야함, template html에서
%NODE_ENV%
사용 가능하게 해줌ModuleNotFoundPlugin: module not found 에러에 대해 필요한 context를 제공(ex: 요구 자원)
webpack.DefinePlugin(env.stringified): 환경변수 js 코드에서 이용가능하게 해줌 ex)
process.env.NODE_ENV === 'production'
ReactRefreshWebpackPlugin (개발환경만): 리액트 핫 리로딩
CaseSensitivePathsPlugin (개발환경만): 대소문자 다르게 혹은 같게 처리하는 파일 시스템에서도 동일 동작 시키도록 file path의 대소문자가 정확히 일치하는지 체크
MiniCssExtractPlugin (배포환경만): css파일을 별도파일로 추출
WebpackManifestPlugin: 애셋의 매니페스트 파일 생성(해시값으로 파일명 못알아볼때 참고하기 좋다)
webpack.IgnorePlugin: 엄청 큰 번들인 Moment.js를 최적화(특정 locale만 포함하도록) - Moment.js 사용안하면 쓸 필요 X
WorkBoxWebpackPlugin (개발환경만)
- GenerateSW: 서비스워커 생성
- InjectManifest: 서비스워커 파일 내에 주입될 precache 할 asset 들의 list 를 생성
ForkTsCheckerWebpackPlugin (TS 사용시): TS 타입검사 (tsc 실행시 코드가 많으면 타입검사가 느리다. 이 플러그인으로 타입검사만 따로, 좀 늦게 실행할 수 있다)
ESLintPlugin (disableESLintPlugin === false): 코드내 문제점들을
eslint
를 사용해 찾고 고친다
jest config
jest 환경 설정
babelTransform.js
: babel-jest 플러그인 사용 설정, jest 사용시 babel로 js 코드를 변환하게 한다.
cssTransform.js
: style imports를 빈 객체로 변환
fileTransform.js
: file imports를 filenames로 변환
babel config
package.json
의 babel
필드에 설정이 있다.
preset으로 react-app을 설정, jsx -> createElement함수를 이용한 코드로 변환
env.js
환경변수 관련 설정
.env 파일들의 환경변수를 사용가능하게 해준다.
getHttpsConfig.js
Https config 정보를 불러오는 함수
modules.js
compiler option 기준으로 모듈path, webpack, jest aliases, hasTsConfig를 리턴
paths.js
PUBLIC_URL
or homepage
필드를 기준으로 절대경로를 계산해서 리턴.
webpackDevServer.config.js
compress: true
gzip 압축static: {directory: paths.appPublic, publicPath: [paths.publicUrlOrPath], watch: {ignored: ignoredFiles(paths.appSrc)}
, public 디렉토리에 있는 static 파일들을 devserver에서 사용가능하게 한다.client: webSocketURL: {}, overlay: {errors: true, warnings: false}
websocket 커스텀이 가능하고, warning 말고 error만 콘솔에 띄운다devMiddleware: {publicPath: ~}
publicPath 설정onBeforeSetupMiddleware: ...
evalSourceMapMiddelware 사용, 프록시 사용시 프록시 셋업onAfterSetupMiddleware: ...
redirect 설정, service worker 사용 설정
scripts
build.js
1. config 생성
2. 빌드 디렉토리의 현재 파일 사이즈를 읽는다. 추후 파일사이즈가 얼마나 바뀔지 보여주기 위해서
3. 빌드 디렉토리를 비운다. -> 퍼블릭 폴더의 파일들을 복사해서 가져온다. -> 웹팩 빌드를 시작
4. 빌드 결과(파일 사이즈 등) 출력
start.js
1. config 생성
2. webpack 컴파일러 생성
3. proxy config 불러오기
4. 컴파일러에 의해 생성된 webpack 결과물 devserver에 실행
test.js
1. jest config와 transform 정보들 불러온다.
2. jest 실행
내 CRA와 비교
내 CRA는 현재 devserver
를 돌린 상태에서 새 의존성 추가시 해당 모듈을 찾지 못하는 오류가 있다. 다시 devserver를 돌릴시에는 잘 찾는다.
기존 CRA는 이런 버그가 없다. 해서 무엇이 다를까 비교해봤는데, 큰 차이점은 다음과 같다.
- 웹팩 캐시 사용
- 웹팩 devserver middleware 사용
이 2가지를 내거에 추가해보고 다시 테스트해봐야겠다.
'프론트엔드 > 개발 환경' 카테고리의 다른 글
나만의 react boilerplate 만들기 - (4) 개선 (1) | 2023.09.19 |
---|---|
나만의 react boilerplate 만들기 - (3) TypeScript로 전환 (0) | 2023.02.05 |
나만의 react boilerplate 만들기 - (2) npx, 배포 (0) | 2022.12.08 |
나만의 react boilerplate 만들기 - (1) 환경 설정 (0) | 2022.12.02 |
린트, Prettier 기초 개념 정리 (0) | 2022.10.03 |