前端工程化 搭建自己的腳手架工具詳細步驟

我們開發時使用vue的話,一般不會是自己去配置相關的配置,而是會直接使用vue-cli工具,使用react時會用create-react-app,這裏我們來試着搭建一個自己的腳手架工具

就我現在所會的搭建方法,

  1. 將模板放到github倉庫中,通過執行命令來將github上的代碼拉取到本地
  2. 使用yeoman-generator,將模板放在generator中,通過yo來將generator中的模板拉取到本地

所以簡單來說,就是將代碼放到某個地方,在需要的時候將代碼拉取到本地,但除了將相關文件拉取到本地外,用過腳手架的同學肯定知道,在初始化的時候,腳手架會提出一些問題,根據我們輸入選擇的不同,最終的配置也有所不同,所以腳手架並非簡單的git clone和yo <name>就可以解決的

第二種搭建的方法我之前寫的一個npm包generator-wxfile已經有用過了,在1.1.2版本中通過使用yeoman-generator來拉取文件,使用co-prompt來向用戶提出配置問題,根據用戶鍵入將相應的文件拉取到本地,並且修改文件中部分內容

這裏我要採用第一種搭建的方法

這裏我要用到幾個npm包

inquirer:用於向用戶提出問題和獲取回答
chalk:改變命令行打印內容的樣式
child_process:用於執行命令行的指令
commander:用於定義自己的命令

初始化腳手架

這裏首先初始化自己的腳手架

mkdir scav-cli
cd scav-cli
npm init

初始化之後,在package.json中把相應的開發依賴寫入

"dependencies": {
    "chalk": "^3.0.0",
    "child_process": "^1.0.2",
    "commander": "^4.1.1",
    "inquirer": "^7.0.4"
},
npm i

將相關的npm包下載到node_modules中,接下來就開始腳手架的相關搭建,在bin文件夾中創建scav.js文件用於定義相關命令

定義相關命令

首先將定義腳手架的文件路徑,將相關的依賴包引入,定義腳手架的版本

#!/usr/bin/env node --harmony
'use strict'
// 定義腳手架的文件路徑,__dirname是當前文件所在的路徑
process.env.NODE_PATH = __dirname + '/../node_modules/'

const program = require('commander')

// 獲取package.json中的version來做爲項目的版本號 
program.version(require('../package').version)
// 定義腳手架的用法,在program.help方法中會顯示
program.usage('<command>')

給腳手架定義初始化的命令

/*
command爲執行的命令
description爲命令的描述
alias爲簡寫
action爲命令相應的操作
*/
program
    .command('init')
    .description('init a vue-based project')
    .alias('i')
    .action(()=>{
        console.log('我是初始化的方法')
    })
   
// program.parse(arguments)會處理參數,沒有被使用的選項會被存放在program.args數組中
program.parse(process.argv)

在根目錄下執行下面的命令

node bin/scav init

出現如圖情況就說明配置成功
在這裏插入圖片描述
爲了在全局使用,在package.json中添加bin相關配置

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

然後使用npm link鏈接到全局,就可以直接在命令行使用scav init了,如圖
在這裏插入圖片描述
在最後添加命令沒有被定義的操作

// 如果有選項被放在program.args,即沒有被program.parse處理,則默認使用program.help()將npm包可以執行的命令打印出來
// 可以通過program.on('--help', function(){})來自定義help
if (program.args.length) {
    program.help()
}

我們可以在判斷之前將program.args打印出來

console.log('program.args: ', program.args);

在這裏插入圖片描述
在這裏插入圖片描述
可以看到,init被處理了,所以program.args裏沒有init,而ttt沒被定義,沒有被處理,所以被寫入program.args中

編寫具體操作

接下來就詳細定義相關的初始化方法了,我們在根目錄下創建一個command文件夾用來存放命令相關操作的文件,創建一個init.js來寫初始化相關操作
文件目錄
接下來編寫init.js,引入相關的依賴包,導出一個方法供scav.js調用

// init.js
const inquirer = require('inquirer')
const chalk =require('chalk')
const {exec} = require('child_process')
chalk.level = 3 // 設置chalk等級爲3

module.exports = ()=>{
    console.log(chalk.green('開始初始化文件'))
    console.log(chalk.gray('初始化中...'))
    console.log(chalk.green('初始化完成'))
}

在init.js文件中調用init.js文件

