上一篇文章分析了创建vue默认工程(Vue-cli(3.0 + ) 源码分析(二)_夜跑者的博客-CSDN博客)
如果vue默认工程项目不符合我们的需求怎么办呢?vue-cli 提供了-p 选项,可以使用自己的预设模板,option('-p, --preset <presetName>', 'Skip prompts and use saved or remote preset')
这一篇文章我们就分析一下uni-app 提供的预设模板怎么做的。uni-app 可以用vue-cli方式创建项目工程,命令如下:
vue create -p dcloudio/uni-preset-vue my-project
dcloudio/uni-preset-vue 就是uni-app提供的预设模板,可以从github上下载。先看下vue-cli对-p的处理
1. vue-cli 对-p 选项的处理
if (cliOptions.preset) {
// vue create foo --preset bar
preset = await this.resolvePreset(cliOptions.preset, cliOptions.clone)
}
如果命令提供了-p选项则 resolvePreset
async resolvePreset (name, clone) {
let preset
const savedPresets = this.getPresets() //首选从本地磁盘~/.vuerc 预设项目文件
if (name in savedPresets) {
preset = savedPresets[name]
} else if (name === 'default') {
preset = savedPresets['Default (Vue 3)']
} else if (name.endsWith('.json') || /^\./.test(name) || path.isAbsolute(name)) {
preset = await loadLocalPreset(path.resolve(name))
} else if (name.includes('/')) {
//从远程服务器拉取预设项目文件
log(`Fetching remote preset ${chalk.cyan(name)}...`)
this.emit('creation', { event: 'fetch-remote-preset' })
try {
preset = await loadRemotePreset(name, clone)
} catch (e) {
error(`Failed fetching remote preset ${chalk.cyan(name)}:`)
throw e
}
}
if (!preset) {
error(`preset "${name}" not found.`)
const presets = Object.keys(savedPresets)
if (presets.length) {
log()
log(`available presets:\n${presets.join(`\n`)}`)
} else {
log(`you don't seem to have any saved preset.`)
log(`run vue-cli in manual mode to create a preset.`)
}
exit(1)
}
return preset
}
首先从本地磁盘读取~/.vuerc预设项目文件,-p选项传入的预设名称不匹配则从远程服务器拉取预设项目文件,dcloudio/uni-preset-vue 就是从远程拉取的。
module.exports = async function loadRemotePreset (repository, clone) {
const os = require('os')
const path = require('path')
const download = require('download-git-repo')
const presetName = repository
.replace(/((?:.git)?#.*)/, '')
.split('/')
.slice(-1)[0]
// for direct urls, it's hard to get the correct project name,
// but we need to at least make sure no special characters remaining
.replace(/[:#]/g, '')
const tmpdir = path.join(os.tmpdir(), 'vue-cli-presets', presetName)
// clone will fail if tmpdir already exists
// https://github.com/flipxfx/download-git-repo/issues/41
if (clone) {
await fs.remove(tmpdir)
}
await new Promise((resolve, reject) => {
download(repository, tmpdir, { clone }, err => {
if (err) return reject(err)
resolve()
})
})
return await loadPresetFromDir(tmpdir)
}
这个也非常简单