官方开发指南 https://cli.vuejs.org/zh/dev-guide/plugin-dev.html

我们团队的Element发布了。为了让大家使用起来便捷。需要加入vue-cli和vite生态之中。

今天先说说vue-cli插件如何开发。

大家可以尝试一下先

  1. vue create vue3-demo
  2. vue add element3

Element3的Vue Cli插件的开发 - 图1

一、什么是Vue CLI插件

Vue CLI工具是Vue生态在Vue生态中负责工具基础标准化。他使用一套基于插件的架构。

比如vue-router、vuex或者安装组件库等都可以通过插件的形式安装。

vue add 的设计意图是为了安装和调用 Vue CLI 插件。

  1. # 插件安装
  2. vue add vuex

一个vue add xxx就搞定了。

二、功能实现

1. 搭建框架

1.1 初始npm库

为了让一个 CLI 插件在 Vue CLI 项目中被正常使用,它必须遵循 vue-cli-plugin-<name> 或者 @scope/vue-cli-plugin-<name> 这样的命名惯例。这样你的插件才能够:

  • @vue/cli-service 发现;

也就是说我们只需要将npm库的名字命名为 vue-cli-plugin-element3

这样只要最后提交到npm仓库后 ,我们通过

  1. vue add element3

就可以安装插件了

  1. mkdir vue-cli-plugin-element3
  2. npm init -y

Element3的Vue Cli插件的开发 - 图2

2. 安装配置命令行交互

在安装插件前通常会通过命令行交互形式,选择一下安装参数:

比如Element中需要询问

  • 是否全局安装
    Element3的Vue Cli插件的开发 - 图3
  • 是否使用sass?
    Element3的Vue Cli插件的开发 - 图4

这个功能是使用通过 inquirer 实现。其实你自己写一个cli工具一般也会用这个功能

在这里面我们只需要编辑一下 prompts.js文件就可以了。具体配置可以参考 inquirer

  1. module.exports = [
  2. {
  3. type: 'list',
  4. name: 'import',
  5. message: 'How do you want to import Element3?',
  6. choices: [
  7. { name: 'Fully import', value: 'full' },
  8. { name: 'Import on demand', value: 'partial' }
  9. ],
  10. default: 'full',
  11. },
  12. {
  13. when: answers => answers.import === 'full',
  14. type: 'confirm',
  15. name: 'customTheme',
  16. message: 'Do you wish to overwrite Element\'s SCSS variables?',
  17. default: false,
  18. },
  19. ]

3. 代码生成器Generator

添加element3组件库的主要功能集中在生成器上。生成器的作用就是

  • 修改已有代码
  • 添加代码
  • 添加依赖
  • 其他功能(比如babel配置)

如果手工添加Element3库大概需要以下步骤:

  • npm添加依赖库
  • 以vue plugin形式添加组件库
  • main.js引用组件库
  • App.vue中写一个代码例子 比如: 引用一个按钮 确认安装效果

Element3的Vue Cli插件的开发 - 图5

3.1 添加依赖

  1. module.exports = (api, opts, rootOptions) => {
  2. api.extendPackage({
  3. dependencies: {
  4. 'element3': '^0.0.26'
  5. }
  6. })
  7. }

这个功能其实就是调用cli提供的api就可以实现了。

3.2 添加插件

添加插件的过程其实就是需要添加/plugins/element.js文件

生成代码通常会使用模板引擎渲染方式,过程类似后端代码渲染,常用的库有ejs模板和hbs模板

cli工具中要求我们使用ejs模板。

如果想了解模板引擎实现原理 请看这篇【天天造轮子 - 模板引擎】](https://juejin.cn/post/6884138429181870093)

首先定义模板

  1. // 部分节选
  2. <%_ if (options.import === 'full') { _%>
  3. import Element3 from 'element3'
  4. <%_ if (options.customTheme) { _%>
  5. import '../element-variables.scss'
  6. <%_ } else { _%>
  7. import 'element3/lib/theme-chalk/index.css'
  8. <%_ } _%>
  9. <%_ if (options.lang !== 'en') { _%>
  10. import locale from 'element3/lib/locale/lang/<%= options.lang %>'
  11. <%_ } _%>
  12. <%_ } else { _%>
  13. import { ElButton } from 'element3'
  14. import 'element3/lib/theme-chalk/index.css'
  15. <%_ if (options.lang !== 'en') { _%>
  16. import lang from 'element3/lib/locale/lang/<%= options.lang %>'
  17. import locale from 'element3/lib/locale'
  18. <%_ }} _%>
  19. export default (app) => {
  20. <%_ if (options.import === 'full') { _%>
  21. <%_ if (options.lang !== 'en') { _%>
  22. app.use(Element3, { locale })
  23. <%_ } else { _%>
  24. app.use(Element3)
  25. <%_ } _%>
  26. <%_ } else { _%>
  27. <%_ if (options.lang !== 'en') { _%>
  28. locale.use(lang)
  29. <%_ } _%>
  30. app.use(ElButton)
  31. <%_ } _%>
  32. }

调用模板引擎渲染

这里面还是使用api提供的render方法 其实就是ejs模板引擎

  1. api.render({
  2. './src/plugins/element.js': './templates/src/plugins/element.js.ejs',
  3. })

3.3 添加插件引用

添加插件引用相当于在main.js文件中增加内容

Element3的Vue Cli插件的开发 - 图6

这个程序逻辑比较简单 ,只需要通过简单的文件操作+正则就可以完成。

如果是复杂功能还需要借助AST抽象语法树完成。这个后续章节有介绍。

  1. api.afterInvoke(() => {
  2. const { EOL } = require('os')
  3. const fs = require('fs')
  4. const contentMain = fs.readFileSync(api.resolve(api.entryFile), { encoding: 'utf-8' })
  5. const lines = contentMain.split(/\r?\n/g)
  6. const renderIndex = lines.findIndex(line => line.match(/createApp\(App\)\.mount\('#app'\)/))
  7. lines[renderIndex] = `const app = createApp(App)`
  8. lines[renderIndex + 1] = `installElement3(app)`
  9. lines[renderIndex + 2] = `app.mount('#app')`
  10. fs.writeFileSync(api.resolve(api.entryFile), lines.join(EOL), { encoding: 'utf-8' })
  11. })

3.4 添加代码示例

这个功能还是通过代码模板渲染代码。

  1. <template>
  2. <div id="app">
  3. <img src="./assets/logo.png">
  4. <div>
  5. <p>
  6. If Element3 is successfully added to this project, you'll see an
  7. <code v-text="'<el-button>'"></code>
  8. below
  9. </p>
  10. <el-button type="primary">el-button</el-button>
  11. </div>
  12. <HelloWorld msg="Welcome to Your Vue.js App"/>
  13. </div>
  14. </template>
  15. <script>
  16. import HelloWorld from './components/HelloWorld.vue'
  17. export default {
  18. name: 'App',
  19. components: {
  20. HelloWorld
  21. }
  22. }
  23. </script>
  24. <style>
  25. #app {
  26. font-family: Avenir, Helvetica, Arial, sans-serif;
  27. -webkit-font-smoothing: antialiased;
  28. -moz-osx-font-smoothing: grayscale;
  29. text-align: center;
  30. color: #2c3e50;
  31. margin-top: 60px;
  32. }
  33. </style>
  1. api.render({
  2. './src/App.vue': './templates/src/App.vue.ejs'
  3. })

4. Service处理

service的会在启动服务时运行。我们这里就小小的秀一下Logo。

Element3的Vue Cli插件的开发 - 图7

我们使用figlet + chalk完成

  1. const figlet = require('figlet')
  2. const chalk = require('chalk')
  3. module.exports = () => {
  4. console.log(chalk.yellow(figlet.textSync('Element 3', {
  5. font: 'big',
  6. horizontalLayout: 'default',
  7. verticalLayout: 'default',
  8. width: 80,
  9. whitespaceBreak: true
  10. })));
  11. }

三、本地调试

在没有上传npm前需要,本地安装,方法如下:

  1. # 再次安装依赖
  2. yarn
  3. npm install --save-dev file:/Users/xiaran/source/hug-sun/vue-cli-plugin-element3
  4. vue invoke vue-cli-plugin-element3

四、上传npm仓库

上传仓库就是执行npm publish就行了。只不过要注意需要更改镜像仓库。上传完后再改回来。

  1. #!/usr/bin/env bash
  2. npm config get registry # 检查仓库镜像库
  3. npm config set registry=http://registry.npmjs.org
  4. echo '请进行登录相关操作:'
  5. npm login # 登陆
  6. echo "-------publishing-------"
  7. npm publish # 发布
  8. npm config set registry=https://registry.npm.taobao.org # 设置为淘宝镜像
  9. echo "发布完成"
  10. exit

Element3的Vue Cli插件的开发 - 图8

五、常用插件一览

开发框架

UI组件库

实用库

服务端


  • nuxt.js - 用于服务器渲染Vue app的最小化框架
  • express-vue - 简单的使用服务器端渲染vue.js
  • vue-ssr - 非常简单的VueJS服务器端渲染模板
  • vue-ssr - 结合Express使用Vue2服务端渲染
  • vue-easy-renderer - Nodejs服务端渲染

辅助工具

应用实例

Demo示例