Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【Vue CLI】手把手教你撸插件 #13

Open
zhuping opened this issue Jul 15, 2020 · 0 comments
Open

【Vue CLI】手把手教你撸插件 #13

zhuping opened this issue Jul 15, 2020 · 0 comments
Labels

Comments

@zhuping
Copy link
Owner

zhuping commented Jul 15, 2020

现如今 Vue 作为主流的前端框架之一,其健全的配套工具,活跃的开源社区,让广发码农热衷追捧。Vue CLI 作为其官方的开发构建工具,目前已更新迭代到 4.x 版本,其内部集成了日常开发用到的打包压缩等功能,简化了常规自己动手配置 webpack 的烦恼。另外提供的插件功能更是满足了使用者定制化的需求场景,那么本文就来讲下如何去开发一个插件。

假设我们团队现在需要去开发一套 UI 组件库,由于团队内每个人的编码习惯不一样,可能会出现单一组件命名、目录结构等不统一的问题,对于团队统一对外呈现的组件库来说,这当然不是一件好事。那有什么办法可以去约束团队成员统一风格呢?这里我们就可以开发一个组件插件来解决这些烦恼,那么我们来看下如何来开发这个组件插件呢?

命名规范

为了让一个 CLI 插件能够被其他开发者使用,官方介绍了必须遵循 vue-cli-plugin- 的命名约定,所以这里我们命名为 vue-cli-plugin-next-component。

mkdir vue-cli-plugin-next-component && cd $_

对于官方自己的插件,都是以 @vue/cli-plugin- 命名以示区别。

目录结构

确定好插件名称后,我们就要为它填充目录结构了。首先我们得先确认,这个插件具体要实现哪些功能:

通过对话的形式,接收开发者输入的组件信息,包括组件名称,类型,作者等信息
获取组件信息,用来渲染内置的 template 组件模板,这样保证所有创建的组件都是统一的结构目录
至此,大致的结构目录如下:

.
├── README.md
├── generator 
│ ├── template 
│ └── index.js # generator
├── prompts.js # prompt 文件 (可选)
├── index.js # service 插件
└── package.json

Service 插件作为其主要导出文件,导出的函数接受两个参数,包含 api 和 options,api 允许 service 插件针对不同的环境扩展/修改内部的 webpack 配置,并向 vue-cli-service 注入额外的命令。options 包含了 vue.config.js 内指定选项的对象或者是在 package.json 内的 vue 字段。

module.exports = (api, options) => {
 api.chainWebpack(webpackConfig => {
 // 通过 webpack-chain 修改 webpack 配置
 })

 api.configureWebpack(webpackConfig => {
 // 修改 webpack 配置
 // 或返回通过 webpack-merge 合并的配置对象
 })

 api.registerCommand('test', args => {
 // 注册 `vue-cli-service test`
 })
}

Prompt 作为对话文件,在插件被初始化的时候会被调用,底层使用了 inquire 模块,最终返回一个用于 inquire 的问题的数组,被解析的答案会作为选项被传递给插件的 generator,这里我们可以增加一些组件相关的问题,同时也可以对输入的内容做校验。

module.exports = [
  {
    name: 'componentName',
    type: 'input',
    message: '请输入要创建的组件名称(kebab-case):',
    validate: function(str) {
    return /^[a-z][a-z|-]*[a-z]$/.test(str);
    }
  },
  {
    name: 'componentCnName',
    type: 'input',
    message: '请输入要创建的组件中文名称(中文):',
    validate: function(str) {
      return /[^\x00-\xff]$/.test(str);
    }
  },
  ...
]

Generator 最终导出一个函数,这个函数接收三个参数,一个是 GeneratorAPI 实例,对于第三方插件来说,options 来自 prompt 对话内容,如果用户使用某个预设创建项目,整个预设将作为第三个参数传递。在调用 render 方法时,该 generator 将使用 ejs 来渲染 template 模板,所以我们在写模板时,需要把动态配置的地方,用 ejs 的模板语法去标注。

module.exports = (api, options, rootOptions) => {
 api.render('./template', {
 ...options
 });
}

模板示例:

<template>
 <div>I am a <%=camelName %> component. Rewrite me from here.</div>
</template>

<script>
export default {
 name: 'nx-<%=componentName %>'
};
</script>

测试验证

完成插件的开发后,先来本地验证下。先建个目录执行 npm init 后,通过 install 安装写好的插件,
image

安装好后,通过 vue invoke 指令初始化插件
image

最终我们会看到 test 目录里已经多了一个 packages 目录,同时下面有个叫 button的组件子目录,这样就满足我们预期目标啦,让参与组件开发的同学更加专注的去写代码就行了,不用再关心目录、命名等规范要求了。
image

小结

对于一些项目开发,如果需要经常引入其他工程的一些功能模块或者是业务组件,但又不想每次都是复制粘贴,就可以写个插件来帮你完成,解放双手,一劳永逸。另外,插件也弥补了脚手架在定制化方面的不足,让附加功能变得单一便捷可插拔,使得 Vue CLI 工具能够更加专注在 Vue 项目脚手架上,将 Vue 生态中的工具基础更加标准通用化。

附上完整插件代码,点击查看

文献参考

插件开发指南

@zhuping zhuping added the Vue label Jul 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant