做为一个菜鸟,我有一颗好奇的心,每当vue init 的时候,看到那流畅的进度和神奇的结果,内心都充满一窥其本质的指望……前端
如下就是我不断的console,大体理出来的一个流程心得,纪录在此,以做备忘。vue
一、which vue,定位vue命令的实际位置node
二、去往命令vue的目录,查看代码webpack
这里的commander包是用来建立命令行的工具,其npm官网粗略了解,了解到其中的init、list命令会在当前目录寻找执行vue-init、vue-list文件git
The commander will try to search the executables in the directory of the entry script (like
./examples/pm
) with the nameprogram-command
, likepm-install
,pm-search
.es6
三、查看vue-init文件及其代码github
经过ls命令咱们能够看到,命令文件的真实位置是在全局node_modules下的vue-cli里面,因此代码里的require包都是从vue-cli包下找的web
这个文件就是init命令的主体了,里面主要有vue-cli
download-git-repo、inquirer等包 和 cli/lib下的功能函数 check-version、generate等
3.一、check-version 的做用npm
首先其会比对vue-cli的package.json里的node版本和当前process.version的环境版本,若是环境版本低就会报错。
其次其会请求线上vue-cli的最新版本,来告诉用户是否有新的vue-cli版本能够更新,只是给用户一个提示
const request = require('request') const semver = require('semver') const chalk = require('chalk') const packageConfig = require('../package.json') module.exports = done => { // Ensure minimum supported node version is used if (!semver.satisfies(process.version, packageConfig.engines.node)) { return console.log(chalk.red( ' You must upgrade node to >=' + packageConfig.engines.node + '.x to use vue-cli' )) } request({ url: 'https://registry.npmjs.org/vue-cli', timeout: 1000 }, (err, res, body) => { if (!err && res.statusCode === 200) { const latestVersion = JSON.parse(body)['dist-tags'].latest const localVersion = packageConfig.version if (semver.lt(localVersion, latestVersion)) { console.log(chalk.yellow(' A newer version of vue-cli is available.')) console.log() console.log(' latest: ' + chalk.green(latestVersion)) console.log(' installed: ' + chalk.red(localVersion)) console.log() } } done() }) }
3.2 、download-git-repo的做用
用来经过git clone 或者 http下载的方式,从github、gitlab等平台下载仓库代码,具体可去官网查看,
默认,咱们没有指定clone参数,程序会从 https://github.com/vuejs-templates/webpack/archive/master.zip 下载模版
若是用 vue init webpack -c 则会经过 git clone git@github.com:vuejs-templates/webpack.git 来下载(本地配置sshkey,能够下载私有库)
tmp变量是临时存放模版的目录,默认在 ~/.vue-templates/
const tmp = path.join(home, '.vue-templates', template.replace(/[\/:]/g, '-')) …… download(template, tmp, { clone }, err => { spinner.stop() if (err) logger.fatal('Failed to download repo ' + template + ': ' + err.message.trim()) generate(name, tmp, to, err => { if (err) logger.fatal(err) logger.success('Generated "%s".', name) }) })
若是咱们要配置本身项目的模版目录,就好好看看vue-init文件里的run函数吧 ^_^,祝你成功^_^。
3.三、inquirer的做用
起到一个prompt confirm的做用
Generate project in current directory?
Target directory exists. Continue?
3.四、generate函数的做用
主要代码
metalsmith.clean(false) .source('.') // start from template root instead of `./src` which is Metalsmith's default for `source` .destination(dest) .build((err, files) => { done(err) if (typeof opts.complete === 'function') { const helpers = { chalk, logger, files } opts.complete(data, helpers) } else { logMessage(opts.completeMessage, data) } })
下载完模版后的处理逻辑都在这里面了,函数文件位于 vue-cli/lib/generate.js,这里面主要用了
metalsmith、handlebars等包 和 lib/options.js
options.js 会去 ~/.vue-templates/模版 目录下获取 meta.js 或者 meta.json 中的配置。
这个配置就是用来配置图中的东西。
3.4.一、metalsmith 的做用
相似于gulp,是一个流程工具,英文很差,我看它看的头疼,只知道它干了什么,但不知道它是怎么作的。
它会配置options.js里获取的配置数据,对模版文件进行过滤
3.4.二、handlebars 的做用
一个js模版工具,相似服务端的smarty、前端的artemplate、es6的字符串模版等。
它会在metalsmith的流程里处理模版里的变量,把咱们填写的项目名等数据渲染成最终的文件,写进当前项目目录里。《完》
好久没写博客,写着好别扭啊,不支持markdown,只能凭感受来写了,估计预览起来会很难看,但愿你们见谅。
最后吟诗一首:
“众鸟高飞尽,孤云独去闲。相看两不厌,只有敬亭山。”