【手把手帶你擼一個腳手架】第四步, 通過擼碼獲取專案資訊
系列文章:
- ofollow,noindex">【手把手帶你擼一個腳手架】第一步, 建立第一個命令
- 【手把手帶你擼一個腳手架】第二步, 搭建開發環境
- 【手把手帶你擼一個腳手架】第三步, 獲取 github 專案資訊
- 【手把手帶你擼一個腳手架】第四步, 通過擼碼獲取專案資訊
- 【手把手帶你擼一個腳手架】第五步, 擼完收工
前面的章節中我們已經能夠獲取到命令列中輸入的引數, 也能通過 gayhub 開放 api 中獲取到專案模板資訊, 這裡我們開始把之前的功能連綴起來 ^_^

本節用到的工具較多, list 一哈:
- 獲取命令列指令commander
- 命令列互動工具 inquirer.js
- 命令列顯示載入中ora
- ajax 封裝庫axios
首先展示一下目錄結構 程式碼地址

各個檔案介紹
bin/learn.js
#!/usr/bin/env node require('../'); 複製程式碼
仍然作為專案的引導檔案, 直接引入專案根目錄下的 index.js
index.js
require('babel-register'); const babel = require('@babel/core'); const babelPresetLatestNode = require('babel-preset-latest-node'); babel.transform('code();', { presets: [[babelPresetLatestNode, { target: 'current', }]], }); require('babel-polyfill'); require('./src'); 複製程式碼
根目錄下的 index 作為專案的入口檔案, 它的職責主要是相容 es6, 並匯入專案主檔案 src/index.js
src/index.js
// colors console.log 文字新增字型顏色, 美觀 import 'colors'; // 接收命令列引數, 提供基礎資訊提示功能 import commander from 'commander'; // 內部模組 import { existsSync } from 'fs'; import { resolve } from 'path'; import { version } from '../package.json'; commander.version(version) .parse(process.argv); // 獲取命令列中傳入的第一個引數 const [todo = ''] = commander.args; // 判斷如果 command 目錄下是否存在使用者輸入的命令對應的檔案 if (existsSync(resolve(__dirname, `command/${todo}.js`))) { require(`./command/${todo}.js`); } else { console.log( ` 你輸入了未知指令, 小哥哥我已經受不了掛了... `.red, ); process.exit(-1); } 複製程式碼
這個是專案的主檔案, 也是整個程式的 總控 . 正如註釋, 執行命令前, 從這裡檢測我們的命令目錄下是否已經存在了使用者請求的命令, 避免了使用者誤操作程式報錯的風險.
command/download.js
// 命令管理 import commander from 'commander'; // 命令列互動工具 import inquirer from 'inquirer'; // 命令列中顯示載入中 import ora from 'ora'; import Git from '../tools/git'; class Download { constructor() { this.git = new Git(); this.commander = commander; this.inquirer = inquirer; this.getProList = ora('獲取專案列表...'); this.getTagList = ora('獲取專案版本...'); this.downLoad = ora('正在加速為您下載程式碼...'); } run() { this.commander .command('download') .description('從遠端下載程式碼到本地...') .action(() => { this.download(); }); this.commander.parse(process.argv); } async download() { let getProListLoad; let getTagListLoad; let repos; let version; try { getProListLoad = this.getProList.start(); repos = await this.git.getProjectList(); getProListLoad.succeed('獲取專案列表成功'); } catch (error) { console.log(error); getProListLoad.fail('獲取專案列表失敗...'); process.exit(-1); } if (repos.length === 0) { console.log('\n可以開發的專案數為 0, 肯定是配置錯啦~~\n'.red); process.exit(-1); } const choices = repos.map(({ name }) => name); const questions = [ { type: 'list', name: 'repo', message: '請選擇你想要開發的專案型別', choices, }, ]; const { repo } = await this.inquirer.prompt(questions); // 獲取專案的版本, 這裡預設選擇確定專案的最近一個版本 try { getTagListLoad = this.getTagList.start(); [{ name: version }] = await this.git.getProjectVersions(repo); getTagListLoad.succeed('獲取專案版本成功'); } catch (error) { console.log(error); getTagListLoad.fail('獲取專案版本失敗...'); process.exit(-1); } console.log(`您選擇的專案是${repo}, 即將下載版本${version}`); } } const D = new Download(); D.run(); 複製程式碼
command 目錄下存放的是我們整個專案中所有的命令檔案, 不同的命令對應不同的檔案, 體現了單一職責的設計. download 命令用到了我們上一節中提到的兩個介面(即獲取專案列表和獲取版本號列表)有疑問的同學請回頭參考系列文章第三步 ^_^.
tools/git.js
import request from './request'; import { orgName } from '../../config'; class Git { constructor() { this.orgName = orgName; } getProjectList() { return request(`/orgs/${this.orgName}/repos`); } getProjectVersions(repo) { return request(`/repos/${this.orgName}/${repo}/tags`); } getProjectUrl() { } downloadProject() { } } export default Git; 複製程式碼
此檔案是 git 相關的操作的檔案, 由於腳手架的核心功能就是獲取專案的 github 地址, 並下載, 所以我的 Git 類規劃了以上幾個功能, 獲取專案列表 獲取專案版本號列表 獲取專案地址 下載專案
, 雖然後兩個功能在這一節還用不到, 我也先留下了程式碼樁
tools/request.js
import axios from 'axios'; import { baseURL } from '../../config'; const instance = axios.create({ baseURL, timeout: 1e4, }); // Add a request interceptor instance.interceptors.request.use(config => config, error => Promise.reject(error)); // Add a response interceptor instance.interceptors.response.use(response => response.data, error => Promise.reject(error)); export default instance; 複製程式碼
這個檔案僅僅是對 axios 做了一層簡單的封裝, 封裝的手法我還不是掌握的很好, 如果有精通的小夥伴歡迎評論區賜教.

config/index.js
// github 介面基礎地址 export const baseURL = 'https://api.github.com'; // organization 名稱 export const orgName = 'learn-cli-organization'; 複製程式碼
作為整個專案的配置檔案, 承擔了儲存專案執行過程中需要的配置資訊的功能.
介紹完幾個檔案, 感到如釋重負. 如果有手懶的小夥伴, 可以直接 github clone 本階段程式碼 按照第一步的方法配置即可
ps: git clone https://github.com/luoquanquan/learn-cli.git
ps: git checkout 0.0.1
ps: 完成後要執行 npm i
和 npm link
的喲 ^_^
驗證程式碼
終於到了驗證的環節. 小夥伴們, 自己寫完或者 git clone 完程式碼以後可以開啟終端啦, 484 有點小小的雞凍 ^_^

輸入 learn download

出現上圖所示的專案名稱和版本號, 說明我們已經通過程式碼獲取 git 專案資訊成功啦.

下集預告: 到現在, 我們已經能夠從 github 獲取到專案的名稱和版本號, 下一步會嘗試把專案 download 到本地用到了工具download-git-repo, 熱愛動手的小夥伴已經可以開始著手啦, 說不定下一步就是你來寫喲 :smile: