평소 Next.js(create-next-app)로 프로젝트를 만드는 편인데, 생각해보니 CRA로 프로젝트를 만들었던 기억이 가물가물 하기도 하고, 현재 만들고 있는 개인 프로젝트가 꼭 Next.js로 만들 이유가 없다고 생각해서 중간에 CRA로 전환 했었어요. 현재 만들고 있는 프로젝트는 멋지게 만들어서 선보이고 싶은 마음도 있지만, 개인적인 공부도 중요하기 때문에 맘먹고 변경 했었어요.
css
는 css-in-js
인 emotion
을 사용 했었어요. 그 중 css prop을 유용하게 잘 사용하고 있어서, CRA 환경에서도 사용하고 싶었는데, 일반적으로 CRA에서는 emotion
의 css prop
을 사용할 수 없더라고요. 다른 대안이 있지만, Next.js에서 사용하는 방법 그대로 사용하고 싶어서, 방법을 찾아보다가 react-app-rewired
와 customize-cra
라는 라이브러리를 통해 css prop
을 사용하는 방법을 알게되어 공유해보려 합니다..!
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에서 제공하는 eject
와 react-scripts
의 포크를 생성하지 않고 웹팩 설정들을 변경할 수 있습니다. no config라는 제한을 두지 않고 CRA의 이점을 제공합니다. 사용자가 원하면 플러그인, 로더들을 추가할 수 있습니다.
해당 라이브러리를 사용하면 CRA가 제공하는 개런티를 깨트리게 됩니다. 사용하는 순간 설정 들을 소유하게 되는 것이기 때문에 지원되는 것들이 제공되지 않을 것입니다.
CRA에 메인 컨트리뷰터인 Dan Abramov라는 분도 트윗을 통해 아래처럼 경고했었네요.
"Stuff can break" — Dan Abramov
npm install react-app-rewired --save-dev
// or
yarn add -D react-app-rewired
config-overrides.js
라는 파일을 생성하고, 아래와 같이 코드를 입력합니다.module.exports = function override(config, env) {
//do stuff with the webpack config...
return config;
}
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
라이브러리는 react-app-rewired
라이브러리의 핵심 기능을 활용하여 create-react-app
버전 2 및 3 구성을 사용자 지정할 수 있는 유틸리티 세트를 제공합니다.
*customize-cra
takes advantage ofreact-app-rewired
'sconfig-overrides.js
file. By importingcustomize-cra
functions and exporting a few function calls wrapped in ouroverride
function, you can easily modify the underlying config objects (webpack
,webpack-dev-server
,babel
, etc.) that make upcreate-react-app
.*
(공식문서의 내용 중)
customize-cra
를 사용하기 위해서는 react-app-rewired
라이브러리가 필수로 설치되어야 합니다. 말 그대로 customize-cra
는 react-app-rewired
라이브러리의 핵심 기능을 활용하여 커스텀 할 수 있는 유틸성 함수를 제공하기 떄문입니다.
npm install customize-cra --save-dev
// or
yarn add -D customize-cra
config-overrides.js
라는 파일이 있어야 하고, 만약 없다면 생성하여 추가적으로 설정한webpack
, webpack-dev-server
, babel
설정 파일들을 customize-cra
에서 제공하는 api로 오버라이드 합니다./* 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")
})
)
);
babelrc
를 오버라이드 하기 위해서 먼저 babelrc
파일을 생성하여 설정을 합니다. 해당 포스팅에서는 css prop
을 설정해야 하기 때문에 css prop
에 대한 설정을 해보겠습니다.
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
babelrc
파일 생성 후 코드 추가@babel/preset-typescript
는 제외합니다.css prop
에 대한 설정을 확인하고 싶다면 공식문서를 통해 알 수 있습니다!{
"presets": [
[
"@babel/preset-react",
{ "runtime": "automatic", "importSource": "@emotion/react" }
],
"@babel/preset-typescript"
],
"plugins": ["@emotion/babel-plugin"]
}
config-overrides.js
파일에 babelrc
오버라이딩useBabelRc
는 생성된 babelrc
파일로 오버라이드하며, getBabelLoader
는 기존의 바벨 로더를 가져옵니다.removeBuiltinBabelConfig
함수를 보면 기존의 바벨 설정 중 preset
과 plugin
을 비운 config
를 반환합니다. 비워져있는 config는 프로젝트에서 새롭게 생성한 babelrc
파일을 오버라이드합니다.getBabelLoader
의 파라미터인 config는 webpack
의 Configuration 이라는 타입을 사용하는 걸 알 수 있습니다.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());
tsconfig.json
파일에 css prop을 위한 설정 추가{
"compilerOptions": {
...
"jsx": "react-jsx",
"jsxImportSource": "@emotion/react"
},
...
}
공유 드린 emotion
공식문서에는 CRA에서는 css prop
을 지원하지 않는다고 합니다. 그래서 JSX Pragma를 사용할까 고민하다가, 공부 할 겸 설정했었는데, 처음이였고, 급해서 그런지 헤맸었던 기억이 있었어요. 공유드린 코드가 좋은 예시 인지는 모르겠지만, 현재는 잘 작동하고 있습니다. 여하튼 CRA에 대해 조금이나마 더 알게 되었던 계기가 아니었을까 생각해봅니다..!
https://github.com/timarney/react-app-rewired#readme