git clone
, npm i
를 자동으로 수행하는 프로젝트 만들기위의 순서대로 진행해보자.
npx create-next-app
으로 next 프로젝트를 시작하자.나는 Tailwind를 쓰지 않고 TypeScript, ESlint, App router를 사용했다.
항상 프로젝트를 시작할 때 ESLint와 Prettier를 설정하는게 매우 귀찮았다. 미리 설정해놓자.
내가 사용한 패키지는 아래와 같다.
1"devDependencies": { 2 "@typescript-eslint/eslint-plugin": "^7.11.0", 3 "@typescript-eslint/parser": "^7.11.0", 4 "eslint": "^8", 5 "eslint-config-airbnb": "^19.0.4", 6 "eslint-config-airbnb-typescript": "^18.0.0", 7 "eslint-config-next": "14.2.3", 8 "eslint-config-prettier": "^9.1.0", 9 "eslint-plugin-import": "^2.29.1", 10 "eslint-plugin-prettier": "^5.1.3", 11 "prettier": "^3.2.5", 12 }
ESLint, Prettier 설정은 다음과 같다.
1// .eslintrc.json 2{ 3 "parserOptions": { 4 "project": "./tsconfig.json" 5 }, 6 "plugins": ["@typescript-eslint/eslint-plugin"], 7 "extends": [ 8 "airbnb-base", 9 "airbnb-typescript/base", 10 "plugin:@typescript-eslint/recommended", 11 "plugin:prettier/recommended" 12 ], 13 "rules": { 14 "import/extensions": [ 15 "error", 16 "ignorePackages", 17 { 18 "": "never" 19 } 20 ], 21 "react/react-in-jsx-scope": "off", 22 "react/jsx-props-no-spreading": "off" 23 } 24}
1// .prettierrc 2{ 3 "printWidth": 80, 4 "tabWidth": 2, 5 "useTabs": false, 6 "semi": true, 7 "singleQuote": true, 8 "jsxSingleQuote": true, 9 "trailingComma": "all", 10 "bracketSpacing": true, 11 "proseWrap": "never", 12 "endOfLine": "auto" 13}
Next.js + react-query 설정하기 포스트 내용과 같이 설정했다.
Next.js + zustand 설정하기 포스트 내용과 같이 설정했다.
template repository로 설정을 했기 때문에 새 repo를 만들 때 템플릿으로 지정을 하면 기본적으로 위 설정과 똑같은 새 프로젝트가 생성이 된다.
하지만 나는 간지나게? 터미널 명령어 한 줄로 위 설정을 가져오고싶었다.
git clone
, npm i
를 자동으로 수행하는 프로젝트 만들기create-next-boilerplate 라는 새 프로젝트 폴더를 만들었다.
npm init -y
물어보는 질문 모두 yes!
1// package.json 2{ 3 "name": "create-next-boilerplate", 4 "version": "1.1.0", 5 "description": "Next.js 14 app router boilerplate with Zustand and React Query", 6 "bin": { 7 "create-next-boilerplate": "./bin/create-next-boilerplate.js" 8 }, 9 "keywords": [ 10 "nextjs", 11 "zustand", 12 "react-query", 13 "boilerplate", 14 "setup" 15 ], 16 "author": "siyeol97", 17 "license": "MIT", 18 "homepage": "https://github.com/siyeol97/nextjs-boilerplate#readme", 19 "bugs": { 20 "url": "https://github.com/siyeol97/create-next-boilerplate/issues", 21 "repository": { 22 "type": "git", 23 "url": "git+https://github.com/siyeol97/create-next-boilerplate.git" 24 } 25 }, 26 "type": "module", 27}
bin
속성을 이용해서 ./bin/create-next-boilerplate.js
파일이 create-next-boilerplate
명령어로 등록되어 사용자는 npx create-next-boilerplate
을 터미널에서 전역 명령어로 실행할 수 있다!
나머지 속성들은 npm 에 등록될 때 정보들을 제공한다.
사용한 라이브러리는 다음과 같다.
git clone
명령어를 실행할 때 사용했다.npm install
명령어를 실행할 때 사용했다.전체적인 코드는 다음과 같다.
1// create-next-boilerplate.js 2#!/usr/bin/env node 3 4import inquirer from 'inquirer'; 5import simpleGit from 'simple-git'; 6import { execa } from 'execa'; 7import path from 'path'; 8import fs, { rmSync } from 'fs'; 9 10const REPO_URL = 'https://github.com/siyeol97/nextjs-boilerplate.git'; 11 12async function promptProjectName() { 13 const answers = await inquirer.prompt([ 14 { 15 type: 'input', 16 name: 'projectName', 17 message: 'What is your project name?', 18 validate: (input) => (input ? true : 'Project name cannot be empty'), 19 }, 20 ]); 21 return answers.projectName; 22} 23 24async function cloneRepo(projectName) { 25 const targetDir = path.join(process.cwd(), projectName); 26 const git = simpleGit(); 27 28 if (fs.existsSync(targetDir)) { 29 console.error( 30 'Target directory already exists. Please remove it or choose a different project name.' 31 ); 32 process.exit(1); 33 } 34 35 console.log('Cloning repository...'); 36 await git.clone(REPO_URL, targetDir); 37 console.log('Repository cloned.'); 38 39 const gitDir = path.join(targetDir, '.git'); 40 rmSync(gitDir, { recursive: true, force: true }); 41 console.log('.git directory removed.'); 42 43 const packageJsonPath = path.join(targetDir, 'package.json'); 44 const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); 45 packageJson.name = projectName; 46 fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); 47 48 console.log('Installing packages...'); 49 await execa('npm', ['install'], { cwd: targetDir, stdio: 'inherit' }); 50 console.log('Packages installed.'); 51} 52 53async function main() { 54 try { 55 const projectName = await promptProjectName(); 56 await cloneRepo(projectName); 57 } catch (error) { 58 console.error('Error:', error.message); 59 } 60} 61 62main();
로직은 간단하다.
npx create-next-boilerplate
를 실행하면package.json
의 name을 입력받은 프로젝트 이름으로 수정한다.npm install
명령어를 실행!마지막 단계인 npm 배포는 다음 포스트에!