前端工程化之腳手架工具

腳手架工具

常用腳手架工具

  • React項目create-react-app
  • Vue項目vue-cli
  • Angular項目angular-cli
  • Yeoman通用型腳手架工具
  • Plop創建一個組件/模塊所需要的文件(類似於Yeoman的sub-generator)

腳手架工具的工作原理

使用node.js來開發一個小型腳手架。

  • 創建sample-scaffolding文件夾,使用npm init初始化
  • 在package.json中添加”bin“: "cli.js"用於指定該腳手架的命令行入口文件爲cli.js。關於Node命令行參考阮一峯老師的文章
    • "bin": { "sample-scaffolding": "cli.js" }表示sample-scaffolding是在終端輸入的命令,該命令的真實入口文件是當前目錄下的cli.js。"bin"字段用來指示命令名與可執行腳本文件的映射關係
  • 創建模板:在項目根路徑下創建templates文件夾來存儲模板文件,如這裏創建了templates/index.html和templates/style.css。
  • cli.js的內容:
    • Node CLI應用入口文件必須要有#!/usr/bin/env node文件頭
    • 如果是Linux或者MacOS系統,則需要修改文件的權限爲755(文件擁有者可讀可寫可執行)chmod 755 cli.js
    • 業務代碼
      • 通過命令行交互詢問用戶問題,安裝npm install inquirer
      • 根據用戶回答的結果生成文件,需要安裝模板引擎npm install ejs來解析模板文件
// cli.js
const inquirer = require('inquirer');
const ejs = require('ejs');

inquirer.propmt([
  {
    type: 'input',
    name: 'name',
    message: 'Project name?'
  }
])
.then(answers => {
  // 根據用戶回答的結果answers結合模板文件,生成新文件
  // 模板目錄
  const tmplDir = path.join(__dirname, 'templates');
  // 目標目錄, 這裏是程序執行的當前路徑
  const destDir = process.cwd();
  // 將模板下的模板文件全部輸出到目標目錄
  fs.readdir(tmplDir, (err, files) => {
    if(err) {
      throw err;
    }
    files.forEach(file => {
      // 通過模板引擎渲染模板文件,將結果寫入新的文件中。
      ejs.renderFile(path.join(tmplDir, file), answers, (err, result) => {
        if(err) throw err;
        // 將結果寫入文件
        fs.writeFileSync(path.join(destDir, file), result);
      })
    })
  })
})
  • 使用npm link全局註冊
  • 在命令行中使用sample-scaffolding命令執行

Yeoman

基本使用

  • 全局安裝yeoman:npm install yo -g
  • 全局安裝generator:安裝項目對應的generator包,讓yeoman運行generator包來創建項目基本結構。yeoman + generator包 = 腳手架工具。比如安裝generator-node來創建一個node項目:npm install generator-node -g
  • 運行腳手架工具:yo node,注意要去掉前綴generator

sub-generator

在已有項目中再創建一些項目文件(結構),就是在generator創建的項目中繼續generator一些文件,就是sub-generator。

  • 使用方式(以上面的node項目爲例):yo node: cli
  • 語法:yo <generator-name>: <sub-generator-name>
  • 注意:並非所有的generator包都包含sub-generator(根據generator文檔查看),有的時候需要我們自己去定義sub-generator

npm安裝二進制文件時的鏡像配置

有時候npm安裝二進制包時,通過對應包的鏡像配置來加速下載。
npm安裝二進制包的鏡像配置

創建自定義generator

  • Generator本質上就是一個NPM模塊
  • Generator包含兩個組成部分
    • 組裝指令
    • 模板文件
  • Generator需要特定的文件結構
    在這裏插入圖片描述
    • app/index.js爲生成器組裝指令文件
  • sub-generator則在該Generator目錄內與app目錄同級,例如這裏的component目錄
    在這裏插入圖片描述
  • generator的名稱要求是有generator-前綴generator-<name>,否則yeoman是無法找到的。
創建generator
  • 新建文件夾作爲自定義generator的項目根路徑,文件夾命名爲generator-<name>
  • 使用npm init初始化package.json文件,注意需要手動更改一些信息。
    在這裏插入圖片描述
  • 安裝最新版的yeoman-generator作爲依賴npm install yeoman-generator -S
  • 在項目文件夾中,創建generator/app/index.js文件,作爲generator的核心入口。
    • index.js需要導出一個繼承自Yeoman Generator的類型
    • Yeoman Generator會在工作時自動調用此類型中定義的一些生命週期方法
    • 在這些生命週期方法中,通過調用父類的API實現功能,如文件寫入等
  • 完成generator後,在項目根路徑使用npm link命令將generator包鏈接到本地的全局npm包所在地,這樣就相當於使用了全局安裝。
