做者: 珈藍 from 迅雷前端javascript
原文地址: greenfavo.github.io/blog/docs/0…html
當新建項目的時候,咱們一般須要設計目錄結構、配各類配置、處理打包編譯,並且每次新建都要重來一遍,或把原來的項目 copy 一份再改改。那能不能本身寫個模板,而後還能夠支持個性化自動建立呢?今天我就來和你們一塊兒分享如何定製一套本身的項目腳手架,提高開發效率。前端
這裏須要引入腳手架的概念,什麼是腳手架呢?腳手架如同一個項目的模板,能夠幫咱們快速開始項目,就像 vue-cli,提供一個終端的交互界面讓用戶自定義項目內容。vue
Yeoman 是一個通用的腳手架系統,容許建立任何類型的應用程序(Web,Java,Python,C#等)。用 yeoman 寫腳手架很是簡單, yeoman 提供了 yeoman-generator 讓咱們快速生成一個腳手架模板,咱們的主要工做就是把模板文件寫好。如今咱們來用 yeoman 寫一個生成 javascript 插件的腳手架吧。java
腳手架功能:node
首先須要全局安裝 yo 和 generator-generatorgit
npm install yo -g
npm install generator-generator -g
複製代碼
生成腳手架模板es6
yo generator
複製代碼
在這個終端界面裏輸入項目名、描述等項目信息。注意項目名稱要寫成generator-xxx
的格式,這樣用戶就能夠經過yo xxx
安裝你的腳手架了。github
生成的腳手架模板目錄結構以下:vue-cli
.
├── generators/
│ └── app/
│ ├── index.js
│ └── templates/
│ └── dummyfile.txt
├── .editorconfig
├── .eslintignore
├── .gitattributes
├── .gitignore
├── .travis.yml
├── .yo-rc.json
├── LICENSE
├── README.md
├── package.json
└── __tests__/
└── app.js
複製代碼
接下來咱們就在generators/app/index.js
裏寫腳手架的邏輯。
腳手架所作的事情:
yeoman 提供了一個基本生成器,你能夠擴展它以實現本身的行爲。這個基礎生成器將幫你減輕大部分工做量。在生成器的 index.js 文件中,如下是擴展基本生成器的方法:
var Generator = require("yeoman-generator"); module.exports = class extends Generator {}; 複製代碼
yeoman 生命週期函數執行順序以下:
咱們經常使用的就是 initializing、prompting、default、writing、install 這四種生命周期函數。看下例子:
"use strict"; const Generator = require("yeoman-generator"); const chalk = require("chalk"); // 讓console.log帶顏色輸出 const yosay = require("yosay"); const mkdirp = require("mkdirp"); // 建立目錄 module.exports = class extends Generator { initializing() { this.props = {}; } // 接受用戶輸入 prompting() { // Have Yeoman greet the user. this.log( yosay( `Welcome to the grand ${chalk.red( "generator-javascript-plugin" )} generator!` ) ); const prompts = [ { type: "confirm", name: "someAnswer", message: "Would you like to enable this option?", default: true } ]; return this.prompt(prompts).then(props => { // To access props later use this.props.someAnswer; this.props = props; }); } // 建立項目目錄 default() { if (path.basename(this.destinationPath()) !== this.props.name) { this.log(`\nYour generator must be inside a folder named ${this.props.name}\n I will automatically create this folder.\n`); mkdirp(this.props.name); this.destinationRoot(this.destinationPath(this.props.name)); } } // 寫文件 writing() { // 將templates目錄的代碼拷貝到目標目錄 // templates目錄默認路徑是generators/app/templates this.fs.copy( this.templatePath("dummyfile.txt"), this.destinationPath("dummyfile.txt") ); this._writingPackageJSON(); } // 如下劃線_開頭的是私有方法 _writingPackageJSON() { // this.fs.copyTpl(from, to, context) this.fs.copyTpl( this.templatePath("_package.json"), this.destinationPath("package.json"), { name: this.props.name, description: this.props.description, keywords: this.props.keywords.split(","), author: this.props.author, email: this.props.email, repository: this.props.repository, homepage: this.props.homepage, license: this.props.license } ); } // 安裝依賴 install() { this.installDependencies(); } }; 複製代碼
前面咱們把一個腳手架的基本框架都寫好了,它能夠接受用戶輸入的內容,能夠寫文件,能夠安裝依賴,但接收用戶輸入的數據怎麼用?寫進什麼文件?安裝什麼依賴呢?這些都是模板文件作的事情。如今就開始最主要的一部分:編寫模板文件。
模板文件是你爲用戶生成的一個項目 demo,讓用戶看着這些示例代碼就能夠開工了,用戶應該只須要專一於業務邏輯,而不用管打包構建這些事。
首先建好模板目錄:
├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .babelrc ├── jsdoc.json ├── README.md ├── package.json ├── build/ └── rollup.js ├── src/ └── index.js ├── test/ └── index.js 複製代碼
咱們的模板package.json
裏已經寫好這些命令:
"scripts": {
"prebuild": "npm run lint && npm run test && npm run doc",
"build": "node ./build/rollup.js",
"lint": "eslint --ext .js, src",
"test": "mocha --require babel-register --require babel-polyfill --bail",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"doc": "jsdoc -c ./jsdoc.json"
}
複製代碼
npm run lint
用 eslint 進行語法檢查,在編譯前就避免語法錯誤和統一代碼風格。npm test
運行單元測試npm run doc
根據註釋生成文檔npm run changelog
根據git log
生成項目日誌,改動記錄一目瞭然npm run prebuild
編譯前的語法檢查、 運行測試、生成文檔npm run build
編譯打包咱們可使用<%= name %>
這樣的模板語法使用腳手架中的context
上下文,不管是用戶輸入的數據,仍是程序本身的變量:
{ "name": "<%= name %>", "description": "<%= description %>", "version": "1.0.0", "private": false, "main": "dist/<%= name %>.umd.js", "module": "dist/<%= name %>.es.js" } 複製代碼
詳細代碼請到github查看。
爲了保證代碼的健壯性,咱們必須進行單元測試。其實咱們用generator
生成的腳手架代碼中已經有測試代碼示例了,改爲本身的邏輯就能夠測試咱們的腳手架邏輯了。如今咱們來測試下文件是否生成:
'use strict'; const path = require('path'); const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); describe('generator-javascript-plugin:app', () => { beforeAll(() => { return helpers .run(path.join(__dirname, '../generators/app')) .withPrompts({ someAnswer: true }); }); it('creates files', () => { assert.file(['build/rollup.js']); assert.file(['dist']); assert.file(['src']); assert.file(['test']); assert.file(['package.json']); assert.file(['.babelrc']); ... }); }); 複製代碼
執行命令
npm test 複製代碼
到此,咱們的腳手架開發完了,接下來實際運行下看看是否正確。
因爲咱們的腳手架仍是本地開發,它還沒有做爲全局 npm 模塊提供。咱們可使用 npm 建立全局模塊並將其符號連接到本地模塊。在項目根目錄運行:
npm link
複製代碼
這樣就能夠調用yo javascript-plugin
運行腳手架了。你能夠在終端看到運行過程。
寫好的腳手架發佈出去才能讓更多的人使用,發佈腳手架和發佈其餘 npm 包同樣。如何發佈?
generator-javascript-plugin
這個腳手架已經發布到npm上,能夠下載或訪問源碼。