webpack, cra, vite에 대해 알아보기 - cra

해준박·2024년 5월 28일
0

react 처음 입문할 때 부터 사용한 CRA는 어떤 역할들을 하였을까
저번에 webpack을 알아보면서, CRA는 내부적으로 webpack 설정을 해주는 것과, 여러 개발환경을 설치해주는 역할이라고 알게되었다.

CRA?

CRA(Create React App)
CRA는 React 애플리케이션을 빠르게 설정할 수 있게 도와주는 CLI 도구입니다. Facebook이 개발한 이 도구는 개발자가 복잡한 설정 없이 곧바로 React 애플리케이션을 시작할 수 있도록 합니다.

주요 역할

  • 기본 프로젝트 구조 제공: public 디렉토리에 index.html과 로고, favicon 등의 정적 자산과 src 디렉토리에 기본적인 리액트 코드(index.js, App.js)를 설정합니다.
  • 개발 환경 설정: Webpack, Babel, ESLint, Jest 등 리액트 개발에 필요한 각종 환경 설정을 자동으로 구성합니다.
  • 라이브러리 설치: react, react-dom, react-scripts 등 리액트 프로젝트에 필요한 주요 라이브러리를 설치합니다.
  • npm 명령어 정의: react-scripts를 사용하여 package.json에 유용한 npm 명령어(start, build, test, eject)를 정의합니다.

cra을 통해 직접 프로젝트를 만들고 eject를 해서 구성들을 살펴보자

설치

npx create-react-app my-react-app

CLI로 간단하게 설치할 수 있다. 요즘엔 템플릿을 타입스크립트로 설정해서, 환경을 타입스크립트로도 설정 가능하다.


설치할 경우 위와 같은 구성으로 폴더가 생성된다.

eject

eject를 해주는 까닭은 CRA 환경에선 웹팩과 바벨 등 개발과 배포를 위한 각종 설정에 직접 접근할 수 없기 때문입니다. eject를 하면 전이 의존성을 갖는 모듈(웹팩, 바벨, 린트 등)을 포함한 모든 모듈을 복사해 package.json의 종속성에 포함시킵니다.

eject를 하기 전에는 webpack,jest 등의 설정에 관여 할 수 없다. 그래서 배포설정이나 추가적인 작업을 원한다면 eject를 해서 webpack에 손을 댈 수 있기 때문에 종종 하는 것 같다.

한번 eject하면 다시 되돌릴수 없다. 테스트용으로 하는거니 그냥 진행함
eject의 뜻은 꺼내다 라고 함

npm run eject


jest가 눈에 보이고, webpack.config.js 또한 있다. 그 외에도 여러 js파일들이 보임

jest?
단위 테스트(Unit Test)와 통합 테스트(Integration Test)를 쉽게 작성하고 실행할 수 있게 해줍니다

npm test를 사용하면 내부적으로 설정된 jest가 돌아가는데, 나는 이걸 한번도 사용해본적없다..

파일들을 구경하고 설명하기엔 너무 많아서, 제일 기본적인 경로 설정만 훑어보았다

path.js

// path.js
'use strict';

const path = require('path');
const fs = require('fs');
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');

// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebook/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);

console.log(resolveApp("")); // output: /Users/phj/my-react-app

먼저 process.cwd를 통해, 현재 디렉토리 경로를 확인해주는데요. process는 현재 실행되고 있는 노드 프로세스에 대한 정보를 담고 있는 노드의 내장객체이며, cwd란 current working directory의 줄임말입니다. 현재 경로를 나타내주죠. 그 뒤에, 상대경로에는 파일명을 입력하면, 정확한 절대경로를 나타낼 수 있게 됩니다. 디렉토리가 오는 경우도 있는데, 그럴 경우엔 해당 디렉토리 경로만 표시됩니다.

fs.realpathSync(process.cwd())는 현재 작업 디렉토리의 실제 경로를 반환합니다.
resolveApp 함수는 주어진 상대 경로를 프로젝트의 루트 디렉토리를 기준으로 한 절대 경로로 변환합니다.

// We use `PUBLIC_URL` environment variable or "homepage" field to infer
// "public path" at which the app is served.
// webpack needs to know it to put the right <script> hrefs into HTML even in
// single-page apps that may serve index.html for nested URLs like /todos/42.
// We can't use a relative path in HTML because we don't want to load something
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
const publicUrlOrPath = getPublicUrlOrPath(
  process.env.NODE_ENV === 'development',
  require(resolveApp('package.json')).homepage,
  process.env.PUBLIC_URL
);

getPublicUrlOrPath 함수를 사용하여 앱이 제공되는 "public path"를 설정합니다. 이는 애플리케이션이 빌드될 때 HTML 파일 내의 <script> 및 기타 리소스 경로를 올바르게 설정하기 위해 필요합니다.

이건 정보가 많이 없어서 잘 모르겠다. 찾아보니 개발환경과, 프로덕션 환경을 구분하여 package.json의 정보에
hoampage:{} 부분에 url로 설정된 부분으로 url을 반환한다는 것 같다.

development가 기본적으로 설정이 되어있다면 로컬 서버 주소를 반환한다고 함

// 빌드 파일 경로 설정
const buildPath = process.env.BUILD_PATH || 'build';
// webpack이 파일을 정삭적으로 읽을수 있게 확장자 배열을 추가
const moduleFileExtensions = [
  'web.mjs',
  'mjs',
  'web.js',
  'js',
  'web.ts',
  'ts',
  'web.tsx',
  'tsx',
  'json',
  'web.jsx',
  'jsx',
];

// Resolve file paths in the same order as webpack
// resolveModule을 통해 해당 파일 경로가 들어올 경우
// moduleFileExtensions을 차례로 순회하면서 해당 파일명의 확장자에 맞게 반환
// 기본적으로 js로 반환이 된다.
const resolveModule = (resolveFn, filePath) => {
  const extension = moduleFileExtensions.find(extension =>
    fs.existsSync(resolveFn(`${filePath}.${extension}`))
  );

  if (extension) {
    return resolveFn(`${filePath}.${extension}`);
  }

  return resolveFn(`${filePath}.js`);
};

webpack에서 각 확장자에 맞게 사용되어지는 로더가 있기때문에, 상황에 맞는 파일 확장자로 변환시켜 반환해준다.

// config after eject: we're in ./config/
// 아마 webpack에 사용 되어지게 키/값 형태로 내보내는 듯 하다. 그 과정에서 resolveApp()을 통해 해당 경로를 가리키게 된다.
module.exports = {
  dotenv: resolveApp('.env'),
  appPath: resolveApp('.'),
  appBuild: resolveApp(buildPath),
  appPublic: resolveApp('public'),
  appHtml: resolveApp('public/index.html'),
  appIndexJs: resolveModule(resolveApp, 'src/index'),
  appPackageJson: resolveApp('package.json'),
  appSrc: resolveApp('src'),
  appTsConfig: resolveApp('tsconfig.json'),
  appJsConfig: resolveApp('jsconfig.json'),
  yarnLockFile: resolveApp('yarn.lock'),
  testsSetup: resolveModule(resolveApp, 'src/setupTests'),
  proxySetup: resolveApp('src/setupProxy.js'),
  appNodeModules: resolveApp('node_modules'),
  appWebpackCache: resolveApp('node_modules/.cache'),
  appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'),
  swSrc: resolveModule(resolveApp, 'src/service-worker'),
  publicUrlOrPath,
};



module.exports.moduleFileExtensions = moduleFileExtensions;

그 외

참고사이트 : Creact React App을 분석해보자
위 사이트에서 참고 하면 좋을것 같다. webpack.config을 저번 글에 다루어서 config는 생략했는데, 블로그에 잘 설명이 되어있고

작은 프로젝트를 했을 경우, 학습하면 좋겠지만 지금 나는 필요성을 느끼지 못해서 글만 읽고 따로 작성을 하지 않을 것 같다.

알게된 점은, cra가 webpack 설정을 해준다는 점, jest가 npm test를 통해 돌아 간다는 점, 그리고 cra가 엄청난 역할을 했다는 점이다

profile
기록하기

0개의 댓글