vue-cli 之 Preset

vue-cli 插件开发指南

TLDR

背景介绍

vue-cli 3 完全推翻了 vue-cli 2 的整体架构设计,所以当你需要给组里定制一份基于 vue-cli 的前端项目初始化模板时,就需要去思考:我该怎么做?

我们要做的事情很简单,就是当别人使用 vue create xxx 命令初始化一个前端项目时,可以从 git repo 去拉取项目初始化信息,好处有两点:

  1. 团队内部所有的新项目都是统一的目录结构代码组织方式,便于维护
  2. 后期可以开发公共插件服务于不同的项目,提高效率

因为 vue-cli 3 才出来不久,所以探索的过程中踩了很多坑,这里就来总结下。

整体设计

vue-cli 官网介绍到:

你可以通过发布 git repo 将一个 preset 分享给其他开发者。这个 repo 应该包含以下文件:

  • preset.json: 包含 preset 数据的主要文件(必需)。
  • generator.js: 一个可以注入或是修改项目中文件的 Generator。
  • prompts.js: 一个可以通过命令行对话为 generator 收集选项的 prompts 文件。
# 从 GitHub repo 使用 preset
vue create --preset username/repo my-project

GitLab 和 BitBucket 也是支持的。如果要从私有 repo 获取,请确保使用 --clone 选项:

vue create --preset gitlab:username/repo --clone my-project
vue create --preset bitbucket:username/repo --clone my-project

是不是看上去很简单,起码我在实践过程中还是遇到了一些问题,接下来就重点讲下。

git repo 参数

上面 --preset 后跟的参数 username/repo 实际是下图中的红框内部分(千万别以为是 git clone 后的地址):

preset.json 文件

先说一点:当你直接用 vue create xxx 初始化项目时,如果你将初始化信息保存成一个本地模板后,会写入到你系统的 ~/.vuerc 文件中。该文件中的内容其实就是我们接下来需要配置的 present.json

此处直接 show code :

{
"useConfigFiles": true, "cssPreprocessor": "less", "plugins": { "@vue/cli-plugin-babel": {
"version": "^3.0.0"
}, "@vue/cli-plugin-eslint": {
"version": "^3.0.0", "config": "recommended", "lintOn": ["save", "commit"]
}
}, "configs": { "vue": {
"baseUrl": "/", "outputDir": "dist", "assetsDir": "static", "filenameHashing": true, "lintOnSave": true, "runtimeCompiler": false, "transpileDependencies": [], "productionSourceMap": false, "pages": {
"index": {
"entry": "src/main.js",
"template": "public/index.html",
"filename": "index.html",
"title": "首页",
"chunks": ["chunk-vendors", "chunk-common", "index"]
}
}, "devServer": {
"open": true, "host": "127.0.0.1", "https": false, "hotOnly": false, "proxy": null
}, "pwa": {}, "pluginOptions": {}
}, "postcss": {}, "eslintConfig": {
}
}, "router": true, "vuex": false, "routerHistoryMode": false
}

其中当 "useConfigFiles": true 时, configs 内的配置信息会直接覆盖初始化后项目中的 vue.config.js

prompts.js 文件

prompts.js 其实就是你在初始化项目时,系统会询问你的配置选项问题,比如你的项目需不需要安装 vuex? 需不需要安装 vue-router?

你的回答会直接影响后面初始化生成的项目文件。

这里最需要注意一点!!!

当你查看官方文档时,第一眼看到就是下图:

只要你这样写,就一定会 报错 !!!

原因很简单:上图中 prompts.js 的写法是开发基于 vue-cli-service 插件的代码。而当你是要开发项目模板时,正确写法如下:

module.exports = [
{
name: "vuex",
type: "confirm",
message: `是否需要使用 vuex`,
default: false
},
{
name: "elementUI",
type: "confirm",
message: `element-ui`,
default: false
}
];

这一点其实官网也有提到,只是很不容易注意到。

此处再给大家安利下 vue-cli-plugin-vuetify 这个开源插件中 prompts.js 的写法。程序猿嘛,最爱的就是栗子。

generator.js 文件

