我想寫一個前端開發工具(三):優化!從vue-cli學了幾招

  

  我從過年開始寫本身的前端工具 coodev,目前已經寫出一個基本的架子,大多數預想的功能都能跑通,還剩一些須要解決的問題也都已經列出來了。原本這一週打算解決對不一樣後端模板的先後端渲染支持的問題。可是看了一下代碼,當初不少功能寫的仍是有很大優化空間的。我打算先停下腳步,多看一些優秀的開源框架的源碼,而後優化整理一下個人前端工具。前端

  在選擇閱讀源碼時,我首先想到的就是vue-cli的源碼。畢竟我最初的靈感就是來源於vue-cli。閒話少說,咱們先下載一份vue-cli,打開源碼先看package.json熟悉總體的代碼結構,不過這裏我建議直接閱讀/bin 文件夾下的幾個文件:vue、 vue-init、 vue-build、 vue-listvue

  引用的比較多的好比vue-init就在一開始引用了一大堆的文件node

  

 1 #!/usr/bin/env node
 2 
 3 var download = require('download-git-repo')
 4 var program = require('commander')
 5 var exists = require('fs').existsSync
 6 var path = require('path')
 7 var ora = require('ora')
 8 var home = require('user-home')
 9 var tildify = require('tildify')
10 var chalk = require('chalk')
11 var inquirer = require('inquirer')
12 var logger = require('../lib/logger')
13 var generate = require('../lib/generate')
14 var checkVersion = require('../lib/check-version')
15 var warnings = require('../lib/warnings')

  它們都是幹嗎用的,咱們調一些比較重要的說一下。jquery

1、優化參數處理webpack

  先看vue:git

1 #!/usr/bin/env node
2 
3 require('commander')
4   .version(require('../package').version)
5   .usage('<command> [options]')
6   .command('init', 'generate a new project from a template')
7   .command('list', 'list available official templates')
8   .command('build', 'prototype a new project')
9   .parse(process.argv)

  能夠看出這個文件主要是對 ‘commander’的使用。那麼‘commander’這個npm包又是什麼呢?字面意思‘指揮官’,咱們在 https://www.npmjs.com/ 網站上能夠搜一下,會有一些簡單的文檔用例。其實‘commander’就是命令控制器,vue-cli用這個庫來管理用戶輸入的命令,來完成在終端上用戶命令行的交互。github

  回到vue-cli能看到一個很大的鏈試調用,完成了一些列的任務,咱們要先了解這些api,就能明白這個文件在幹什麼了。關於 ‘commander’的API,能夠看npm上的官方例子,後續我也會寫一篇有關於使用 ‘commander’的文章。我這裏先介紹幾個我用到的:web

  我原先是經過一個map定義命令,用到的地方require一下,經過 process.argv.splice(2) 拿到參數。後來改用‘commander’,就比較省心直接註冊參數:vue-cli

  

 1 var program = require('commander');
 2 
 3 
 4 program
 5     .version(require('./package').version)
 6     .option('-i, --init', '初始化項目文件夾')
 7     .option('-d, --dev', '以開發模式啓動coodev 即時編譯 不壓縮')
 8     .option('-b, --build', '以生產模式啓動coodev 編譯一次 壓縮')
 9     .option('-s, --server', '本地server調試')
10     .option('-p, --publish', '提交到發佈倉庫')
11     .parse(process.argv);
12 
13 /** init */
14 if (program.init) {
15     require('./src/tasks/task-init.js').render();
16 }
17 
18 /** dev */
19 if (program.dev) {
20     require('./src/tasks/task-dev.js').render();
21 }
22 
23 /** build */
24 if (program.build) {
25     require('./src/tasks/task-build.js').render();
26 }
27 
28 /** start */
29 if (program.start) {
30     require('./src/tasks/task-server.js').render();
31 }
32 
33 /** publish */
34 if (program.publish) {
35     require('./src/tasks/task-publish.js').render();
36 }
37 
38 program.on('--help', function () {
39   console.log('  Examples:')
40   console.log()
41   console.log(chalk.gray('    # create a new project with an official template'))
42   console.log('    $ coodev --init')
43   console.log()
44   console.log(chalk.gray('    # develop project'))
45   console.log('    $ coodev --dev')
46   console.log()
47   console.log(chalk.gray('    # start local server'))
48   console.log('    $ coodev --start')
49   console.log()
50 });

  其中version和我原來的方式差很少,版本號就直接引用package.json,本身以爲預設的命令就用option定義(簡寫,全名,描述),簡寫和全名是調用的時候用的,描述是在輸入命令'--help'的時候會自動抓取的。最後的‘on’,就像是jquery中的事件綁定同樣,給命令追加額外的處理邏輯。npm

  這裏只是一些經常使用的,我後期還要加上一些交互性質的參數處理,好比引導用戶配置工程等等,雖然原來本身寫的也能知足目前的需求,但爲了後期的功能,仍是先改爲‘commander’好一些。

2、按需拉取github上的模板

  這事我最想學習的功能。用過vue-cli的朋友都知道有一個這樣的命令 $ vue init webpack-simple yourproject-name 的初始化命令,他會做爲幾個腳手架給咱們初始化模板,那麼模板都放哪了?若是放在vue-cli裏面,隨着後期維護,就會愈來愈大,這不就毀了嗎。我看了一下官方的描述說模板放在了另外一個git倉庫裏,我也在github裏找到了。我起初的時候爲了獨立維護模板,也是這樣作的放在了別處,每次coodev發佈時,用腳本同步過來,但個人方式雖然快,可是也就是如今模板數少還能夠。所以我打算按須要拉取模板。

  這個功能無疑是在vue-init文件裏面,我發現有一個 var download = require('download-git-repo') ,在npm上查了一下,描述是這樣「從節點下載並提取一個git存儲庫」,那麼應該就是它了。

  個人模板放在了github上的另外一個倉庫,https://github.com/grARM/coodev-temp-normal。如今想拉到coodev中只須要調用以下代碼:

1 /** get code from github */
2 var loadNormalTmpl = function(cb){
3     download('grARM/coodev-temp-normal', proPath, function (err) {
4         if(err){
5             console.log('err', err);
6         }
7         cb && cb(err);
8     });
9 }

  其中proPath是個人工程目錄,這樣就比我以前的遞歸文件拷貝高端了很多。

3、交互式命令

  既然能夠從別處拉模板,那麼個人coodev一會兒就能夠精簡不少,我之後能夠擁有一大堆模板,都放在github上,我想拉哪個,就拉哪個。我還須要給用戶提供交互式的命令。在vue-init中也是有這個例子的。 var inquirer = require('inquirer') 

  'inquirer'是一個提供交互式命令的npm包,地址: https://www.npmjs.com/package/inquirer。這個庫在Github的examples文件夾裏有詳細的例子。每個問答都會被封裝到answers裏。

 1 inquirer.prompt([{
 2         type: 'list',
 3         message: 'which template do you need:',
 4         name: 'template',
 5         choices: ['normal', 'wap', 'h5']
 6     }]).then(function (answers) {
 7         console.log(answers)
 8             done();
 9     })        

  如圖:  

總結:  

  就這樣,我就在vue-cli中學習了3招:命令管理、按需拉取模板、交互式命令。

  接下來就是處理不一樣的主流後端模板引擎的支持了。

相關文章
相關標籤/搜索