program
    .command('init')
    .description('init a vue-based project')
    .alias('i')
    .action(()=>{
        require('../command/init.js')()
    })

再執行初始化命令試試,如圖就成功了
初始化文件命令行圖片
接下來使用inquirer來提問用戶項目名,如果項目名爲空,則給出提示並讓用戶重新輸入

module.exports = ()=>{
    console.log(chalk.green('開始初始化文件'))
    inquirer.prompt([{
        type:'input', // 問題類型爲填空題
        message:'your  projectName:', // 問題描述
        name:'projectName', // 問題對應的屬性
        validate:(val)=>{ // 對輸入的值做判斷
            if(val===""){
                return chalk.red('項目名不能爲空,請重新輸入')
            }
            return true
        }
    }]).then(answer=>{
        console.log(chalk.gray('初始化中...'))
        console.log(chalk.green('初始化完成'))
    })
}

效果如圖
在這裏插入圖片描述
接下來通過child_process中的exec來執行git clone命令

module.exports = ()=>{
    inquirer.prompt([{
        type:'input', // 問題類型爲填空題
        message:'your  projectName:', // 問題描述
        name:'projectName', // 問題答案對應的屬性,用戶輸入的內容被存儲在then方法中第一個參數對應的該屬性中
        validate:(val)=>{ // 對輸入的值做判斷
            if(val===""){
                return chalk.red('項目名不能爲空,請重新輸入')
            }
            return true
        }
    }]).then(answer=>{ // 通過用戶的輸入進行各種操作
        console.log(chalk.green('開始初始化文件\n'))
        console.log(chalk.gray('初始化中...'))
        const gitUrl = 'https://github.com/QZEming/vue-temp.git'
        exec(`git clone ${gitUrl} ${answer.projectName}`,(error,stdout,stderr)=>{
            if (error) { // 當有錯誤時打印出錯誤並退出操作
                console.log(chalk.red(error))
                process.exit()
            }
            console.log(chalk.green('初始化完成'))
            process.exit() // 退出這次命令行操作
        })
    })
}

出現如圖情況就配置成功了
在這裏插入圖片描述
發現本地多了一個文件夾
在這裏插入圖片描述

修改生成的文件

但是打開package.json,發現name是vue-temp,這可不符合我們的預期,所以我們要引入一個fs模塊,通過fs模塊來讀寫這個package.json,將之前輸入的項目名寫入,通過process.cwd()來獲取當前命令行執行的路徑,代碼如下

const fs = require('fs')
module.exports = ()=>{
    inquirer.prompt([{
        type:'input', // 問題類型爲填空題
        message:'your  projectName:', // 問題描述
        name:'projectName', // 問題答案對應的屬性,用戶輸入的內容被存儲在then方法中第一個參數對應的該屬性中
        validate:(val)=>{ // 對輸入的值做判斷
            if(val===""){
                return chalk.red('項目名不能爲空,請重新輸入')
            }
            return true
        }
    }]).then(answer=>{ // 通過用戶的輸入進行各種操作
        console.log(chalk.green('開始初始化文件\n'))
        console.log(chalk.gray('初始化中...'))
        const gitUrl = 'https://github.com/QZEming/vue-temp.git'
        exec(`git clone ${gitUrl} ${answer.projectName}`,(error,stdout,stderr)=>{ // 克隆模板並進入項目根目錄
            if (error) { // 當有錯誤時打印出錯誤並退出操作
                console.log(chalk.red('拷貝文件失敗'))
                process.exit()
            }
            fs.readFile(`${process.cwd()}/${answer.projectName}/package.json`,(err,data)=>{
                if(error){
                    console.log(chalk.red('讀取文件失敗'))
                    process.exit()
                }
                data= JSON.parse(data.toString())
                data.name = answer.projectName
                fs.writeFile(`${process.cwd()}/${answer.projectName}/package.json`,JSON.stringify(data,"","\t"),err=>{
                    if(err){
                        console.log(chalk.red('寫入文件失敗'))
                        process.exit()
                    }
                    console.log(chalk.green('初始化完成'))
                    process.exit() // 退出這次命令行操作
                })
            })
        })
    })
}

打開package.json發現與我們輸入的項目名一樣即修改成功

npm發佈的相關內容可見前端工程化 發佈一個自動生成微信開發文件的npm包
我已經發布了這個腳手架到npm上,相關代碼放在github上,也可以npm i scav-cli -g試試相關的內容

發佈了193 篇原創文章 · 獲贊 13 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章