React app rewired를 이용하여 CRA에 css prop 설정하기 (with customize-cra)

Seal Park·2022년 9월 17일
2

개요

평소 Next.js(create-next-app)로 프로젝트를 만드는 편인데, 생각해보니 CRA로 프로젝트를 만들었던 기억이 가물가물 하기도 하고, 현재 만들고 있는 개인 프로젝트가 꼭 Next.js로 만들 이유가 없다고 생각해서 중간에 CRA로 전환 했었어요. 현재 만들고 있는 프로젝트는 멋지게 만들어서 선보이고 싶은 마음도 있지만, 개인적인 공부도 중요하기 때문에 맘먹고 변경 했었어요.

csscss-in-jsemotion을 사용 했었어요. 그 중 css prop을 유용하게 잘 사용하고 있어서, CRA 환경에서도 사용하고 싶었는데, 일반적으로 CRA에서는 emotioncss prop을 사용할 수 없더라고요. 다른 대안이 있지만, Next.js에서 사용하는 방법 그대로 사용하고 싶어서, 방법을 찾아보다가 react-app-rewiredcustomize-cra라는 라이브러리를 통해 css prop을 사용하는 방법을 알게되어 공유해보려 합니다..!

react-app-rewired 라이브러리란?

Tweak the create-react-app webpack config(s) without using 'eject' and without creating a fork of the react-scripts.

All the benefits of create-react-app without the limitations of "no config". You can add plugins, loaders whatever you need.

(공식문서의 내용 중)

CRA에서 제공하는 ejectreact-scripts의 포크를 생성하지 않고 웹팩 설정들을 변경할 수 있습니다. no config라는 제한을 두지 않고 CRA의 이점을 제공합니다. 사용자가 원하면 플러그인, 로더들을 추가할 수 있습니다.

주의사항

해당 라이브러리를 사용하면 CRA가 제공하는 개런티를 깨트리게 됩니다. 사용하는 순간 설정 들을 소유하게 되는 것이기 때문에 지원되는 것들이 제공되지 않을 것입니다.

CRA에 메인 컨트리뷰터인 Dan Abramov라는 분도 트윗을 통해 아래처럼 경고했었네요.

"Stuff can break" — Dan Abramov

사용 방법

  1. 아래와 같이 라이브러리를 설치합니다.
npm install react-app-rewired --save-dev
// or
yarn add -D react-app-rewired
  1. 최 상단 경로에 config-overrides.js라는 파일을 생성하고, 아래와 같이 코드를 입력합니다.
module.exports = function override(config, env) {
  //do stuff with the webpack config...
  return config;
}
  1. packages.json 파일 안에 script 설정을 변경합니다.
/* package.json */

"scripts": {
	"start": "react-app-rewired start",
	"build": "react-app-rewired build",
	"test": "react-app-rewired test",
	"eject": "react-scripts eject"
}

다만 주의해야 하는 점은, eject 설정을 건드리면 안된다는 것입니다. eject는 단 한 번만 사용할 수 있으며, 그 후에는 웹팩 설정에 대한 권한이 생기기 때문에 react-app-rewired를 필요로 하지 않게 돼요.

만약 웹팩 설정, 테스트(jest) 설정, 웹팩 데브서버 등 추가적인 설정이 필요하다면 공식문서를 통해 확인해보세요. 이번 포스팅에서는 babel config 설정을 위한 글이기 때문에 생략하겠습니다..!

customize-css 라이브러리란?

customize-css 라이브러리는 react-app-rewired 라이브러리의 핵심 기능을 활용하여 create-react-app 버전 2 및 3 구성을 사용자 지정할 수 있는 유틸리티 세트를 제공합니다.

*customize-cra takes advantage of react-app-rewired's config-overrides.js
file. By importing customize-cra functions and exporting a few function calls wrapped in our override function, you can easily modify the underlying config objects (webpackwebpack-dev-serverbabel, etc.) that make up create-react-app.*
(공식문서의 내용 중)

사용 방법

customize-cra를 사용하기 위해서는 react-app-rewired 라이브러리가 필수로 설치되어야 합니다. 말 그대로 customize-crareact-app-rewired 라이브러리의 핵심 기능을 활용하여 커스텀 할 수 있는 유틸성 함수를 제공하기 떄문입니다.

  1. 아래와 같이 라이브러리를 설치합니다.
npm install customize-cra --save-dev
// or
yarn add -D customize-cra
  1. 최 상단 경로에 config-overrides.js라는 파일이 있어야 하고, 만약 없다면 생성하여 추가적으로 설정한webpack, webpack-dev-server, babel 설정 파일들을 customize-cra에서 제공하는 api로 오버라이드 합니다.
    아래 코드와 같이 일반적으로 override라는 api를 사용하여 오버라이드 하려는 api들을 감싸 export 합니다.
/* config-overrides.js */

// webpack example

const {
  override,
  addDecoratorsLegacy,
  disableEsLint,
  addBundleVisualizer,
  addWebpackAlias,
  adjustWorkbox
} = require("customize-cra");
const path = require("path");

module.exports = override(
  // enable legacy decorators babel plugin
  addDecoratorsLegacy(),

  // disable eslint in webpack
  disableEsLint(),

  // add webpack bundle visualizer if BUNDLE_VISUALIZE flag is enabled
  process.env.BUNDLE_VISUALIZE == 1 && addBundleVisualizer(),

  // add an alias for "ag-grid-react" imports
  addWebpackAlias({
    ["ag-grid-react$"]: path.resolve(__dirname, "src/shared/agGridWrapper.js")
  }),

  // adjust the underlying workbox
  adjustWorkbox(wb =>
    Object.assign(wb, {
      skipWaiting: true,
      exclude: (wb.exclude || []).concat("index.html")
    })
  )
);

config-overrides.js 파일에 babelrc 설정하기

babelrc를 오버라이드 하기 위해서 먼저 babelrc 파일을 생성하여 설정을 합니다. 해당 포스팅에서는 css prop을 설정해야 하기 때문에 css prop에 대한 설정을 해보겠습니다.

  1. babel config 관련 라이브러리 설치
    타입스크립트를 사용하지 않는다면 두 번째 @babel/preset-typescript는 제외하고 설치합니다.
npm install @babel/preset-react @babel/preset-typescript @emotion/babel-plugin --save-dev
// or
yarn add -D @babel/preset-react @babel/preset-typescript @emotion/babel-plugin
  1. babelrc 파일 생성 후 코드 추가
    마찬가지로 타입스크립트를 사용하지 않는다면 중간에 @babel/preset-typescript는 제외합니다.
    css prop에 대한 설정을 확인하고 싶다면 공식문서를 통해 알 수 있습니다!
{
  "presets": [
    [
      "@babel/preset-react",
      { "runtime": "automatic", "importSource": "@emotion/react" }
    ],
    "@babel/preset-typescript"
  ],
  "plugins": ["@emotion/babel-plugin"]
}
  1. config-overrides.js 파일에 babelrc 오버라이딩
    useBabelRc는 생성된 babelrc 파일로 오버라이드하며, getBabelLoader는 기존의 바벨 로더를 가져옵니다.
    removeBuiltinBabelConfig함수를 보면 기존의 바벨 설정 중 presetplugin을 비운 config를 반환합니다. 비워져있는 config는 프로젝트에서 새롭게 생성한 babelrc파일을 오버라이드합니다.
    깃허브에 useBabelRc 함수를 보면 getBabelLoader 함수를 사용하는 것을 볼 수 있는데, getBabelLoader의 파라미터인 configwebpackConfiguration 이라는 타입을 사용하는 걸 알 수 있습니다.
const { override, useBabelRc, getBabelLoader } = require('customize-cra');

const removeBuiltinBabelConfig = (config) => {
  getBabelLoader(config).options.presets = [];
  getBabelLoader(config).options.plugins = [];
  return config;
};

module.exports = override(removeBultinBabelConfig, useBabelRc());
  1. tsconfig.json 파일에 css prop을 위한 설정 추가
{
  "compilerOptions": {
    ...
    "jsx": "react-jsx",
    "jsxImportSource": "@emotion/react"
  },
	...
}

마치며

공유 드린 emotion 공식문서에는 CRA에서는 css prop을 지원하지 않는다고 합니다. 그래서 JSX Pragma를 사용할까 고민하다가, 공부 할 겸 설정했었는데, 처음이였고, 급해서 그런지 헤맸었던 기억이 있었어요. 공유드린 코드가 좋은 예시 인지는 모르겠지만, 현재는 잘 작동하고 있습니다. 여하튼 CRA에 대해 조금이나마 더 알게 되었던 계기가 아니었을까 생각해봅니다..!

References

https://github.com/timarney/react-app-rewired#readme

https://github.com/arackaf/customize-cra#readme

https://github.com/emotion-js/emotion/issues/2202

0개의 댓글