手摸手教你搭個腳手架


目錄

  1. 腳手架
  2. 全局命令
  3. 交互式輸入
  4. 拉取遠程倉庫代碼
  5. 優化
  6. 總結

1、腳手架

今天工地的磚有點燙,我抬頭望了望天,思考了半分鍾,決定為了以后搬磚方便,先搭個腳手架:

不好意思,拿錯了,是這個:

相信很多小伙伴都用過vue-cli、create-react-app或angular-cli之類的腳手架,一個命令行就能快速搭起項目框架,告別刀耕火種的復制粘貼,分分鍾解放生產力。

作為一個有追求的切圖仔,這種摸魚神器,必須立馬安排。

好了,那么問題來了:什么是腳手架?

從表現形式上來看,腳手架主要有以下幾個特點:

  1. 一個能全局執行的命令;
  2. 能實現交互式輸入,比如輸入項目名稱,選擇配置項等;
  3. 能自動拉取github或gitlab遠程倉庫的代碼。

當然高級的腳手架肯定不止這么點功能,不過我們先從最簡單的實現起。

2、全局命令

2.1 基本原理

先拆包觀察一下,類似vue-cli這類的全局命令是如何實現的。
首先找到vue-cli的安裝路徑,全局安裝可以通過npm config get prefix找到路徑,比如我的windows系統就是
C:\Users\用戶名\AppData\Roaming\npm:

可以看到這個目錄下有很多與全局命令同名的文件,以及一個node_modules文件夾。我們全局安裝的依賴包就在node_modules里。找到@vue\cli,這個就是vue-cli的源碼包。

vue-cli的源碼目錄

vue-cli源碼包中的package.json有這樣一個關鍵配置:

  "bin": {
    "vue": "bin/vue.js"
  },

這個bin/vue.js腳本必須以#!/usr/bin/env node開頭,

當npm全局安裝時,就會根據這個配置,生成對應的同名可執行文件。

而當我們運行vue時,系統就會以node程序來運行vue.js。

npm官方文檔中提供了npm link命令,用以讓用戶將自定義的腳手架生成一個全局命令。

npm link主要做了兩步操作:

  • 一是在npm全局安裝路徑下的node_modules文件夾里生成一個鏈接文件,這個鏈接文件指向執行該命令的文件夾,也就是我們的腳手架源碼文件夾;
  • 二是在npm全局安裝路徑下生成與配置bin里同名的可執行文件。

所以,通過npm link,我們就可以生成一個node全局命令

npm link官方文檔:https://docs.npmjs.com/cli/v6/commands/npm-link。

2.2 全局命令的實現

話不多說,先來擼一個全局命令。

1)執行npm init初始化一個package.json

2)在package.json里加上bin配置:

  "bin": {
    "test-cli": "./test.js"
  },

3)添加對應的執行腳本文件test.js

#! /usr/bin/env node
console.log("Hello! My CLI!");

4)在package.json同級目錄下執行npm link

5)在控制台運行一下我們定義的全局命令test-cli,看到輸出結果:

全局命令生效

完成!

3、交互式輸入

通過上述操作,用戶已經可以通過全局命令執行到我們的test.js文件,剩下的功能我們就可以在js里去自由發揮了。

Node社區有着數量龐大的第三方模塊,藉由這些模塊我們可以快速開發實現想要的功能。

inquirier就是其中之一,目前在github上有14.5k的star,它的目標就是“致力於成為一個易於嵌入且美觀的命令行工具”。顧名思義,通過inquirier模塊,我們可以在命令行中實現與用戶的輸入交互。

我們需要知道用戶要創建的項目名稱是什么,以及用戶想要下載哪個遠程倉庫的代碼:

const inquirer = require("inquirer");

inquirer
    .prompt([
        {
            type: "input",
            name: "project",
            message: "項目名稱",
        },
        {
            type: "list",
            name: "tpl",
            message: "請選擇模板",
            choices: ["vue", "react"],
        }
    ])
    .then((res) => {
        console.log(res);
        const { project, tpl } = res;
        // project就是用戶輸入的項目名稱
        // tpl就是用戶選擇的模板
    });

這段代碼就是為用戶提供了一個input輸入選項,來輸入項目名稱,以及一個list列表選項,來選擇要下載的模板(之后我們再根據這個模板名稱去對應的倉庫地址進行下載)。

inquirer交互效果

inquirer還有更多的選項功能,感興趣的小伙伴可以去官方文檔上自由探索:https://github.com/SBoudrias/Inquirer.js。

4、拉取遠程倉庫代碼

現在我們已經知道用戶要下載的是哪個模板代碼,也知道這些模板代碼對應的下載地址:

const stores = [
    {
        name: "vue",
        url: "https://github.com/vuejs/vue.git"
    },
    {
        name: "react",
        url: "https://github.com/facebook/react.git"
    }
]

拉取github或者gitlab遠程倉庫代碼的第三方模塊也有好幾個,我選用的是nodegit,這個項目在github上目前有4.9k的star,用起來也很簡單:

const Git = require("nodegit");

/** 克隆遠程倉庫代碼 */
// url: 源碼倉庫地址; path: 要下載的目標路徑; cb: 下載結束后的回調函數
const gitClone = (url, path, cb)=>{
    console.log("正在下載遠程倉庫代碼...")
    console.log(url)
    Git.Clone(url, path)
       .then(function(res) {
            console.log("下載完成")
            cb(true)
        })
        .catch(function(err) { console.log("下載失敗"+err);cb(false) });
}

nodegit官網地址:
https://github.com/nodegit/nodegit

至此三個基本功能都已實現!

5、優化

深諳摸魚之道的我想了想,覺得還能更進一步,比如下載完源碼,再幫我自動安裝下依賴包啦:

const process = require('child_process');

/** 安裝依賴包 */
const install = (path)=>{ // path是源碼模板中package.json所在的路徑
    console.log("正在安裝依賴包...")
    const cmd = 'cd '+path+' && yarn';
    process.exec(cmd, function(error, stdout, stderr) {
        console.log(error);
        console.log(stdout);
        console.log(stderr);
        console.log("安裝完成")
    });
}

愉快地摸會兒魚

之前看到很多腳手架出場都自帶拉風的藝術字,作為一個有追求的切圖仔,這個必須安排!
這個也是用到了一個第三方模塊figlethttps://github.com/patorjk/figlet.js):

const figlet = require('figlet');   
figlet('My CLI!', {horizontalLayout:"full"}, function(err, data) {
    if (err) {
        console.log('Something went wrong...');
        console.dir(err);
        return;
    }
    console.log(data)
    // do something...
});

瞬間高大上有木有o

很多腳手架還提供了參數配置、幫助信息等功能,這個大多是通過commander模塊實現的(https://github.com/tj/commander.js,20.7k star),這里就不詳細展開了,我在demo項目里也簡單實現了下,確實很強大很好用。

Demo已開源:https://github.com/youzouzou/testcli

這個demo只是簡單地實現了腳手架的基本功能,探索了一下幾個node模塊的用法,還有很多需要優化的點。進一步學習的最好辦法就是去看那些成熟的腳手架源碼,然后去模仿去實踐,再結合實際情況,摸索出最適合自己團隊的方案。

6、總結

工欲善其事,必先利其器。

實際上腳手架並不拘泥於上面的實現形式,凡是能提高效率的工具,在某種意義上都可以稱之為腳手架。

模仿只是最初級的階段,創新才是真正的開始。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM