# CRACO

**CRACO**(**C**reate **R**eact **A**pp **C**onfiguration **O**verride)는 Create React App 구성을 덮어쓸 수 있도록 도와줍니다.

![](https://597303073-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MUfqhMWK9ILIx0SXJTa%2F-MUvRC4B_iTjDz8r_w7P%2F-MUvRgQl_qnfqht1fryO%2Fimage.png?alt=media\&token=47ee9579-6965-485d-a000-a750c511f12e)

CRA `eject` 명령을 사용하지 않고도 프로젝트 루트 위치에 `craco.config.js` 파일을 추가한 다음 ESLint, Babel, PostCSS, Sass 구성 등을 사용자 입맛에 맞게 수정할 수 있어 유용합니다.

## 패키지 설치 <a href="#install-package" id="install-package"></a>

[@craco/craco](https://www.npmjs.com/package/@craco/craco) 패키지를 프로젝트에 설치합니다.

{% tabs %}
{% tab title="패키지 설치" %}

```bash
npm i -D @craco/craco
```

{% endtab %}
{% endtabs %}

## package.json

NPM 스크립트 명령이 CRACO를 사용하도록 `start`, `build`, `test` 명령을 변경합니다.

{% tabs %}
{% tab title="package.json" %}

```bash
"scripts": {
  "start": "craco start",
  "build": "craco build",
  "test": "craco test",
  "eject": "react-scripts eject"
}
```

{% endtab %}
{% endtabs %}

## craco.config.js

CRACO 구성 파일을 프로젝트 루트 위치에 생성합니다.

```bash
.
├── node_modules/
├── craco.config.js # CRACO 구성 파일
└── package.json
```

{% tabs %}
{% tab title="craco.config.js" %}

```javascript
module.exports = {
  // ...
}

// 또는

module.exports = ({env}) => {
  return {
    // ...
  }
}
```

{% endtab %}
{% endtabs %}

## CRACO 구성 <a href="#config-craco" id="config-craco"></a>

`craco.config.js` 파일 구성은 다음과 같은 구조로 작성합니다. 모든 내용을 작성할 필요는 없고 덮어쓰기 하고 싶은 구성만 추가하면 됩니다.

{% tabs %}
{% tab title="craco.config.js" %}

```javascript
const {
  when,
  whenDev,
  whenProd,
  whenTest,
  ESLINT_MODES,
  POSTCSS_MODES,
} = require('@craco/craco')

module.exports = {
  reactScriptsVersion: 'react-scripts' /* 기본 값 */,
  style: {
    css: {
      loaderOptions: {
        // CSS 구성 옵션 
        // 참고: https://github.com/webpack-contrib/css-loader
      }
    },
    sass: {
      loaderOptions: {
        // Sass 구성 옵션 
        // 참고: https://github.com/webpack-contrib/sass-loader
      }
    },
    postcss: {
      mode: 'extends' /* (기본 값) */ || 'file',
      plugins: [],
      env: {
        autoprefixer: {
          // autoprefixer 옵션 
          // https://github.com/postcss/autoprefixer#options
        },
        stage: 3 /* 참고: https://cssdb.org/#staging-process */,
        features: { /* 참고: https://preset-env.cssdb.org/features */ },
      },
      loaderOptions: {
        // postcss-loader 구성 옵션
        // 참고: https://github.com/postcss/postcss-loader
      }
    },
  },
  
  eslint: {
    enable: true /* 기본 값 */,
    mode: 'extends' /* 기본 값 */ || 'file',
    configure: {
      // eslint 구성 옵션
      // https://eslint.org/docs/user-guide/configuring
    }
    pluginOptions: {
      // eslint 플러그인 구성 옵션
      // 참고: https://github.com/webpack-contrib/eslint-webpack-plugin#options
    }
  },
  
  babel: {
    presets: [],
    plugins: [],
    loaderOptions: {
      // babel-loader 구성 옵션
      // 참고: https://github.com/babel/babel-loader
    }
  },
  
  typescript: {
    enableTypeChecking: true /* 기본 값 */,
  },
  
  webpack: {
    alias: {},
    plugins: {
      // 플러그인 배열
      add: [],
      // 플러그인 생성자 이름 배열("StyleLintPlugin", "ESLintWebpackPlugin")
      remove: [] 
    },
    configure: {
      // webpack 구성 옵션
      // 참고: https://webpack.js.org/configuration
    }
  },
  
  jest: {
    babel: {
      addPresets: true /* 기본 값 */,
      addPlugins: true /* 기본 값 */,
    },
    configure: {
      // Jest 구성 옵션 
      // 참고: https://jestjs.io/docs/en/configuration
    }
  },
  
  devServer: {
    // devServer 구성 옵션 
    // 참고: https://webpack.js.org/configuration/dev-server/#devserver
  },
  
  plugins: [
    // CRACO 플러그인
    // 참고: https://bit.ly/3reUqet
  ]
}

```

{% endtab %}
{% endtabs %}

## \[플러그인] sass sourcemap <a href="#sass-sourcemap" id="sass-sourcemap"></a>

Sass 소스맵을 활성화 하려면 CRACO의 [overrideWebpackConfig](https://github.com/gsoft-inc/craco/blob/master/packages/craco/README.md#overridewebpackconfig) 함수를 사용해 Webpack 구성을 덮어써야 합니다. Sass 소스맵을 활성화 하는 CRACO 플러그인 파일을 아래와 같이 만든 후 작성합니다.

{% tabs %}
{% tab title="plugins/sass-sourcemap.js" %}

```javascript
module.exports = {

  // Webpack 구성 파일 덮어쓰기 설정
  overrideWebpackConfig: ({
    webpackConfig,
    cracoConfig,
    pluginOptions,
    context: { env, paths },
  }) => {
  
    // 탐색 함수
    function traverse(obj, callback) {
      if (Array.isArray(obj)) {
        obj.forEach((item) => traverse(item, callback))
      } else if (typeof obj === 'object' && obj !== null) {
        Object.keys(obj).forEach((key) => {
          if (obj.hasOwnProperty(key)) {
            callback(obj, key)
            traverse(obj[key], callback)
          }
        })
      }
    }
    
    // Webpack 구성 파일 탐색
    traverse(webpackConfig, (node, key) => {
      // key 값이 loader 이고
      if (key === 'loader') {
        // node[key] 값이 sass-loader, postcss-loader, css-loader인 경우
        if (
          node[key].indexOf('sass-loader') !== -1 ||
          node[key].indexOf('postcss-loader') !== -1 ||
          node[key].indexOf('css-loader') !== -1
        ) {
          // node의 options 값이 존재하면
          if (node.options) {
            // node.options 소스맵 활성화
            node.options.sourceMap = true
          }
        }
      }
    })
    
    // Webpack 구성 파일 내보내기
    return webpackConfig
  }
}
```

{% endtab %}
{% endtabs %}

`craco.config.js` 파일에 sass-sourcemap 플러그인 파일을 불러와 CRACO 플러그인 아이템으로 설정합니다.

{% tabs %}
{% tab title="craco.config.js" %}

```javascript
const sassSourcemapsPlugin = require('./plugins/sass-sourcemap')

module.exports = {
  plugins: [
    { plugin: sassSourcemapsPlugin },
  ],
}
```

{% endtab %}
{% endtabs %}

## \[플러그인] alias

[craco-alias](https://github.com/risenforces/craco-alias) 플러그인은 Webpack, Jest의 별칭을 등록하는데 유용합니다. 플러그인을 사용하려면 설치합니다.

{% tabs %}
{% tab title="패키지 설치" %}

```bash
npm i -D craco-alias
```

{% endtab %}
{% endtabs %}

`craco.config.js` 파일에 craco-alias 플러그인 파일을 불러와 CRACO 플러그인 아이템으로 설정합니다.

{% tabs %}
{% tab title="craco.config.js" %}

```javascript
const cracoAliasPlugin = require('craco-alias')

module.exports = {
  plugins: [
    {
      plugin: cracoAliasPlugin,
      options: {
        // 'tsconfig', 'options'(기본 값) 중 선택
        source: 'jsconfig', 
        // './' (기본 값)
        baseUrl: './src', 
        // 디렉토리 별칭 등록 {} (기본 값)
        aliases: {
          '@components/*': ['components/*', 'components']
        },
        // 디버깅 false(기본 값) → debug: false 
      }
    }
  ]
}
```

{% endtab %}
{% endtabs %}

## \[플러그인] favicons

[craco-favicons](https://github.com/rickysullivan/craco-favicons) 플러그인은 [favicon-webpack-plugin](https://github.com/jantimon/favicons-webpack-plugin) 플러그인을 활용하여 파비콘(favicons)을 자동 생성하므로 유용합니다. 플러그인을 사용하려면 설치합니다.

{% tabs %}
{% tab title="패키지 설치" %}

```bash
npm i -D craco-favicons
```

{% endtab %}
{% endtabs %}

`craco.config.js` 파일에 craco-favicons 플러그인 파일을 불러와 CRACO 플러그인 아이템으로 설정합니다.

{% tabs %}
{% tab title="craco.config.js" %}

```javascript
const cracoFaviconsPlugin = require('craco-favicons')

module.exports = {
  plugins: [
    {
      plugin: cracoFaviconsPlugin,
      // 제공된 모든 옵션은 favicons-webpack-plugin에 전달됩니다.
      // 참고: https://bit.ly/30dWLdX
      options: {
        logo: './src/assets/images/app-logo.svg',
        inject: true,
        prefix: 'static/icons/',
        favicons: {
          icons: {
            android: { offset: 10 },
            appleIcon: { offset: 10 },
            coast: false,
            yandex: false,
            appleStartup: { offset: 10 },
            firefox: false,
            windows: false,
          }
        }
      }
    }
  ]
}
```

{% endtab %}
{% endtabs %}

## \[플러그인] image optimizer

[craco-image-optimizer-plugin](https://github.com/kkulbae/craco-image-optimizer-plugin) 플러그인은 [image-webapck-loader](https://www.npmjs.com/package/image-webpack-loader) 플러그인을 활용하여 모든 이미지를 최적화 처리합니다. 플러그인을 사용하려면 설치합니다.

{% tabs %}
{% tab title="패키지 설치" %}

```bash
npm i -D craco-image-optimizer-plugin
```

{% endtab %}
{% endtabs %}

`craco.config.js` 파일에 플러그인 파일을 불러와 CRACO 플러그인 아이템으로 설정합니다.

{% tabs %}
{% tab title="craco.config.js" %}

```javascript
const imageOptimizerPlugin = require('craco-image-optimizer-plugin')

module.exports = {
  plugins: [
    {
      plugin: imageOptimizerPlugin,
      // 제공된 모든 옵션은 image-webpack-plugin에 전달됩니다.
      // 참고: https://github.com/tcoopman/image-webpack-loader#usage
      options: {
        mozjpeg: {
          progressive: true,
          quality: 65,
        },
        optipng: {
          enabled: false,
        },
        pngquant: {
          quality: [0.65, 0.9],
          speed: 4,
        },
        gifsicle: {
          interlaced: false,
        },
        webp: {
          quality: 75,
        }
      }
    }
  ]
}
```

{% endtab %}
{% endtabs %}

## 커스텀 템플릿 <a href="#custom-template" id="custom-template"></a>

필요하다면 CRACO 설정이 반영된 커스텀 템플릿을 다운로드 받아 사용할 수 있습니다.

{% embed url="<https://www.npmjs.com/package/cra-template-ko-craco>" %}
