Element3开发内幕 - Vue CLI插件开发
官方开发指南 cli.vuejs.org/zh/dev-guid…
我们团队的Element发布了。为了让大家使用起来便捷。需要加入vue-cli和vite生态之中。
今天先说说vue-cli插件如何开发。
大家可以尝试一下先
vue create vue3-demo vue add element3
一、什么是Vue CLI插件
Vue CLI工具是Vue生态在Vue生态中负责工具基础标准化。他使用一套基于插件的架构。
比如vue-router、vuex或者安装组件库等都可以通过插件的形式安装。
vue add
的设计意图是为了安装和调用 Vue CLI 插件。
# 插件安装 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仓库后 ,我们通过
vue add element3
就可以安装插件了
mkdir vue-cli-plugin-element3 npm init -y
2. 安装配置命令行交互
在安装插件前通常会通过命令行交互形式,选择一下安装参数:
比如Element中需要询问
- 是否全局安装
- 是否使用sass?
这个功能是使用通过 inquirer 实现。其实你自己写一个cli工具一般也会用这个功能
在这里面我们只需要编辑一下 prompts.js文件就可以了。具体配置可以参考 inquirer
module.exports = [ { type: 'list', name: 'import', message: 'How do you want to import Element3?', choices: [ { name: 'Fully import', value: 'full' }, { name: 'Import on demand', value: 'partial' } ], default: 'full', }, { when: answers => answers.import === 'full', type: 'confirm', name: 'customTheme', message: 'Do you wish to overwrite Element\'s SCSS variables?', default: false, }, ]
3. 代码生成器Generator
添加element3组件库的主要功能集中在生成器上。生成器的作用就是
- 修改已有代码
- 添加代码
- 添加依赖
- 其他功能(比如babel配置)
如果手工添加Element3库大概需要以下步骤:
- npm添加依赖库
- 以vue plugin形式添加组件库
- main.js引用组件库
- App.vue中写一个代码例子 比如: 引用一个按钮 确认安装效果
3.1 添加依赖
module.exports = (api, opts, rootOptions) => { api.extendPackage({ dependencies: { 'element3': '^0.0.26' } }) }
这个功能其实就是调用cli提供的api就可以实现了。
3.2 添加插件
添加插件的过程其实就是需要添加/plugins/element.js文件
生成代码通常会使用模板引擎渲染方式,过程类似后端代码渲染,常用的库有ejs模板和hbs模板
cli工具中要求我们使用ejs模板。
如果想了解模板引擎实现原理 请看这篇【天天造轮子 - 模板引擎】]
首先定义模板
// 部分节选 <%_ if (options.import === 'full') { _%> import Element3 from 'element3' <%_ if (options.customTheme) { _%> import '../element-variables.scss' <%_ } else { _%> import 'element3/lib/theme-chalk/index.css' <%_ } _%> <%_ if (options.lang !== 'en') { _%> import locale from 'element3/lib/locale/lang/<%= options.lang %>' <%_ } _%> <%_ } else { _%> import { ElButton } from 'element3' import 'element3/lib/theme-chalk/index.css' <%_ if (options.lang !== 'en') { _%> import lang from 'element3/lib/locale/lang/<%= options.lang %>' import locale from 'element3/lib/locale' <%_ }} _%> export default (app) => { <%_ if (options.import === 'full') { _%> <%_ if (options.lang !== 'en') { _%> app.use(Element3, { locale }) <%_ } else { _%> app.use(Element3) <%_ } _%> <%_ } else { _%> <%_ if (options.lang !== 'en') { _%> locale.use(lang) <%_ } _%> app.use(ElButton) <%_ } _%> }
调用模板引擎渲染
这里面还是使用api提供的render方法 其实就是ejs模板引擎
api.render({ './src/plugins/element.js': './templates/src/plugins/element.js.ejs', })
3.3 添加插件引用
添加插件引用相当于在main.js文件中增加内容
这个程序逻辑比较简单 ,只需要通过简单的文件操作+正则就可以完成。
如果是复杂功能还需要借助AST抽象语法树完成。这个后续章节有介绍。
api.afterInvoke(() => { const { EOL } = require('os') const fs = require('fs') const contentMain = fs.readFileSync(api.resolve(api.entryFile), { encoding: 'utf-8' }) const lines = contentMain.split(/\r?\n/g) const renderIndex = lines.findIndex(line => line.match(/createApp\(App\)\.mount\('#app'\)/)) lines[renderIndex] = `const app = createApp(App)` lines[renderIndex + 1] = `installElement3(app)` lines[renderIndex + 2] = `app.mount('#app')` fs.writeFileSync(api.resolve(api.entryFile), lines.join(EOL), { encoding: 'utf-8' }) })
3.4 添加代码示例
这个功能还是通过代码模板渲染代码。
<template> <div id="app"> <img src="./assets/logo.png"> <div> <p> If Element3 is successfully added to this project, you'll see an <code v-text="'<el-button>'"></code> below </p> <el-button type="primary">el-button</el-button> </div> <HelloWorld msg="Welcome to Your Vue.js App"/> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
api.render({ './src/App.vue': './templates/src/App.vue.ejs' })
4. Service处理
service的会在启动服务时运行。我们这里就小小的秀一下Logo。
我们使用figlet + chalk完成
const figlet = require('figlet') const chalk = require('chalk') module.exports = () => { console.log(chalk.yellow(figlet.textSync('Element 3', { font: 'big', horizontalLayout: 'default', verticalLayout: 'default', width: 80, whitespaceBreak: true }))); }
三、本地调试
在没有上传npm前需要,本地安装,方法如下:
# 再次安装依赖 yarn npm install --save-dev file:/Users/xiaran/source/hug-sun/vue-cli-plugin-element3 vue invoke vue-cli-plugin-element3
四、上传npm仓库
上传仓库就是执行npm publish就行了。只不过要注意需要更改镜像仓库。上传完后再改回来。
#!/usr/bin/env bash npm config get registry # 检查仓库镜像库 npm config set registry=http://registry.npmjs.org echo '请进行登录相关操作:' npm login # 登陆 echo "-------publishing-------" npm publish # 发布 npm config set registry=https://registry.npm.taobao.org # 设置为淘宝镜像 echo "发布完成" exit
作者:全栈然叔
链接:https://juejin.cn/post/6899334776860180494
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。