大家都知道,使用vue-cli可以快速的初始化一個基於Vue.js的項目,全局安裝腳手架之後,你可以通過vue list命令看到官方提供的5個模板 vue list 當開發一個獨立項目的時候,使用官方提供的template確實很方便,省去了繁瑣的依賴配置,webpack等配置問題,甚至連項目目錄結構 ...
大家都知道,使用vue-cli可以快速的初始化一個基於Vue.js的項目,全局安裝腳手架之後,你可以通過vue list命令看到官方提供的5個模板
vue list
當開發一個獨立項目的時候,使用官方提供的template確實很方便,省去了繁瑣的依賴配置,webpack等配置問題,甚至連項目目錄結構也不需要去考慮,著實方便。但是,當我們需要開發多個系統,每個系統依賴的包,webpack都不一致的時候,vue官方提供的模板就顯得捉襟見肘了,這是我們就需要去考慮,能否開發一套自己定製化的template,答案是肯定的,那麼在開始定製之前我們需要瞭解一些前置知識。
一、前置知識
模板結構
首先我們瞭解一下模板的主要結構,當我們從githup官網上去看vue官方給們提供的模板結構的時候,發現模板其實很簡單,主要包括兩個部分
- template 該目錄用於存放模板文件,當你執行vue init <templateName> <myProject>的時候,初始化項目文件目錄結構就來與此
- meta.js/meta.json用於描述初始化項目的時候在命令行和用戶交互的行為
download-git-repo
使用vue-cli初始化項目時會使用該工具來下載目標倉庫,預設我們平常都會下載webpack這個模板(vue init webpack myProject),自定義模板可以是一個GitHub倉庫,也可以是一個本地文件,使用如下命令來初始化項目:
vue init username/repo my-project //其中username為自定義模板倉庫所在GitHub用戶名,repo是倉庫名
vue init ./../ my-project //本地文件
Inquirer.js
vue-cli在模板倉庫下載完成後,將通過Inquire.js根據模板倉庫中的meta.js或meta.json文件中的設置,與用戶進行一些簡單的交互以確定項目的一些細節,如下圖:
該交互是可選的,如果項目中沒有meta.js或meta.json文件時,模板倉庫下載完成後將直接進入模板模板構建過程。
Handlebars.js
在通過命令行交互確定了項目初始化細節後,就該進入最後一道工序,按照模板初始化我們的項目了,這裡vue-cli選用的是Handlebars.js,一個簡單高效的語義化模板構建引擎。
定製模板主要圍繞著命令行交互(Inquirer.js)與模板文件開發(Handlebars.js)這兩部分。
meta.js配置文件(Inquirer.js)
meta.js相當於模板項目的配配置文件,這個文件不是必須的,這裡主要看看它能做些什麼,設置都在meta.js或meta.json裡面,但是我推薦使用meta.js,因為它的配置相對更靈活一點,下麵主要簡單說明一下meta.js的配置。
meta.js一共包含如下幾個欄位,簡單列一下各欄位功能:
-
- helpers:自定義Handlebars.js的輔助函數
- prompts:基於Inquirer.js的命令行交互配置
- filters:根據命令行交互結果過濾將要渲染的項目文件
- metalSmith:配置Metalsmith插件,文件會像gulp.js中的pipe一樣依次經過各個插件的處理
- completeMessage:將模板渲染為項目後輸出一些提示信息,取值為字元串
- complete:與completeMessage功能相同,二選其一,取值為函數,函數最後要返回輸出的字元串,這裡也可以配置讓其自動安裝項目依賴
命令行交互(Inquirer.js)
命令行交互主要是meta.js中prompts欄位的配置,詳細的配置可以閱讀官方文檔,或者在這裡推薦我一個朋友的博客地址,他那有詳細的說明。
module.exports = { metalsmith:{ before: addTestAnswers },
"helpers": { "if_or": function (v1, v2, options) { if (v1 || v2) { return options.fn(this); } return options.inverse(this); }, template_version() { return templateVersion }, }, "prompts": { "name": { "type": "input", "required": true, "message": "項目名" }, "author": { "type": "input", "message": "作者" }, } }
說一下各個欄位的意思
-
- name與author:交互欄位名稱,可在後續條件交互或模板渲染時通過該欄位讀取到交互的的結果。
- type:交互類型,有input,confirm,list,rawlist,expand,checkbox,password,editor八種類型
- message:交互的提示信息
- when:進行該條件交互的先決條件
- default:預設值,當輸入為空時預設此值
- required:預設為false,該值是否為必填項
- validate:輸入驗證函數
模板基本語法(Handlebars.js)
在編寫模板的時候,我們可以用Mustache語法在任何文本類型的文件中輸出在命令行交互中得到一些數據:
{ "name": "{{ name }}", "description": "{{ description }}", "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", {{/if_eq}} {{#e2e}} "e2e": "node test/e2e/runner.js",{{/e2e}} {{#if_or unit e2e}} "build": "node build/build.js" }, "dependencies": { {{#vux}} "vux": "^2.2.0", {{/vux}} } }
以package.json文件為例,{{name}}即為meta.js裡面寫name,{{#vux}}"vux":"^2.2.0",{{/vux}}即為根據命令行交互的結果得知是否渲染。
模板渲染時的輔助函數(Handlebars.js)
vue-cli中為handlebar.js預置了if_eq與unless_eq輔助函數,用於使用交互所得數據來處理模板中是否渲染兩種邏輯關係,此外handlebars中還內內置了if、unless、each等輔助函數。此外我們可以自定義輔助函數(handlebars.js)
有時候現有的輔助函數不能可能不能滿足我們的需求,通過meta.js中的helpers欄位我們可以自定義輔助函數:
"helpers": { "if_or": function (v1, v2, options) { if (v1 || v2) { return options.fn(this); } return options.inverse(this); }, template_version() { return templateVersion }, },
輔助函數可以接受若幹個參數,最後一個參數options為輔助函數的鉤子,調用options.fn(this)即輸出該輔助函數運算結果為真時的內容,反之調用options.inverse(this)的內容
現在就可以直接再模板中使用if_or輔助函數了:
{{#if_or unit e2e}} "test": "{{#unit}}npm run unit{{/unit}}{{#unit}}{{#e2e}} && {{/e2e}}{{/unit}}{{#e2e}}npm run e2e{{/e2e}}", {{/if_or}}
按條件過濾渲染文件
輔助函數值可以控制文件內的一部分內容的輸出與否,有時候我們需要根據交互結果控制某些文件本身是否輸出。
在meta.js中的filters欄位中進行相應的設置就可以達到控制文件輸出的效果
filters: {//根據命令行交互的結果過濾將要渲染的項目文件 '.eslintrc.js': 'lint', '.eslintignore': 'lint', 'config/test.env.js': 'unit || e2e', 'build/webpack.test.conf.js': "unit && runner === 'karma'", 'test/unit/**/*': 'unit', 'test/unit/index.js': "unit && runner === 'karma'", 'test/unit/jest.conf.js': "unit && runner === 'jest'", 'test/unit/karma.conf.js': "unit && runner === 'karma'", 'test/unit/specs/index.js': "unit && runner === 'karma'", 'test/unit/setup.js': "unit && runner === 'jest'", 'test/e2e/**/*': 'e2e', 'src/router/**/*': 'router', },
filters中鍵名是要控制輸出的文件的路徑,鍵名對應的值為命令行交互中得到的數據
關於metalSmith插件的使用本人尚未研究,如果有感興趣的朋友敬請期待,或可以直接去查閱相關資料。
以上就就是定製團隊模板的大概步驟,差不多已經介紹結束了,如果有興趣趕快為自己的團隊定製去吧!!!