接下来就是 generator.js,这个文件负责的就是 注入或是修改项目中文件

同样,我还是直接 show code :

module.exports = (api, options, rootOptions) => {
// 安装一些基础公共库
api.extendPackage({
dependencies: {
"axios": "^0.18.0",
"lodash": "^4.17.10",
"keymirror": "^0.1.1"
},
devDependencies: {
"mockjs": "^1.0.1-beta3"
}
}); // 安装 vuex
if (options.vuex) {
api.extendPackage({
dependencies: {
vuex: '^3.0.1'
}
}); api.render('./template/vuex');
} // 安装 element-ui 库
if (options.elementUI) {
api.extendPackage({
devDependencies: {
"element-ui": "^2.4.6"
}
});
} // 公共基础目录和文件
api.render('./template/default'); // 配置文件
api.render({
'./.eslintrc.js' : './template/_eslintrc.js',
'./.gitignore' : './template/_gitignore',
'./.postcssrc.js' : './template/_postcssrc.js'
});
}

核心 api:

  • api.extendPackage : 负责给初始化项目中的 package.json 添加额外依赖并安装;
  • api.render : 负责将模板项目中提前定义好的目录和文件拷贝到初始化的项目中;
  • api.postProcessFiles : 负责具体处理模板项目中的文件,关于它可以参考 How to build your own vue-cli 3 pluginGeneratorAPI.js 源码

对于 api.render 需要注意几点:

  1. 拷贝目录的话,直接传地址字符串,render 函数会将你所传目录内的所有文件覆盖初始化项目中 src 目录下的文件(我的测试结果是限于两层目录);
  2. 拷贝文件的话,直接传入一个 object,其中 key 对应初始化项目中的目标位置,value 对应模板项目中的文件位置;
  3. 当你需要创建一个以 . 开头的文件时,模板项目中需要用 _ 替代 .,这点官网有说明;

最后再说个很重要点,vue-cli 3 在拷贝文件时使用的是 EJS 模板去实现的,所以开发者是可以在任意文件中使用 EJS 语法去做更细粒度的控制。比如我的 main.js:

import Vue from 'vue'
import App from './App.vue'
<%_ if (options.vuex) { _%>
import store from './store'
<%_ } _%>
<%_ if (options.elementUI) { _%>
import ElementUI from 'element-ui';
Vue.use(ElementUI);
<%_ } _%> // simulation data
import './mock/index'; Vue.config.productionTip = false new Vue({
router,
<%_ if (options.vuex) { _%>
store,
<%_ } _%>
render: h => h(App)
}).$mount('#app')

其中 options.vuexoptions.elementUI 就是用户在处理 prompts.js 中设定的问题的回答值。正是基于这点,我没有再去使用 api.postProcessFiles 这个 api 。

今天就写到这里,后续有补充再写~

