利用yeoman構建項目generator

本文做者:ivweb qcyhust 原文出處:IVWEB社區 未經贊成,禁止轉載css

導語

在一個項目的初始化階段咱們通常會作什麼呢?若是有一個可參考的項目,是否是會複製這個項目,而後修改爲新項目?若是是要在項目中增長一個新頁面或是新組件,在開始的時候是否是會複製粘貼先前已存在的頁面、組件代碼。這些初始化時複製粘貼的操做意味着咱們即將着手的項目有大量的結構代碼(好比構建腳本,開發腳手架)是存在共性的,在開發過程當中,新建一個頁面,新開發一個組件,甚至新寫一個路由均可能利用一個相同結構的代碼來往裏面填寫新的內容。那麼一個能幫助開發者生成自定製結構文件的小工具就會在這中使用場景下派上用場,它能讓開發者的工做焦點回到真正的業務邏輯開發上,同時也能爲團隊開發體統一份統一的代碼規範。html

圖片描述

簡介

yeoman是一個能夠幫助開發者快速開啓一個新項目的工具集。yoeman提出一個yeoman工做流的概念,經過腳手架工具(yo),構建工具(grunt gulp等)和包管理器(npm bower等)的配合使用讓開發者專一於業務的解決上而不是其餘小事情。在yeoman的官網中能夠搜索到不少用於初始化項目的generator,能夠用於快速開啓項目。同時yeoman也提供給開發者如何定義本身的generator,全部咱們本身開發的generator都做爲一個插件能夠經過yo工具建立出咱們須要的結構。前端

本身建立的generator能夠是很簡單的建立幾個模板頁面,也能夠經過和用戶交互構建一套量身定製的項目,取決於項目初始化的策略。能夠利用yeoman的generator-generator工具來開始構建本身的generator。node

從一個簡單的例子開始

先從一個簡單的模板頁面入手,建立簡單的generator。假設咱們的須要的demo項目目錄結構是這樣的:git

├───index.html
|───styles/
|    └───style.css
├───scripts/
    └───main.js

複製代碼

以前提到,咱們的generator是一個插件,因此首先須要建立成一個node module包,在yeoman中這個包的名字應該是generator開頭的,那麼咱們這個generator就叫作generator-demo。每個包的keyword中必須包含yeoman-generator。files屬性要指向項目的模板目錄。github

第一步是經過npm init或是本身手動建立generator的package.json,項目依賴yeoman-generator。也能夠利用generator-generator來初始化。web

{
    "name": "generator-demo",
    "version": "0.1.0",
    "description": "",
    "files": [
        "generators"
    ],
    "keywords": [
        "yeoman-generator"
    ],
    "main": "generators/app/index.js",
    "dependencies": {
        "yeoman-generator": "^1.0.0"
    }
}

複製代碼

咱們的generator項目目錄:npm

├───package.json
└───generators/
    └───app/
        └───index.js
        └───templates/
            ├───index.html
            ├───styles/
            │   └───style.css
            └───scripts/
                └───main.js    

複製代碼

第二步就是往template中填充內容,也就是demo項目的三個基本文件的內容。這裏簡單提供一個例子: template/index.htmljson

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <title>generator-demo</title>
    <link rel="stylesheet" href="styles/style.css">
</head>
<body>
    <h1>helle <%= name %></h1>
    <script src="scripts/main.js"></script>
</body>
</html>

複製代碼

yeoman採用ejs模板語法,能夠在模板文件中傳入參數。gulp

template/styles/style.css

* {
  margin: 0;
  padding: 0;
}

複製代碼

template/sctipts/main.js

'use strict';

window.onload = function() {
    console.log('generator success');
};

複製代碼

到這一步後就是擴展generator。yeoman提供了一個基礎的generator,它有本身的生命週期和事件,功能強大。能夠經過擴展這個基礎generator來實現咱們項目的初始化需求。因而第三步就是編輯app/index.js來擴展它:

const Generator = require('yeoman-generator');
const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');
const utils = require('../utils');
const log = utils.log;

