前面对yeoman进行了初步的了解 前端工程化之yeoman的使用(一) ,接下来对yeoman进行扩展安装自己的脚手架,以及遇到的问题进行记录
新建模板
因为我这里直接删除generators
文件夹了(可对照上篇文章的新建目录结构部分)。所以files
中的数组直接就是generator
:
"files": [
"app"
],
新建根据公司项目分pc
端和移动端分两块pc
和mobile
用到的方法属性等说明
需要的方法:
initializing
-做一些初始化的动作,比如参数获取等等
prompting
- 使用this.prompt()
来询问的操作
configuring
-配置文件配置等(如创建.editorconfig
文件等等)
default
-如果方法名称与优先级不匹配,它将被推送到该组。
writing
-生成处理赋复制等操作的地方
conflicts
-处理冲突的地方(内部使用)
install
-对依赖进行下载等处理
end
- 最后的处理一般做退出时的操作
copyTpl
:copyTpl(from,to,context,templateOption,copyOption)
将模板复制到指定的目录中(源码)
参数:
from
:模板目标源地址
to
:要复制到的地址
context
:需要传递给ejs模板的参数
templateOption:ejs
模板引擎配置参数
templateOption
对象属性:(EJS参数部分)
copyOption
:复制时参数配置
prompt()
:同plop
一样也是基于Inquirer
,故具体参考(Inquirer )
逻辑
场景:
询问选择pc还是移动端。如果是pc端,那么就填写项目名和是否添加一些功能等等,然后执行赋值以及复制到指定目录
prompting
询问部分:
这里加上async/await
的目的就是为了同步,询问完才能处理下面操作
async prompting() {
this.log('欢迎使用' + chalk.blue('welink-cli') + '脚手架')
await this.prompt([{
type: 'list',
name: 'projectType',
message: '请选择项目类型?',
choices: [
'Mobile',
'PC'
],
default: 'PC'
}]).then(async answer => {
if (answer.projectType == 'PC') {
//PC端
this.answer = Object.assign(answer, await this.prompt([{
type: 'input',
name: 'projectName',
message: '请输入项目名?',
default: this.appname //默认执行yo的所在文件夹名
}, {
type: 'input',
name: 'projectDesc',
message: '请输入项目描述?'
}, {
type: 'input',
name: 'projectAuthor',
message: '请输入项目作者',
default: 'dongdong.wu'
}, {
type: 'confirm',
name: 'echart',
message: '是否加入图表功能组件',
default: 'Y'
}]))
} else {
//移动端
}
})
}
writing()
操作写入部分
先对package.json
操作。这里有两种方式,一种使用ejs
模板(EJS用法)直接写入,还有一种是使用extendJSON
去生成一个package.json
,我这里使用ejs
模板
{
"name": "<%=name %>",
"version": "1.0.0",
"description": "<%=description %>",
"author": "<%=author %>",
"license": "MIT",
...省略
"dependencies": {
...省略
<%if(echart){-%> "echarts": "^4.8.0",<%_}-%>
...省略
}
//this.templatePath('pc') 寻找./templates下的pc文件夹下的内容
//this.destinationPath(this.answer.projectName):以项目名作为生成的文件夹名(当然有默认的 this.appname(这里就是执行yo的所在文件夹名))
this.fs.copyTpl(this.templatePath('pc'), this.destinationPath(this.answer.projectName), {
name: this.answer.projectName,
description: this.answer.projectDesc,
author: this.answer.author,
echart: this.answer.echart,
baseUrl: '<%= BASE_URL %>',
title: '<%= webpackConfig.name %>',
}, {
},
{
globOptions: {
dot: true
}
})
解析
为了不去替换public
中index.html
中的ejs
,想着在package.json
中用?
即使用templateOption
中的delimiter
属性去替换会报错,具体原因未知
所以title
和baseUrl
的传递是无奈之举,Vue
中会有个public
文件夹,其中的title
和icon
地址等,html-webpack-plugin
暴露的默认值以及.env
暴露的变量值
所以index.html
改造一下接收字符
最后执行yo welink-cli
的时候发现,以.
开头的文件没有复制出来。
具体得看copyOption
这个参数的配置,其集成fast-glob
dot
属性:默认为false
:即以点开头的文件会被忽略。
而根据源码
可以看到最后copyTpl
调用的是copy
,而其中copyOptions
其中还包有一个对象层globOptions
。基本的复制算完了
效果
新建一个名为test
的文件夹,然后在该文件夹下执行yo welink-cli
选择项目类型
新建项目名(默认以当前文件夹作为项目名)
千里之行
始于足下