평소 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-cratakes advantage ofreact-app-rewired'sconfig-overrides.js
file. By importingcustomize-crafunctions and exporting a few function calls wrapped in ouroverridefunction, 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