CRA 분석하기

2022. 12. 20. 23:58·프론트엔드/개발 환경

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는 이런 버그가 없다. 해서 무엇이 다를까 비교해봤는데, 큰 차이점은 다음과 같다.

  1. 웹팩 캐시 사용
  2. 웹팩 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
'프론트엔드/개발 환경' 카테고리의 다른 글
  • 나만의 react boilerplate 만들기 - (4) 개선
  • 나만의 react boilerplate 만들기 - (3) TypeScript로 전환
  • 나만의 react boilerplate 만들기 - (2) npx, 배포
  • 나만의 react boilerplate 만들기 - (1) 환경 설정
정현우12
정현우12
  • 정현우12
    정현우의 개발 블로그
    정현우12
  • 전체
    오늘
    어제
    • 분류 전체보기 (79)
      • 프론트엔드 (56)
        • JavaScript, TypeScript (12)
        • 스타일링 (1)
        • React (13)
        • Next.js (4)
        • 개발 환경 (9)
        • 테스트 (3)
        • 성능 최적화 (11)
        • 함수형 프로그래밍 (2)
        • 구조 (1)
      • 프로젝트 회고 (23)
        • 이미지편집기 개발 (7)
        • 엑셀 다운로드, 업로드 공통 모듈 개발 (4)
        • 사용자 매뉴얼 사이트 개발 (3)
        • 통계자동화 솔루션 개발 (1)
        • 엑셀 편집기 개발 (5)
        • API 플랫폼 (1)
        • 콜센터 솔루션 OB 캠페인 (1)
        • AI 스튜디오 (1)
      • 백엔드 (0)
  • 블로그 메뉴

    • 홈
    • 포트폴리오
    • 태그
  • 인기 글

  • 태그

    Github Actions
    React
    TypeScript
    회고
    webpack
    React-boilerplate
    JavaScript
    라이브러리 선정
    엑셀 에디터
    엑셀
    커스텀 훅
    frontend
    렌더링 성능 최적화
    웹 성능 최적화
    이미지 편집기
    로딩 성능 최적화
    useReducer
    사용자 매뉴얼 사이트
    Next.js
    memoization
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
정현우12
CRA 분석하기
상단으로

티스토리툴바