《前端那些事》從0到1開發簡單腳手架

樹醬但願將前端的樂趣帶給你們 本文已收錄 github.com/littleTreem… 喜歡就star✨前端

上一篇樹醬講《前端工程化那些事》,聊到腳手架,不過期間比較倉促,致使內容較少,而在我實踐開發中,隨着新項目越來越多,腳手架工具就起到提升效能的做用,藉此機會跟小夥伴們分享下我是如何從0到1開發一個簡單腳手架vue

1.什麼是腳手架

腳手架用於快速生成新項目的目錄模板,並集成一系列體系化工具的安裝,可以提高前端開發人員的效率,減小copy操做node

目前比較主流的腳手架:react

  • Vue腳手架:Vue-cli
  • React腳手架:create-react-app
  • Yeoman

2.我指望的腳手架

而我所指望的腳手架是怎麼樣的呢?git

當我要開啓一個新項目的開發,能夠快速生成新項目的目錄模板,而這個目錄結構是每一個項目統一個模版規範(目錄規範),同時也設定了通用的配置包括以下github

  • 通用的Webpack配置(vue cli 3x 以上是vue.config.js)
  • 統一的Eslint 校驗規則:如Airbnb、eslint-plugin-vue等(eslintConfig)
  • 統一的單元測試框架配置:單元測試覆蓋率、測試的目錄等
  • 統一的Dockerfile和jenkinsfile (用來打包成鏡像和部署流水線定義)
  • 統一babel的配置(.babelrc或babel.config.js)
  • 統一的常量配置(緩存字段等等)
  • 不一樣環境的配置文件(development、test、production)

沒有腳手架,我只能經過copy拷貝代碼來完成,這樣繁瑣又機械化的操做浪費大量時間,並且還可能在拷貝過程當中,由於某個細節出錯,致使項目出錯,排查問題又耗時。或許你可能會想,咱們不是能夠用vue或者react官方的腳手架來生成模版嗎?是,可是這種方式建立的模版不必定符合你內部結構化標準web

爲了解決上述問題,腳手架就起到一個相當重要的角色,咱們能夠經過腳手架來約束好規範,統一的配置,來打通新項目的開發工具鏈,一方面提高開發效率,一方面則提升項目對接可維護性及新員工熟悉項目簡易性。shell

3.開發腳手架

3.1 如何開發

若是是要開發一個高度可定製化的腳手架,須要考慮的因素不少,由於某種限制,選擇了一種簡易的方式來實現內部的腳手架工具,遠離就是經過準備兩個模版,一個是pc端的,另外一個是mobile端的模版,而後用git管理起來,我須要以下工具:npm

  • 可用於控制檯選擇的工具:inquirer
  • 可處理控制檯命令的工具:commander
  • 可改變輸出log顏色的工具:chalk
  • 可執行shell命令的工具: child_process

入口文件 index.jsjson

#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const commander = require('commander');
const inquirer = require('inquirer');
const checkDire = require('./utils/checkDire.js');
const { exec } = require('child_process');
const { version } = require('../package.json');
const { promptTypeList } = require('./config');

//version 版本號
commander.version(version, '-v, --version')
  .command('init <projectName>')
  .alias("i")
  .description("輸入項目名稱,初始化項目模版")
  .action(async (projectName,cmd) => {
    await checkDire(path.join(process.cwd(),projectName),projectName);   // 檢測建立項目文件夾是否存在
    inquirer.prompt(promptTypeList).then(result => {
      const {url, gitName, val} = result.type;
      console.log("您選擇的模版類型信息以下:" + val);
      console.log('項目初始化拷貝獲取中...');
      if(!url){
        console.log(chalk.red(`${val} 該類型暫不支持...`));
        process.exit(1);
      }
      exec('git clone ' + url, function (error, stdout, stderr) {
        if (error !== null) {
          console.log(chalk.red(
            `clone fail,${error}`
          ));
          return;
        }
        fs.rename(gitName, projectName, (err)=>{
          if (err) {
            exec('rm -rf '+gitName, function (err, out) {});
            console.log(chalk.red(`The ${projectName} project template already exist`));
          } else {
            console.log(chalk.green(`The ${projectName} project template successfully create(項目模版建立成功)`));
          }
        });
      });
    })
  });
