Create-React-App 의 webpack.config.js 들여다보기

김승엽
Berkbach
7 min readMay 14, 2020

--

Photo by Markus Spiske on Unsplash

CRA로 생성된 React 프로젝트의 webpack 설정파일을 자세히 알아보겠습니다. CRA로 cra-eject-example 프로젝트를 생성해줍니다.

% create-react-app cra-eject-example

명령어 한 줄로 간단하게 프로젝트를 만들었습니다. 그런데 디렉토리를 보면 어떤 설정파일도 보이지 않습니다.

그 이유는 CRA가 설정파일을 숨겼기 때문입니다. 이 또한 명령어로 설정파일을 뽑을 수 있습니다. package.json 의 스크립트를 정의하는 부분을 보면 “eject”: “react-scripts eject” 이 있습니다. 이 명령어가 설정파일을 추출하는 명령어입니다.

% npm run eject

위 명령어를 입력해서 숨겨져있던 파일을 꺼내면 configscripts 폴더가 생기고 package.json 파일이 모든 dependencybabel, jest 설정 코드가 드러납니다.

⚙️ Config

이 포스트에서는 webpack 설정 부분만 확인하겠습니다. webpack.config.js 에 명시되어있는 옵션 입니다.

  • mode: webpack에게 현재 모드를 알려주는 옵션입니다.
  • bail: True 일 경우 첫 번째 오류를 허용합니다. 여기서는 production 일 때만 허용합니다.
  • devtool: 어떤 source-map 을 사용할지 결정하는 부분입니다. source-map 이란 원본 코드와 빌드된 코드를 매핑 해주는 방법입니다. CRA 에서는 production 일 때는 source-map , development 일 때는 cheap-module-source-map 을 사용하는군요. 근데 source-map 를 넣었을 때 원본 코드가 드러나는 경우가 있어서 source map 을 안쓰는 사람도 있습니다. 또 쓰더라도 source-map 의 성능이 안 좋아서 source-map 대신 cheap-module-source-map 를 사용하는 경우도 있습니다.
  • entry: 앱을 번들할 때 시작 점을 정의합니다. 배열로 받을 경우 시작시 모든 모듈이 로드됩니다. 여기서는 ].filter(Boolean) 을 통해서 isEnvDevelopment 부분을 모드에 따라서 제외시켰습니다.
  • output: 번들을 완료한 파일을 설정합니다. path 는 파일을 저장할 경로 입니다. pathinfo 는 모듈에 관련된 내용을 주석으로 표시합니다. production 일 때는 안하는 것이 좋습니다. filename 은 번들을 완료한 파일의 이름을 정의합니다. futureEmitAssetswebpack-5 에서 없어진다고 하니 중요하지 않아보여서 넘어 가겠습니다. chunkFilename 은 청크 파일의 이름을 정의합니다. publicPath 는 브라우저에서 참조될때 출력 파일의 공용 URL 주소를 지정합니다. devtoolModuleFilenameTemplate 은 source-map의 소스 배열을 커스터마이징 합니다. jsonpFunction 는 여러 개의 webpack이 작동할 때 충돌을 막기위해 설정합니다. globalObject 는 전역변수를 설정하는 부분입니다. 기본 값은 window 입니다.
  • optimization: webpack 4 부터 mode 에 따라서 설정이 가능해졌습니다. minimizeTerserPlugin 이나 minimizer 에 따로 정의된 plugin 을 사용해서 번들한 파일을 최소화 할지 결정합니다. minimizerTerserPlugin 을 커스터마이징 하거나 기본 값으로 minimize 에 사용될 minimizer 를 설정합니다. 여기서는 TerserPlugin 커스터마이징과 OptimizeCSSAssetsPlugin 을 추가해서 사용했네요. splitChunks 는 청크 파일에서 중복되는 모듈을 모으는 역할을 합니다. runtimeChunktrue 나 설정을 하면 런타임만 포함하는 각 진입점에 청크가 추가됩니다.
  • resolve: 이 옵션은 모듈을 해석하는데 관여합니다. 모듈을 해석할 때 modules 로 먼저 탐색할 폴더를 지정할 수 있습니다. extensions.ts , .jsx 와 같은 확장자를 관리할 수 있습니다. 여기서는 paths.js/moduleFileExtensions 로 관리하고 있습니다. alias 는 모듈에 별명을 주어서 간단하게 import , require 를 할 수 있습니다. plugins 는 모듈 해석에 대한 plugin 입니다.
  • resolveLoader: resolve 와 같은 속성을 갖지만 resolveLoader는 loader 모듈만 해석합니다.
  • module: loader 를 설정하는 부분입니다. strictExportPresence 는 경고 대신 에러를 보냅니다. rules 로 loader를 설정합니다.
  • plugins: plugin을 설정합니다.
  • node: 노드 객체를 설정합니다. true, false, empty, mock 값으로 객체를 설정할 수 있습니다. true 는 polyfill 을 제공합니다. false 는 어떤 것도 반환하지 않습니다. empty 는 빈 객체, mock 은 mock 객체를 반환합니다.

자세한 내용이나 추가 옵션은 webpack 공식 사이트에서 확인해주세요.

🏗 Build

다음으로 eject로 생긴 scripts 폴더의 build.js 를 봅시다. 아래는 build.js 의 함수 실행 순서 입니다.

  1. checkBrowsers(): 브라우저를 체크합니다.
  2. measureFileSizesBeforeBuild(): 빌드 전 build 폴더의 크기를 계산합니다.
  3. emptyDirSync(): build 폴더를 비웁니다.
  4. copyPublicFolder(): 비워진 build 폴더에 public 폴더를 복사합니다.
  5. build(): 빌드를 진행합니다.

이런 식으로 빌드를 진행하고나면 마지막으로 상태를 로그에 찍고 마무리 합니다. scripts/build.jsconfig/webpack.config.js 를 살펴보니 create-react-app 으로 만들어도 .env 환경 변수 파일로 어느정도 설정을 할 수 있게 해놓았네요. 또 eject 를 사용할 때 조심해야할 부분이 있습니다. 바로 한번 eject 를 진행하면 eject 하기 전으로 되돌리지 못한다는 점 입니다. 그때 그때 상황에 따라 webpack 설정을 해주시면 될 것 같습니다. 감사합니다.

--

--