腳手架閒聊 | 七日打卡

楔子

前端工程化日益盛行,腳手架成爲了咱們平常開發中必不可少的東西,例如:vue-cli、react-create-app 等等。前端

使用腳手架,咱們能夠很方便的簡化咱們的開發流程,有效的提升咱們的研發能效vue

例如咱們須要從零開始搭建一個項目,首先須要去建立目錄,在個目錄下去建立相應初始化的文件,去配置 webpack、gulp、rollup 等模塊打包器,這每每會花費咱們一天甚至數天的時間。然而腳手架只須要在命令行敲入簡簡單單的一行命令,便可在短短的幾分鐘內爲你建立一個項目模板,極大程度上節省了咱們的時間成本。java

相信大部分的同窗對腳手架的認識只停留在使用上面,今兒咱們就來了解一下腳手架的原理。node

注:本文章是使用 Node.js 進行腳手架開發的react

腳手架的做用

你們能夠想想腳手架的做用是什麼?開發腳手架的核心目標是什麼?webpack

沒錯,就是提高研發效能!git

腳手架的核心價值

  1. 自動化:項目重複、代碼拷貝、git 操做、發佈上線操做
  2. 標準化:項目建立、git flow、發佈流程、回滾流程
  3. 數據化:研發過程系統化、數據化、使研發過程能夠被量化

和自動化構建工具的區別

有的同窗可能會問到,世面上已經有了 jenkins、travis 等自動化構建工具了,並且也很成熟,爲何還要開發相關的腳手架?web

  1. 需求不知足:jenkins、travis 一般在 git hooks 中觸發,須要在服務端執行,沒法覆蓋研發人員本地的功能,如:建立項目自動化、本地 git 操做自動化等
  2. 定製複雜:jenkins、travis 定製過程須要開發插件,其過程較爲複雜,須要使用 java 語言,對前端開發不夠友好

腳手架的本質

腳手架本質上來講,其實就是一個操做系統的客戶端。vue-cli

它經過命令行來執行,例如:npm

vue create vue-project
複製代碼

腳手架的執行原理

爲何咱們在命令行中輸入 vue create vue-project 後就能執行呢?

用戶在命令行中輸入了命令 vue create vue-project ,操做系統首先會在全局的環境變量裏面去查找 vue 這個環境變量,找到後就會去執行它,沒有找到就會報錯,以下圖所示:

腳手架的實現原理

經過 npm 全局安裝一個腳手架例如 @vue/cli 後,會去解析 package.json 文件中的 bin 配置,而後會去在 node 的安裝目錄下的 bin 目錄中,建立一個軟鏈接而且鏈接到軟件包中,軟鏈接的名稱就是 bin 配置的 key(鍵值對的鍵),鏈接的文件就是 bin 配置的 value(鍵值對的值)value 指向的文件中須要設置 #! /usr/bin/env node 來標識文件執行的方法

實現一個最簡單的腳手架

第一步:咱們須要建立一個文件夾 test-cli;
第二步:在命令行中,進入到 test-cli 文件夾,而後執行 npm init 初始化項目;
第三步:修改 package.json 文件,在裏面的配置項里加上以下的:

{
    ...
    "bin": {
      "test-cli": "./bin/index.js"
    },
    ...
}
複製代碼

第四步:在 test-cli 裏面新建一個 bin 文件夾,而且在裏面建立一個 index.js 文件,接下來打開 index.js 文件在裏面第一行寫上 #! /usr/bin/env node;
第五步:能夠寫上一些內容了,好比 console.log('xxx') 滑稽臉;
第六步:在命令行中,進入到 test-cli 文件夾,而後執行 npm link;
第七步:在命令行中,輸入 test-cli 而且回車,你就會發如今命令行中就會打印出 xxx;

這就是一個最簡單的腳手架了,若是你想作的更好一點的,好比經常使用腳手架的一些命令式操做能夠了解一下 yargs、commander 兩個插件,這裏給上一個基於 commander 的註冊命令的代碼,有興趣的同窗能夠複製到剛剛的 index.js 裏面執行一下 test-cli --help

#! /usr/bin/env node

const commander = require('commander')
const pkg = require('../package.json')

// 獲取 commander 的單例
// const { program } = commander

// 手動實例化一個 commander 實例
const program = new commander.Command()

program
    .name(Object.keys(pkg.bin)[0])
    .usage('<command> [options]')
    .version(pkg.version)
    .option('-d, --debug', '是否開啓調試模式', false)
    .option('-e, --env <envName>', '獲取環境變量名稱', false)

// addCommand 註冊子命令
const service = new commander.Command('service')
service
    .command('start [port]')
    .description('start service at some port')
    .action((prot, cmdObj) => {
        console.log('do server start', prot)
    })
service
    .command('stop')
    .description('stop service')
    .action(() => {
        console.log('do server stop')
    })


program.addCommand(service)

program.on('option:debug', () => {
    console.log('debug')
})

program.on('command:*', (obj) => {
    console.log('未知的命令', obj)
    const availableCommands = program.commands.map(cmd => cmd.name())
    console.log('可用的命令', availableCommands)
})

program    
    .parse(process.argv)

// console.log(program.debug)
// console.log(program.env)
// console.log(program.opts())
複製代碼

總結

腳手架的開發博大精深,它爲我打開了一個新世界的大門,同時也讓我對 Node.js 也有了更深刻的瞭解。也是突破現有技術瓶頸的一個方向,也是做爲一個高級前端開發工程師必需要掌握的技能。

相關文章
相關標籤/搜索