commander.parse(process.argv);

複製代碼

這裏定義的是npm包命令bin的入口文件

須要注意在文件前面定義#!/usr/bin/env node

#!/usr/bin/env node設置後,可讓系統動態的去查找node,已解決不一樣機器不一樣用戶設置不一致問題

檢測目錄是否存在

// utils/checkDire.js
const fs = require('fs');
const chalk = require('chalk');
const path = require('path');

module.exports = function (dir,name) {
  let isExists = fs.existsSync(dir);
  if (isExists) {
    console.log(chalk.red(
      `The ${name} project already exists in  directory. Please try to use another projectName`
    ));
    process.exit(1);
  }
複製代碼

配置文件

// config/index.js
配置文件
/*
  @dest: 使用配置文件
  @Author: tree
 */
module.exports  = {
  promptTypeList:[{
      type: 'list',
      message: '請選擇拉取的模版類型:',
      name: 'type',
      choices: [{
        name: 'mobile',
        value: {
          url: '',
          gitName: 'vue-web-template',
          val:'移動端模版'
        }
      },{
        name: 'pc',
        value: {
          url: 'https://github.com/littleTreeme/vue-web-template.git',
          gitName: 'vue-web-template',
          val:'PC端模版'
        }
      }]
  }],
};
複製代碼

源碼連接:github.com/littleTreem… 若是你以爲實用請給個🌟支持,在此感謝

3.2 工具詳解

  • inquirer

一個用戶與命令行交互的工具

基本用法 🔗使用文檔

const inquirer = require('inquirer');

const promptList = [
     type: 'list',
     message: '請選擇拉取的模版類型:',
     name: 'type',
      choices: ['mobile','pc']
];

inquirer.prompt(promptList).then(type => {
    console.log(type); // 返回 mobile 或 pc
})
複製代碼

場景以下

  • commander

commander是一個輕巧的nodejs模塊,提供了用戶命令行輸入和參數解析強大功能

使用到的commander API 🔗使用文檔

const commander = require('commander');
commander.version(version, '-v, --version')
  .command('init <projectName>') 
  .alias("i") 
  .description("輸入項目名稱,初始化項目模版") 
  .action(async (projectName,cmd) => {
      console.log(projectName,'你輸入的<projectName>')
  })
commander.parse(process.argv);
  
// command – 定義命令行指令,後面可跟上一個name,用空格隔開
// alias – 定義一個更短的命令行指令
// description – 描述,它會在help裏面展現
// option – 定義參數
// action – 註冊一個callback函數
// parse - 解析命令行
 
複製代碼
  • chalk

node終端樣式庫,讓你的日誌樣式更美觀,主要用chalk來區別錯誤與成功的日誌

如何使用 🔗使用文檔

const chalk = require('chalk');

// 報錯日誌用紅色來顯示
chalk.red(`The project already exists in  directory. Please try to use another projectName`));

// 成功日誌用綠色來顯示
chalk.green(`The project template successfully create(項目模版建立成功)`);
複製代碼

3.3 如何使用

能夠先經過試着本地安裝嘗試流程閱讀使用文檔

以下所示是本身開發的一個kdv-cli運行時的示意圖

那麼 kdv-cli 命令是怎樣映射進去的?,緣由在於 package.json 裏面的 定義了 bin 字段;

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

我選擇pc類型,而後建立名爲 test的項目(暫還不支持mobile)

重複建立則報錯

拉取後的項目目錄結構以下所示:

4.注意事項

  • 注意事項

當你完成腳手架開發時,你想本地測試是否成功運做,會出現這種狀況

這是由於你本地找不到命令執行的路徑,沒有映射到bin中去,那麼如何在本地測試剛開發玩的腳手架工具命令,那就是用npm link,以下所示便可

5.結尾

經過上文所述,咱們就從0到1完成kdv-cli腳手架開發 ,該工具或許不太適用於每一個場景,但能夠梳理一個簡單的腳手架的搭建過程,爲後期作更全面、功能更強大的腳手架奠基基礎,若是你喜歡,請給樹醬點個✨ github.com/littleTreem…

往期文章

相關文章
相關標籤/搜索