module.exports = class extends Generator {
  constructor(args, opts) {
      super(args, opts);

      this.props = {
          projectName: 'demo',
          name: 'world'
      };
  }

  writing() {
      const { projectName, name } = this.props;
      const temps = {
        'index.html': { name: this.props.name }
      };

      fs.readdir(this.sourceRoot(), (err, items) => {
          for(let item of items) {
              if(temps[item]) {
                  this.fs.copyTpl(
                      this.templatePath(item),
                      this.destinationPath(projectName, item),
                      temps[item]
                  );
              } else {
                  this.fs.copy(
                      this.templatePath(item),
                      this.destinationPath(projectName, item)
                  );
              }
          }
      });
  }

  end() {
      log.info('generator success');
  }
};

複製代碼

第四步就是運行generator。yoeaman的henerator是一個全局npm module,咱們在本地開發的generator能夠經過軟鏈接的方式生成它的全局npm包。在generator-demo的根目錄下運行npm link,它會在本地的全局npm目錄下安裝咱們新建的generator。

在肯定本地已經安裝yo工具(npm install -g yo)後,在你須要初始化demo項目的地方運行yo demo,等命令執行完畢,就能夠看到新建的項目了。

圖片描述
圖片描述
圖片描述

run loop

在擴展基礎generator時,咱們能夠給實例添加自定義的方法,每個添加進去的方法都會在generator調用的時候被調用,並且一般來說,這些方法是按照順序調用的。除非是已下劃線_開頭的私有方法,或是定義在實例上的方法。

module.exports = class extends Generator {
    constructor(args, opts) {
        super(args, opts);

        this.task = () =>  {
            this.log('instance task');
        }
     }

      method1() {
          this.log('method 1');
      }

      method2() {
          this.log('method 2');
      }

     _task() {
        this.log('private task');
     }
};

// 輸出:
// 'method 1'
// 'method 2'

複製代碼

每個方法在yeoman中都被認爲是一個任務,這些任務都會被run loop調用。yeoman的run loop是一個有優先級的隊列系統。採用Grouped-queue來維護yeoman的事件隊列。除了自定義的方法外,yeoman有不少特殊的事件方法,按照優先級排序:

  1. initializing - 初始化開始

  2. prompting - 調用this.prompt()與用戶產生交互

  3. configuring - 建立配置文件(package.json,config.js等)

  4. default - 方法都不匹配這些優先級時,就會是default優先級(自定義方法會被劃入default)

  5. writing - 建立項目文件

  6. conflicts - 文件建立中產生衝突的處理

  7. install - 調用(npm, bower)包install

  8. end - 結束項目初始化 其餘自定義方法在configuring和writing按順序優先級調用。

    圖片描述
    圖片描述

    更復雜的交互

    如今咱們來給generator增長用戶交互和package.json,讓它能構建出一個更復雜的項目。仍是修改app/index.js,首先增長prompting:

prompting() {
  return this.prompt([{
      type: 'input',
      name: 'projectName',
      message: '請輸入項目名字',
      default: 'default-name'
  }, {
      type: 'confirm',
      name: 'package',
      message: '須要package.json文件',
      default: true
  }, {
      type: 'input',
      name: 'name',
      message: '請輸入你的名字',
      default: 'world'
  }]).then((answers) => {
      this.log('create project: ', answers.projectName);
      this.log('by: ', answers.name);
      this.props = answers;
  });
}

複製代碼

增長configuring:

configuring() {
  const { projectName, name } = this.props;
  let packageSettings = {
    name: projectName,
    version: '0.0.1',
    description: 'YOUR DESCRIPTION - Generated by generator-demo',
    main: '',
    scripts: {},
    repository: '',
    keywords: [],
    author: name,
    devDependencies: {},
    dependencies: {}
  };

  this.fs.writeJSON(this.destinationPath(projectName, 'package.json'), packageSettings);
}

複製代碼

package.json能夠直接建立也能夠利用模板文件建立或是將其中的屬性抽象到配置文件中,這樣方便修改。

總結

yeoman genenrator的功能遠不僅本文演示的這些,它還支持異步事件(prompting自己就返回一個promise對象)、install依賴包等等。

一個genenrator也不僅是建立一個模板,它同時支持多種模板的須要,好比咱們有個複雜的項目,files裏面能夠添加多個generator,主generator負責初始化項目的時候建立項目的主要文件並安裝好各類依賴,在項目的開發中,咱們須要增長一個container或是router的話,調用對應的genenrator便可,生成的模板能夠將注意力放在內容上,提升開發效率。

騰訊NOW直播前端工程化解決方案feflow正式開源啦~: https://github.com/feflow/feflow 感興趣的能夠star一下哈~

相關文章
相關標籤/搜索