Vite 프로젝트 생 성 실현 절차

9535 단어 Vite창설항목
머리말
Vite 2 가 발표 되 고 안정 되면 서 점점 더 많은 프로젝트 들 이 사용 을 시도 하고 있다.저희 가 Vite 를 사용 하 는 것 은 보통 아래 명령 으로 프로젝트 를 만 드 는 것 입 니 다.

//    npm
npm init @vitejs/app
//    yarn
yarn create @vitejs/app

 
//                     ,       
// npm
npm init @vitejs/app my-vue-app --template vue
// yarn
yarn create @vitejs/app my-vue-app --template vue

이 명령 을 실행 하면 프로젝트 폴 더 가 생 성 됩 니 다.대부분의 사람들 은 프로젝트 를 정상적으로 만 들 면 된다 고 생각 할 수 있 지만 왜 이 명령 을 실행 하면 프로젝트 폴 더 가 생 성 되 는 지 궁금 합 니 다.여 기 는 Yrn 을 예 로 들 어 프로젝트 를 만 들 고 설명 합 니 다.
yarn create 뭐 했 어 요?
많은 사람들 이 왜 많은 프로젝트 의 생 성 방식 이 Yrn create 라 는 명령 을 사용 하여 생 성 되 었 는 지 의심 할 수 있 습 니 다.이곳 의 Vite 를 제외 하고 우리 가 React 프로젝트 를 만 든 것 도 마찬가지 입 니 다.yarn create react-app my-app.
그러면 이 명령 은 도대체 무엇 을 했 는 지 사실은 두 가지 일 을 했다.

yarn global add create-react-app
create-react-app my-app
Yrn create 에 대한 더 많은 내용 은 여 기 를 보 실 수 있 습 니 다.
소스 코드 분석yarn create @vitejs/app 명령 이 실행 되면 @vitejs/create-app 리 의 코드 가 실 행 됩 니 다.우 리 는 먼저 이 파일 의 항목 구 조 를 보 자.

template 에서 시작 하 는 폴 더 는 각 프레임 워 크 와 대응 하 는 type:script 버 전의 프로젝트 템 플 릿 입 니 다.관심 을 가지 지 않 아 도 됩 니 다.프로젝트 를 만 드 는 논 리 는 index.js 파일 에 있 습 니 다.이 안에 뭐 가 들 어 있 는 지 살 펴 보 겠 습 니 다.
프로젝트 의존
우선 의존 적 인 도입 이다.

