自定义vue-cli远程preset模板

前言

vue-cli提供了一个名为preset的功能,即预设,顾名思义就是将vue-cli的一些设置保存在preset文件中,以便快速复用;

而远程preset则拥有更多的扩展性,可以用来定制扩展的脚手架功能,如定制项目模板;

远程preset的组成

远程preset本质上就是一个vue-cli插件项目,其中最核心的部分是:

  • preset.json:预设文件,可以被vue-cli识别自动安装一些插件;
  • prompts.js:返回一个数组,该数组格式参照inquirer.jsprompt方法参数,因此该文件的功能就是提供一个交互式命令,交互的结果会被传递到生成器(即generator/index.js导出的函数)中;
  • generator/index.js:生成器,该文件导出一个函数,该函数接收三个参数,提供一些内置的API和交互参数,用于处理项目文件及结构;

远程preset处理流程

img

生成器

生成器可以说是整个远程preset中扩展性最强的部分,也是自由度最大的部分,除了可以接收preset配置和交互式命令的结果,还能利用提供的Generator API实例快速地改变项目结构和自由组合;

生成器函数的结构

1
2
3
4
5
// generator/index.js

module.exports = (api, options, preset) => {
// do something
}

常用的Generator API

  • extendPackage(packageInfo: object):用于合并生成项目中的package.json
    传入需要增加或覆盖的字段即可,如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    api.extendPackage({
    "scripts": {
    "lint:nofix": "vue-cli-service lint --no-fix",
    "lint:ts": "vue-cli-service lint --ext .ts --no-fix",
    "type-check": "tsc --noEmit"
    },
    "devDependencies": {
    "lint-staged": "^10.2.11",
    "chalk": "^4.1.0",
    "cz-conventional-changelog": "^3.2.0",
    "husky": "^4.2.5"
    },
    "lint-staged": {
    "src/**/*.(js|ts|vue)": [
    "vue-cli-service lint --no-fix"
    ]
    },
    "husky": {
    "hooks": {
    "pre-commit": "npm run type-check && lint-staged",
    "commit-msg": "node ./hooks/commit-msg $HUSKY_GIT_PARAMS && commitlint -E HUSKY_GIT_PARAMS",
    "post-merge": "node ./hooks/post-merge",
    "pre-push": "node ./hooks/pre-push $HUSKY_GIT_PARAMS"
    }
    }
    })
  • render():用于渲染模板文件,实际上背后就是基于ejs渲染引擎;该方法有三个参数,一般情况下只会用到第一个参数,用于添加模板文件或者移除一些默认文件;

    img

    • 由于渲染引擎是ejs,因此如果模板文件中包含了一些ejs语句,就需要对一些语句进行特殊处理,否则渲染时会报错;主要的是将<%变成<%%即可,这样在渲染后模板文件中的<%%就会自动变成<%,在项目中使用就是正常的;

    • 对于ejs不能识别的那些文件,只要不是空文件就会按相对于模板根目录的路径复制到创建项目中;

    • 利用回调函数,甚至可以删除默认创建的一些文件,如:

    1
    2
    3
    4
    5
    6
    // 删除 vue-cli 默认目录
    api.render(files => {
    Object.keys(files)
    .filter(removeFile)
    .forEach(path => delete files[path]) // 删除键等同于删除对应的文件
    })

    可以看到回调函数可以得到一个对象,该对象是当前项目中已经存在的文件,键名就是文件路径(包括文件名),当删除该对象的键(即属性)时等同于删除了该文件,可以用来删除vue-cli创建的某些默认文件;

模板文件

所谓的模板文件,就是指通过render()方法进行渲染或者复制到新项目的那些文件,其本质上是一个空白项目(或者一部分);模板文件可以放在一个文件夹内,也可以分开放在不同的地方,根据参数不同然后进行组装,这取决于创建项目的流程设计了;

注意事项

  • 文件名如果是以点.开头的(常见于配置文件),需要把点换成下划线_
  • 文件名如果是以单个下划线_开头的,需要把单个下划线_替换成双下划线__

相关文档