本文梳理如何搭建和构建前端组件库.javascript
了解几个问题css
为什么须要组件化?html
大部分项目起源都是源于业务方的各类各样的奇葩
需求。随着公司的业务发展,公司内部开始衍生出不少的B2C系统、后台系统,前端部门也疲于应对愈来愈多同质化的项目,这些项目在不少基础模块层、源代码存在不小的类似,甚至存在类似的业务模块。前端
笔者曾经所在的一个电商团队,前端成员基本每一个人多作过登陆注册、购物车、支付、微信登陆...... 大量重复的业务代码。因为组内技术没有强制规范vue
本质上相同的东西,重复的去code就显得浪费.java
分析这些问题发现:
日渐增多的业务场景需求webpack
前端资源有限,没法支持全部项目的快速迭代git
公司内部诸多产品业务混乱、体验不统一web
因而开发底层的工具去服务不一样业务就颇有必要:
设计一套公司内部的基础组件库支撑各个前端项目,提高项目和业务的可用性和一致性。vue-cli
一个前端团队拥有大量的业务场景和业务代码,类似的页面和代码层出不穷,如何管理和抽象这些类似的代码和模块,绝大多数团队会遇到这样的问题。 不断的拷代码? 修改代码?仍是抽象成组件?显而后者更高效。因此在多项目存在高度的可控、底层依赖的状况下,前端实现组件库是最好的选择。
组件化,又或者组件抽离的目的是为了功能
共享方便维护,其可以带来的好处是少写代码,统一管理、统一维护。一套基础组件代码千锤百炼精而又精,从而起到快速支撑业务迭代,提高开发效率的目的。
业务型组件库
前端组件库百花齐放,antd、element ui这些基础组件库已经很强大,使用于各类业务场景。可是这些基础组件的粒度是基于单个交互
,而在交互
与产品
之间隔着各类各样的模块和业务场景,产品的汇聚源于各类基础组件在业务逻辑的沾粘下集成为一个个项目,一个团队或多或少会有项目或模块存在功能、交互流程的重复、本质上的同质化。
因此antd、element ui 这类组件库是基于单个非连续性的交互组件
,一个组件表明着一次人机
无反作用的操做与响应,其不思考实体、用户、终端的状态,最小化的暴露和响应组件内部状态。对于连续性的交互
一般来讲与特色的业务场景有关,存在诸多的外部依赖,目前都是在各个业务模块由用户(coder)自行编写。
有没有一种方法解决连续性交互流程的共用问题?
解决的办法是组件封装包含业务场景的连续性交互流程,利用组件化将内部依赖经过接口映射到外部。
前端架构部门为业务部门提供业务型组件库
可以有效提升开发效率.
组件库设计思路
组件是对一些具备相同业务场景和交互模式、交互流程代码的抽象,组件库首先应该保证各个组件的视觉风格和交互规范保持一致。组件库的 props 定义须要具有足够的可扩展性,对外提供组件内部的控制权,使组件内部彻底受控。支持经过 children 自定义内部结构,预约义组件交互状态。保持组件具备统一的输入和输出,完整的API.
组件库的开发咱们须要考虑:
一个完整强大的组件库须要多方面努力,回归正题.
使用到的基础技术
Demo
下面就手把手
搭建一个前端偏业务性的组件库。
组件库包括:
只抛出一个栗子,组件内部实现略~
这里注意组件抽取的粒度
,组件的抽离以一个完整的连续性交互为目地。
组件依赖数据、交互事件、控制权的暴露须要考虑全面,不一样的上层业务部门都有本身对组件可配置的不一样渴望。须要权衡,不能把配置化
给捣鼓的永无止境到很难堪的局面。笔者曾经就参与一个项目的组件化,组件抽离的面目全非,各类依赖、环境、状态的配置,致使最后只有组件编写人员在看文档加回忆的状况下才能搞清楚其前因后果.
从简单的开始~
建立一个空项目
// 新建一个项目 vue create qw-ui
通过vue cil3
初始化后的qw-ui
目录:
├─docs │ ├─public │ ├─src │ .gitignore │ babel.config.js │ package-lock.json │ package.json │ README.md │ vue.config.js │
此时为了方便组件库的代码管理,将目录结构修改成:
├─src // 用做示例 Demo │ ├─packages // 新增 packages 用于编写存放组件 │ ├─lib // 新增 lib 用于存放编译后的输出文件 │ .gitignore │ babel.config.js │ package-lock.json │ package.json │ README.md │ vue.config.js │
目录结构能够更具须要调整.
vue cli3 提供一个可选的 vue.config.js 配置文件。这个文件存在则他会被自动加载,全部的对项目和webpack的配置,都在这个文件中。
修改 vue.config.js 配置的目的主要是:
src
目录的编译处理;package
的编译、构建处理作如下两处修改:
entry 字段为项目入口
入口修改使用 Vue CLI 3 的 page属性来配置:
module.exports = { pages: { index: { // page 的入口 entry: 'src/main.js', // 模板来源 template: 'public/index.html', // 在 dist/index.html 的输出 filename: 'index.html' } } }
packages
是咱们后来新增的一个目录,默认是不被 webpack 处理的,因此须要经过添加配置对该目录的编译支持。
新增编译处理目录,须要经过webpack的链式操做chainWebpack函数实现:
module.exports = { pages: { index: { // page 的入口 entry: 'examples/main.js', // 模板来源 template: 'public/index.html', // 在 dist/index.html 的输出 filename: 'index.html' } }, chainWebpack: config => { // packages和examples目录须要加入编译 config.module .rule('js') .include.add(/packages/) .end() .include.add(/src/) .end() .use('babel') .loader('babel-loader') .tap(options => { // 修改它的选项... return options; }); } }
执行 npm run vue-cli-service serve
, 实现对Demo的访问.
建立一个 message组件
建立组件
packages
目录下,全部的单个组件都以文件夹的形式存储,这里建立一个目录 message
文件夹;message/
目录下建立 src/
目录存储组件源码,全部 message
依赖的除第三方资源都存放与该目录下;/message目录下建立
index.js` 文件对外提供对组件的引用示例代码:
message/index.js 对外提供应用
// message/index.js import message from './src/message ' message .install = function (Vue) { Vue.component(message .name, message ) } export default message
// message/src/message .js <template> <div class="message"> <el-row class="message-test"> <el-col :span="12" class="message-row"><p class="text">hello {{ message }}</p></el-col> <el-col :span="6"> <img src="./st.png"/> </el-col> </el-row> </div> </template> <script> import './index.scss' export default { name: 'v-message', // 申明组件的 name属性 props: { message: String } } </script>
须要注意的是,组件 mesage 必须声明 name 属性,这个 name 就是组件的标签,如:
<v-message><v-message/>
packages/message目录结构以下:
packages/message ├─index.js │ ├─src │ message.vue │ st.png // 组件依赖的图片 │ index.scss // 组件依赖的样式文件
导出 packages 组件库
修改 /packages/index.js
文件,整合全部组件,并对整个组件库进行导出:
// 导入组件 import hello from './hello' // 存储组件列表 const components = [ hello ] // 定义 install 方法,接收 Vue 做为参数。若是使用 use 注册插件,则全部的组件都将被注册 const install = function (Vue) { // 判断是否安装 if (install.installed) return // 遍历注册全局组件 components.map(component => Vue.component(component.name, component)) } // 判断是不是直接引入文件 if (typeof window !== 'undefined' && window.Vue) { install(window.Vue) } export default { // 导出的对象必须具备 install,才能被 Vue.use() 方法安装 install, // 如下是具体的组件列表 hello }
到此,构建组件库的环境准好好了
### 四、发布组件库到 npm
packages 目录的编译打包
在 package.json
的 scripts
字段中新增一下命令:
"lib": "vue-cli-service build --target lib --name kui --dest lib packages/index.js"
vue cil3 提供了 [库模式](https://cli.vuejs.org/zh/guide/build-targets.html#%E5%BA%93) 来打包第三方库的开发,packages 的编译打包须要使用库模式
--target
: 构建目标,默认为应用模式。这里修改成 lib
启用库模式。
--dest
: 输出目录,默认 dist
。这里咱们改为 lib
[entry]
: 最后一个参数为入口文件,默认为 src/App.vue
。这里咱们指定编译 packages/
组件库目录。
在 vue cil3 库模式中,Vue 是
外置的。这意味着包中不会有 Vue,即使你在代码中导入了 Vue。若是这个库会经过一个打包器使用,它将尝试经过打包器以依赖的方式加载 Vue;不然就会回退到一个全局的
Vue
变量。
配置好了后,执行编译命令:
npm run lib
稍后控制台输出,即编译完成:
DONE Compiled successfully in 5988ms16:05:35 File Size Gzipped lib\kui.umd.min.js 8.08 KiB 4.55 KiB lib\kui.umd.js 17.78 KiB 7.31 KiB lib\kui.common.js 17.41 KiB 7.19 KiB lib\kui.css 0.10 KiB 0.10 KiB Images and other types of assets omitted.
Total task duration: 8.71s ```
package.json 配置
name
: 包名,该名字是惟一的。可在 npm 官网搜索名字。version
: 版本号,每次发布至 npm 须要修改版本号,不能和历史版本号相同。description
: 描述。main
: 入口文件,该字段需指向咱们最终编译后的包文件。keyword
:关键字,以空格分离但愿用户最终搜索的词。author
:做者private
:是否私有,须要修改成 false 才能发布到 npmlicense
: 开源协议
参考配置:
{ "name": "qw-ui", "version": "0.1.0", "private": false, "main": "lib/kui.umd.min.js", "description": "qw-ui", "keyword": "qw-ui", "author":"luojh", "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "lib": "vue-cli-service build --target lib --name kui --dest lib packages/index.js" } }
添加 .npmignore
文件
发布时,只有编译后的 lib
目录、package.json、README.md才须要被发布。因此经过配置.npmignore
文件忽略不须要提交的目录和文件。
# 忽略目录 examples/ packages/ public/ # 忽略指定文件 vue.config.js babel.config.js *.map # 本地文件 .env.local .env.*.local # 日志文件 npm-debug.log* yarn-debug.log* yarn-error.log* # 编辑器缓存文件 .idea .vscode *.suo *.ntvs* *.njsproj *.sln *.sw*
发布到 npm
首先须要在 npm 官网上注册一个帐号,经过 npm adduser
命令建立一个帐户,或者在 npm 官网注册
注册完成后在本地命令行中登陆:
npm login
执行发布命令,发布到 npm
npm publish
- npm 淘宝镜像不支持 publish 命令,若是设置了淘宝镜像,publish 前需将镜像设置会 npm :
npm config set registry http://registry.npmjs.org
npm publish
时,本地cmd终端需经过管理员运行
### 5.使用组件库
安装发布的组件库:
npm i qw-ui
使用组件:
# 在 main.js 引入并注册 import qwui from 'qw-ui' Vue.use(qwui) # 在组件中使用 <template> <v-message message=" hello 333 :: 使用kui组件库"></v-message> </template> <script> export default { data () { return { } } } </script>
完!