본문 바로가기

카테고리 없음

CRA (create-react-app)을 사용한 boilerplate 만들기

CRA는 무엇인가?

CRA는 React 개발을 위한 여러 가지 설정 작업을 미리 해둔 Boilerplate입니다.

CRA를 사용하는 이유는 다음과 같습니다.

 

1. react 프로젝트를 구성할 때 필요한 eslint, babel, webpack과 같은 종속성을 신경쓰지 않아도 된다.

2. 프로젝트 구성에 필요한 각 패키지들의 설정에 많은 시간을 소요하지 않아도 된다.

3. react 프로젝트 구성에 필요한 많은 양의 패키지를 깔끔하게 react-scripts하나로 퉁칠 수 있다.

 

하지만 CRA를 사용하다 보면 Webpack이나 babel의 설정을 변경해야 하는 경우들이 생기는데
이를 위해 eject나 customize-cra와 같은 것들을 사용합니다.

CRA의 eject를 사용하지 않는 이유

eject는 CRA의 명령 중 하나인데 사용하게 되면 react-scripts에 숨겨져 있던 명령 스크립트들과 종속성들이 밖으로 추출됩니다.

추출된 명령 스크립트, 프로젝트 종속성

하지만 eject를 사용하게 되면 추출된 명령과 종속성들을 직접 관리해주어야 하기 때문에 CRA Boilerplate를 사용하는 이유가 사라지게 됩니다.

그래서 보통 customize-cra나 react-app-rewired와 같은 패키지를 사용하여 CRA를 커스텀해 사용합니다.

왜 CRA를 사용하여 Boilerplate를 만드는가?

제가 사용하는 eslint의 설정이나 다른 패키지들의 설정을 위해 매번 customize-cra와 react-app-rewired를 사용하여

커스텀을 하는 것이 불편해 react-scripts를 사용하는 boilerplate를 만들어야겠다! 라고 생각하게 되었습니다.

Github Packages Registry를 사용하여 Global Package를 배포해보자

우선 Github Packages Registry를 사용하여 test를 출력하는 Global Package를 만들어 볼 것입니다.

Github에서 Settings -> Developer Settings -> Personal Access Token에서 write:packages 권한이 있는 Token을 생성합니다.

vi ~/.npmrc 명령을 사용하여 다음과 같이 입력합니다.

@닉네임:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=write:packages권한이 있는 personal access token

이제 스크립트를 작성해야 합니다.

// package.json
{
  "name": "@닉네임/create-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "bin": {
    "create-app": "./index.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/MKachi/create-app.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/MKachi/create-app/issues"
  },
  "homepage": "https://github.com/MKachi/create-app#readme",
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/"
  }
}

위의 package.json 파일에서 평소에 보지 못하던 "bin"이라는 property가 있는데

해당 property가 해당 패키지를 global 로 설치하였을 때 해당 패키지내의 특정 스크립트를 실행시키는 옵션 입니다.

 

즉 위의 내용은 create-app을 입력하면 index.js를 실행시키라는 명령이 됩니다.

 

"publishConfig"의 경우는 npm publish 명령을 사용하였을 때 Github Packages Registry에 배포하도록 하는 설정입니다.

// index.js
#!/usr/bin/env node

console.log('test')

 

"bin" property를 통하여 실행될 수 있는 스크립트들의 경우 Shebang을 작성하여 node로 해당 스크립트가 실행되어야 한다는 것을 꼭 명시해야합니다.

Shebang에 대한 자세한 것은 https://en.wikipedia.org/wiki/Shebang_(Unix) 여기를 참조해주세요

 

npm publish

이제 위의 명령을 통해 Github Packages Registry에 배포를 하면

짜잔!

정상적으로 배포된 것을 확인할 수 있습니다.

npx @mkachi/create-app

해당 명령을 사용하면

와!

npx 명령을 사용하여 index.js를 실행시킨 것을 볼 수 있습니다!

이제 진짜 Boilerplate를 만들자

우선 위의 사진처럼 완전히 기본적인 정보들이 들어있는 package.json파일과 설정 파일 & 폴더를 templates폴더에 넣어 프로젝트 내부에 지니도록 하였습니다.

install-list.json에는 해당 프로젝트에 설치해야할 패키지들을 명시하였습니다.

#!/usr/bin/env node

const path = require('path')
const fs = require('fs-extra')
const execSync = require('child_process').execSync

const packageJson = require('./templates/package.json')
const installList = require('./install-list.json')

const createProject = async () => {
  const args = process.argv.slice(2)
  if (args.length <= 0) {
    console.log('프로젝트 이름을 입력해주세요')
    console.log('create-app {프로젝트 이름}')
  }

  const projectName = args[0]
  const templatePath = path.resolve(__dirname, 'templates')
  const createPath = path.resolve(process.cwd(), projectName)

  await fs.copy(templatePath, createPath)

  packageJson.name = projectName
  await fs.writeFile(path.resolve(createPath, 'package.json'), JSON.stringify(packageJson, null, 2))

  let command  = 'yarn add '
  const dependencies = installList.dependencies
  dependencies.map((package) => {
    command += `${package} `
  })
  execSync(command, { cwd: createPath })

  command  = 'yarn add -D '
  const devDependencies = installList.devDependencies
  devDependencies.map((package) => {
    command += `${package} `
  })
  execSync(command, { cwd: createPath })
  console.log(`${projectName} 프로젝트가 생성되었습니다.`)
}

createProject()

index.js의 내용입니다.

우선 해당 명령을 실행시킨 Directory에 templates의 내용을 복사하고 templates내의 package.json의 name property를 프로젝트의 이름으로 변경 후 새로 생성합니다.

그 뒤 install-list.json에 있는 패키지 정보들을 가져와 yarn으로 패키지 설치를 시도합니다.

프로젝트가 아주 잘 생성되었습니다!