vue-cli 插件开发指南html
TLDR前端
vue-cli 3 彻底推翻了 vue-cli 2 的总体架构设计,因此当你须要给组里定制一份基于 vue-cli 的前端项目初始化模板时,就须要去思考:我该怎么作?vue
咱们要作的事情很简单,就是当别人使用 vue create xxx
命令初始化一个前端项目时,能够从 git repo 去拉取项目初始化信息,好处有两点:ios
由于 vue-cli 3 才出来不久,因此探索的过程当中踩了不少坑,这里就来总结下。git
vue-cli 官网介绍到:github
你能够经过发布 git repo 将一个 preset 分享给其余开发者。这个 repo 应该包含如下文件:vue-router
- 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
是否是看上去很简单,起码我在实践过程当中仍是遇到了一些问题,接下来就重点讲下。vuex
git repo 参数vue-cli
上面 --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 plugin 和 GeneratorAPI.js 源码 对于 api.render
须要注意几点:
render
函数会将你所传目录内的全部文件覆盖初始化项目中 src
目录下的文件(个人测试结果是限于两层目录);object
,其中 key
对应初始化项目中的目标位置,value
对应模板项目中的文件位置;.
开头的文件时,模板项目中须要用 _
替代 .
,这点官网有说明;最后再说个很重要点,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.vuex
和 options.elementUI
就是用户在处理 prompts.js
中设定的问题的回答值。正是基于这点,我没有再去使用 api.postProcessFiles
这个 api 。
今天就写到这里,后续有补充再写~