const fs = require('fs')
const path = require('path')
const argv = require('minimist')(process.argv.slice(2))
const prompts = require('prompts')
const {
  yellow,
  green,
  cyan,
  blue,
  magenta,
  lightRed,
  red
} = require('kolorist')
fs,path 는 Nodejs 내장 모듈 이 고 minimist,prompts,kolorist 는 각각 제3자 의존 라 이브 러 리 입 니 다.
  • minimist:명령 행 인 자 를 분석 하 는 도구 입 니 다.문서.
  • prompts:명령 행 대화 도구 입 니 다.문서.
  • kolorist:명령 행 출력 에 색 채 를 가 진 도구 입 니 다.문서.
  • 모듈 구성
    다음 프레임 워 크 모드 의 프로필 은 마지막 으로 모드 이름 의 배열 을 만 듭 니 다.
    
    //      vue react     ,         ,         。
    const FRAMEWORKS = [
      ......
      
      {
        name: 'vue',
        color: green,
        variants: [
          {
            name: 'vue',
            display: 'JavaScript',
            color: yellow
          },
          {
            name: 'vue-ts',
            display: 'TypeScript',
            color: blue
          }
        ]
      },
      {
        name: 'react',
        color: cyan,
        variants: [
          {
            name: 'react',
            display: 'JavaScript',
            color: yellow
          },
          {
            name: 'react-ts',
            display: 'TypeScript',
            color: blue
          }
        ]
      },
      
      ......
    ]
    
    //         
    const TEMPLATES = FRAMEWORKS.map(
      (f) => (f.variants && f.variants.map((v) => v.name)) || [f.name]
    ).reduce((a, b) => a.concat(b), [])
    
    
    그 다음으로.gitignore 파일 의 특수성 으로 인해 모든 프레임 워 크 프로젝트 모델 에서 먼저 만 든gitignore 파일 은 후속 프로젝트 를 만 들 때'gitignore'로 바 꿉 니 다.따라서 코드 에 이름 을 바 꿀 파일 을 저장 할 대상 을 미리 정의 합 니 다.
    
    const renameFiles = {
      _gitignore: '.gitignore'
    }
    
    도구 함수
    핵심 함 수 를 시작 하기 전에 코드 에 정 의 된 도구 함 수 를 살 펴 보 세 요.가장 중요 한 것 은 파일 작업 과 관련 된 세 가지 함수 입 니 다.
    copy
    
    function copy(src, dest) {
      const stat = fs.statSync(src)
      if (stat.isDirectory()) {
        copyDir(src, dest)
      } else {
        fs.copyFileSync(src, dest)
      }
    }
    
    copy 함 수 는 파일 이나 폴 더 src 를 지정 한 폴 더 dest 로 복사 하 는 데 사 용 됩 니 다.src 상태 stat 를 먼저 가 져 옵 니 다.src 가 폴 더 라면 stat.isDirectory()가 true 일 때 아래 에 소 개 된 copyDir 함 수 를 호출 하여 src 폴 더 의 파일 을 dest 폴 더 로 복사 합 니 다.반면 src 가 파일 이 라면 fs.copy FileSync 함 수 를 직접 호출 하여 src 파일 을 dest 폴 더 로 복사 합 니 다.
    copyDir
    
    function copyDir(srcDir, destDir) {
      fs.mkdirSync(destDir, { recursive: true })
      for (const file of fs.readdirSync(srcDir)) {
        const srcFile = path.resolve(srcDir, file)
        const destFile = path.resolve(destDir, file)
        copy(srcFile, destFile)
      }
    }
    
    copyDir 함 수 는 특정한 폴 더 srcDir 의 파일 을 지정 한 폴 더 destDir 에 복사 하 는 데 사 용 됩 니 다.이것 은 먼저 fs.mkdirSync 함 수 를 호출 하여 제 정 된 폴 더 를 만 든 다음 에 fs.readdirSync 를 호출 하여 srcDir 폴 더 에서 가 져 온 파일 을 하나씩 복사 합 니 다.마지막 으로 copy 함 수 를 호출 하여 복사 합 니 다.폴 더 에 있 는 파일 이나 폴 더 가 존재 할 수 있 기 때 문 입 니 다.
    emptyDir
    
    function emptyDir(dir) {
      if (!fs.existsSync(dir)) {
        return
      }
      for (const file of fs.readdirSync(dir)) {
        const abs = path.resolve(dir, file)
        if (fs.lstatSync(abs).isDirectory()) {
          emptyDir(abs)
          fs.rmdirSync(abs)
        } else {
          fs.unlinkSync(abs)
        }
      }
    }
    
    empty Dir 함 수 는 dir 폴 더 의 코드 를 비 우 는 데 사 용 됩 니 다.dir 폴 더 가 존재 하 는 지 여 부 를 판단 하고 존재 하 는 지 여 부 는 이 폴 더 의 파일 을 옮 겨 다 니 며 이 파일 을 구성 하 는 경로 abs 입 니 다.abs 가 폴 더 일 때 empty Dir 함 수 를 재 귀적 으로 호출 하여 이 폴 더 의 파일 을 삭제 한 다음 fs.rmdirSync 를 호출 하여 이 폴 더 를 삭제 합 니 다.abs 가 파일 일 때 fs.unlinksync 함 수 를 사용 하여 이 파일 을 삭제 합 니 다.
    핵심 함수
    다음은 핵심 기능 이 실 현 된 init 함수 입 니 다.
    명령 행 대화 및 폴 더 만 들 기
    우선 명령 행 인자 가 져 오기
    
    let targetDir = argv._[0]
    let template = argv.template || argv.t
    
    const defaultProjectName = !targetDir ? 'vite-project' : targetDir
    
    
    argv._[0.@vitejs/app 을 대표 한 첫 번 째 인자
    template 는 사용 할 모델 이름 입 니 다.
    defaultProjectName 은 우리 가 만 든 프로젝트 이름 입 니 다.
    다음은 prompts 패 키 지 를 사용 하여 명령 행 에서 질문 을 출력 하 는 것 입 니 다.아래 와 같이:

    구체 적 인 코드 는 다음 과 같다.
    
    //                     ,          
    let result = {}
    
    result = await prompts(
      [
        {
          type: targetDir ? null : 'text',
          name: 'projectName',
          message: 'Project name:',
          initial: defaultProjectName,
          onState: (state) =>
            (targetDir = state.value.trim() || defaultProjectName)
        },
        ......
        
      ]
    )
    
    const { framework, overwrite, packageName, variant } = result
    
    const root = path.join(cwd, targetDir)
    
    if (overwrite) {
      emptyDir(root)
    } else if (!fs.existsSync(root)) {
      fs.mkdirSync(root)
    }
    
    template = variant || framework || template
    
    //          
    console.log(`
    Scaffolding project in ${root}...`) const templateDir = path.join(__dirname, `template-${template}`)
    선택 이 완료 되면 우리 가 선택 한 결 과 를 되 돌려 줍 니 다 result
    루트 는 path.join 함 수 를 통 해 구 축 된 전체 파일 경로 입 니 다.
    overwrite 는 우리 가 만 들 같은 이름 의 파일 이 존재 할 때 다시 쓸 지 여부 입 니 다.다시 쓰 려 면 앞의 emptyDir 함수 로 폴 더 를 비 웁 니 다.이 폴 더 가 존재 하지 않 으 면 fs.mkdirSync 를 사용 하여 폴 더 를 만 듭 니 다.
    templateDir 에서 선택 한 템 플 릿 폴 더 이름
    파일 쓰기
    
    const write = (file, content) => {
      const targetPath = renameFiles[file]
        ? path.join(root, renameFiles[file])
        : path.join(root, file)
      if (content) {
        fs.writeFileSync(targetPath, content)
      } else {
          copy(path.join(templateDir, file), targetPath)
      }
    }
    
    const files = fs.readdirSync(templateDir)
    for (const file of files.filter((f) => f !== 'package.json')) {
      write(file)
    }
    
    const pkg = require(path.join(templateDir, `package.json`))
    
    pkg.name = packageName
    
    write('package.json', JSON.stringify(pkg, null, 2))
    
    const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm'
    
    //                  ,                   
    console.log(`
    Done. Now run:
    `) if (root !== cwd) { console.log(` cd ${path.relative(cwd, root)}`) } console.log(` ${pkgManager === 'yarn' ? `yarn` : `npm install`}`) console.log(` ${pkgManager === 'yarn' ? `yarn dev` : `npm run dev`}`) console.log()
    write 함 수 는 두 개의 인자 file 과 content 를 받 아들 이 고 두 가지 기능 이 있 습 니 다.
  • 지정 한 파일 file 에 지정 한 내용 content 를 기록 하고 fs.writeFileSync 함 수 를 호출 하여 내용 을 파일 에 기록 합 니 다.
  • 모드 폴 더 의 파일 을 지정 한 폴 더 에 복사 하고 앞에서 소개 한 copy 함 수 를 호출 하여 파일 의 복 사 를 실현 합 니 다.
  • 그리고 fs.readdirSync 를 호출 하여 모듈 폴 더 의 파일 을 읽 고 프로젝트 폴 더 로 복사 합 니 다.(그 중에서 필터 할 package.json 파일 은 name 필드 가 수정 되 어야 하기 때 문 입 니 다)마지막 으로 package.json 파일 을 기록 합 니 다.
    작은 매듭
    Vite 의 create-app 가방 의 실현 은 320 줄 정도 의 코드 만 있 지만 각종 장면 의 호 환 처 리 를 고려 합 니 다.공 부 를 마 친 후에 이런 CLI 도 구 를 스스로 실현 하 는 것 도 그리 어 려 운 일이 아니다.
    여기 서 Vite 프로젝트 의 실현 절차 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 Vite 프로젝트 의 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기