使用自定義generator
  • 新建文件夾作爲項目根路徑
  • 使用yo <name>來使用自定義的generator作爲腳手架工具來生成項目結構。
使用模板文件來創建自定義generator
  • 在app/目錄下創建一個templates/目錄,用於存放模板文件
  • 模板文件使用的是EJS模板引擎的語法規範
  • 同時,在index.js中需要使用根據模板方式創建項目的API方法
接收用戶輸入的數據

有很多時候需要根據用戶輸入的信息,來決定如何生成項目的結構。比如模板文件中的動態數據、是否安裝某項依賴等等

命令行詢問

在index.js中,導出的類裏添加prompting方法,yeoman在詢問用戶的階段會自動調用此方法,在prompting方法中可以調用父類的prompt方法來發出對用戶的命令行詢問。

module.exports = class extends Generator {
  prompting() {
    // 返回一個Promise,yeoman可以使用異步流程
    // this.prompt()接收一個數組,數組元素爲表示要提出的問題對象
    // 
    return this.prompt([
      // 以下這個示例表示的是請用戶輸入項目名稱,默認是該項目所在文件夾名稱
      {
        type: 'input', // 問題類型,這裏表示使用用戶輸入的方式提交信息
        name: 'name', // 類似於web表單的name屬性,也就是結果的鍵值對中的鍵
        message: 'your project name', // 該問題的描述
        default: this.appname // 該問題的默認值,我們這裏使用了this.appname表示爲項目生成的目錄名稱
      }
    ])
    // answers爲當前問題的用戶回答
    .then(answers => {
      // 將用戶給與的回答掛載到answers屬性上,以便於之後使用該信息。
      this.answers = answers;
    })
  }
}
創建自定義的Vue腳手架

Plop:小而美的腳手架工具

創建特定類型文件的腳手架工具,有點類似yeoman sub-generator。一般不獨立使用,而是集成在項目中,自動化地創建同類型文件。

使用

  • 安裝:npm install plop -D
  • 項目根目錄下創建plopfile.js文件作爲Plop的入口文件
    • 需要導出一個函數
    • 該函數接受一個Plop對象,用於創建生成器任務
  • 項目根目錄下創建plop-templates目錄,用於存放Plop生成文件時的模板文件
  • 模板文件遵循handlebars的模板語法
  • 在命令行中啓動Plop:npx plop <task-name>,這裏的<task-name>就是在plopfile.js中定義的生成器任務名字。啓動的方式與gulp在命令行啓動任務是一致的。
// plopfile.js
module.exports = plop => {
  // 創建生成器任務
  // setGenerator第一個參數爲生成器名字,第二個參數爲配置選項
  plop.setGenerator('component', {
    // 對於任務的一個描述
    description: 'create a component',
    // 對於該任務,在命令行中的交互問題
    prompts: [
      {
        type: 'input',
        name: 'name',
        message: 'component name',
        default: 'MyComponent'
      }
    ],
    // 完成命令行交互後生成器的動作,多個文件多個模板如下
    actions: [
      {
        type: 'add', // 表示添加新的文件
        // 表示添加文件的路徑,可以使用{{}}的插值語法,下面的name就是命令行獲得的name值
        path: 'src/components/{{name}}/{{name}}.js',
        // 指定模板文件的路徑
        templateFile: 'plop-templates/component.hbs'
      }{
        type: 'add', // 表示添加新的文件
        // 表示添加文件的路徑,可以使用{{}}的插值語法,下面的name就是命令行獲得的name值
        path: 'src/components/{{name}}/{{name}}.css',
        // 指定模板文件的路徑
        templateFile: 'plop-templates/component.css.hbs'
      },
      {
        type: 'add', // 表示添加新的文件
        // 表示添加文件的路徑,可以使用{{}}的插值語法,下面的name就是命令行獲得的name值
        path: 'src/components/{{name}}/{{name}}.test.j.s',
        // 指定模板文件的路徑
        templateFile: 'plop-templates/component.test.hbs'
      }
    ]
  })
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章