如何使用 vue-cli 3 的 preset 打造基于 git repo 的前端项目模板的更多相关文章

  1. [Vue 牛刀小试]:第十七章 - 优化 Vue CLI 3 构建的前端项目模板(1)- 基础项目模板介绍

    一.前言 在上一章中,我们开始通过 Vue CLI 去搭建属于自己的前端 Vue 项目模板,就像我们 .NET 程序员在使用 asp.net core 时一样,我们更多的会在框架基础上按照自己的开发习 ...

  2. 如何打造一个"逼格"的web前端项目

    最近利用空余的时间(坐公交车看教程视频),重新了解了前后端分离,前端工程化等概念学习,思考如何打造一个“逼格”的web前端项目. 前端准备篇 前端代码规范:制定前端开发代码规范文档. PS:重中之中, ...

  3. 在基于ABP框架的前端项目Vue&Element项目中采用电子签名的处理

    在前面随笔介绍了<在基于ABP框架的前端项目Vue&Element项目中采用电子签章处理文件和打印处理>的处理,有的时候,我们在流程中或者一些文件签署的时候,需要签上自己的大名,一 ...

  4. vue开发:前端项目模板

    简介 vue-cli创建vue项目,整合vuex.vue-router.axios.element-ui 项目模板下载地址 创建项目 使用vue-cli创建项目,功能选择:Babel.Router.v ...

  5. 在基于ABP框架的前端项目Vue&Element项目中采用日期格式处理,对比Moment.js和day.js的处理

    Day.js 是一个轻量的处理时间和日期的 JavaScript 库,和 Moment.js 的 API 设计保持完全一样. 如果您曾经用过 Moment.js, 那么您已经知道如何使用 Day.js ...

  6. 在基于ABP框架的前端项目Vue&Element项目中采用电子签章处理文件和打印处理

    在一些内部OA或者流转的文件,或者给一些客户的报价文件.合同,或者一些医院出示的给保险机构的病历资料等,有时候可能都希望快速的使用电子签章的处理方式来给文件盖上特定的印章,本篇随笔介绍基于Vue&am ...

  7. vue cli 3

    介绍 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统 通过 @vue/cli 搭建交互式的项目脚手架. 通过 @vue/cli + @vue/cli-service-global 快 ...

  8. 13. Vue CLI脚手架

    一. Vue CLI 介绍 1. 什么是Vue CLI? Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统.Vue CLI 致力于将 Vue 生态中的工具基础标准化.它确保了各种构建工 ...

  9. Vue CLI 是如何实现的 -- 终端命令行工具篇

    Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供了终端命令行工具.零配置脚手架.插件体系.图形化管理界面等.本文暂且只分析项目初始化部分,也就是终端命令行工具的实现. 0. 用法 ...

随机推荐

  1. Nginx搭建动态静态服务器

    Nginx做静态资源服务器优于Tomcat 区分静态资源,动态资源请求 使用域名区分! 如果是动态资源请求  反向代理到 Tomcat 如果 是静态资源请求  直接走本地Nginx 配置: ###静态 ...

  2. Tomcat-8.5.39性能监控及调优

    一.下载地址 https://tomcat.apache.org/download-80.cgi 二.安装步骤 将安装包 apache-tomcat-8.5.39.tar.gz 上传至服务器 /usr ...

  3. asp.net mvc model attribute and razor and form and jquery validate 完美结合

    1.创建Model,添加标注. [Serializable] public class BaseUserModel:BaseModel { [StringLength(100)] [Required( ...

  4. C#代码获取另一程序的错误提示,并关闭窗口。

    A程序报错弹框如下: B程序捕捉到此错误消息,并关闭.B程序核心代码如下. private void timer_Click(object sender, EventArgs e) { //查找Mes ...

  5. Mybatis(一) 入门

    对原生态jdbc程序中问题总结 创建mysql数据库 jdbc程序 使用jdbc查询mysql数据库中用户表的记录. 创建java工程,加入jar包 数据库驱动包 第一个是mysql驱动 第二个是or ...

  6. 区间和序列上的dp

    区间上的dp状态设计最基本的形式: \(F[i]\)表示以i结尾的最优值或方案数. \(F[i][k]\)表示以i结尾附加信息为k的最优值或方案数. 当然可以有多维附加信息. 转移的话往往是枚举上一个 ...

  7. 洛谷 P1073 最优贸易 题解

    题面 大家都是两遍SPFA吗?我这里就一遍dp啊: 首先判断对于一个点u,是否可以从一号点走到这里,并且可以从u走到n号点: 对于这样的点我们打上标记: 那么抛出水晶球的点一定是从打上标记的点中选出一 ...

  8. Python 入门之 内置模块 -- re模块

    Python 入门之 内置模块 -- re模块 1.re 模块 (1)什么是正则? 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类 ...

  9. Comet OJ - Contest #13 「佛御石之钵 -不碎的意志-」(hard)

    来源:Comet OJ - Contest #13 一眼并查集,然后发现这题 tmd 要卡常数的说卧槽... 发现这里又要用并查集跳过访问点,又要用并查集维护联通块,于是开俩并查集分别维护就好了 一开 ...

  10. Codeforces - 1203D2 - Remove the Substring (hard version) - 双指针

    https://codeforces.com/contest/1203/problem/D2 上次学了双指针求两个字符串之间的是否t是s的子序列.但其实这个双指针可以求出的是s的前i个位置中匹配t的最 ...