资讯专栏INFORMATION COLUMN

【手牵手】搭建前端组件库(一)

waltr / 1559人阅读

摘要:手牵手搭建前端组件库本文梳理如何搭建和构建前端组件库了解几个问题为何需要组件化大部分项目起源都是源于业务方的各种各样的奇葩需求。作者是否私有,需要修改为才能发布到开源协议参考配置添加文件发布时,只有编译后的目录才需要被发布。

手牵手搭建前端组件库

本文梳理如何搭建和构建前端组件库.

了解几个问题

为何需要组件化?

大部分项目起源都是源于业务方的各种各样的奇葩需求。随着公司的业务发展,公司内部开始衍生出很多的B2C系统、后台系统,前端部门也疲于应对越来越多同质化的项目,这些项目在很多基础模块层、源代码存在不小的相似,甚至存在相似的业务模块。

笔者曾经所在的一个电商团队,前端成员基本每个人多做过登录注册、购物车、支付、微信登录...... 大量重复的业务代码。由于组内技术没有强制规范

本质上相同的东西,重复的去code就显得浪费.

分析这些问题发现:
日渐增多的业务场景需求

前端资源有限,无法支持所有项目的快速迭代

公司内部诸多产品业务混乱、体验不统一

于是开发底层的工具去服务不同业务就很有必要:
设计一套公司内部的基础组件库支撑各个前端项目,提升项目和业务的可用性和一致性。

一个前端团队拥有大量的业务场景和业务代码,相似的页面和代码层出不穷,如何管理和抽象这些相似的代码和模块,绝大多数团队会遇到这样的问题。 不断的拷代码? 修改代码?还是抽象成组件?显然后者更高效。所以在多项目存在高度的可控、底层依赖的情况下,前端实现组件库是最好的选择。

组件化,又或者组件抽离的目的是为了功能共享方便维护,其能够带来的好处是少写代码,统一管理、统一维护。一套基础组件代码千锤百炼精而又精,从而起到快速支撑业务迭代,提升开发效率的目的。

业务型组件库

前端组件库百花齐放,antd、element ui这些基础组件库已经很强大,使用于各种业务场景。但是这些基础组件的粒度是基于单个交互,而在交互产品之间隔着各种各样的模块和业务场景,产品的汇聚源于各种基础组件在业务逻辑的沾粘下集成为一个个项目,一个团队或多或少会有项目或模块存在功能、交互流程的重复、本质上的同质化。

所以antd、element ui 这类组件库是基于单个非连续性的交互组件,一个组件代表着一次人机无副作用的操作与响应,其不思考实体、用户、终端的状态,最小化的暴露和响应组件内部状态。对于连续性的交互通常来说与特点的业务场景有关,存在诸多的外部依赖,目前都是在各个业务模块由用户(coder)自行编写。

有没有一种方法解决连续性交互流程的共用问题?

解决的办法是组件封装包含业务场景的连续性交互流程,利用组件化将内部依赖通过接口映射到外部。

前端架构部门为业务部门提供业务型组件库能够有效提高开发效率.

组件库设计思路

组件是对一些具有相同业务场景和交互模式、交互流程代码的抽象,组件库首先应该保证各个组件的视觉风格和交互规范保持一致。组件库的 props 定义需要具备足够的可扩展性,对外提供组件内部的控制权,使组件内部完全受控。支持通过 children 自定义内部结构,预定义组件交互状态。保持组件具有统一的输入和输出,完整的API.

组件库的开发我们需要考虑:

组件设计思路、需要解决的场景

组件代码规范

组件测试

组件维护,包括迭代、issue、文档、发布机制

一个完整强大的组件库需要多方面努力,回归正题.

使用到的基础技术

vue cil 3

npm

webpack

rollup(v1.2.2)

Demo

下面就手把手搭建一个前端偏业务性的组件库。

组件库包括:

message 组件: 一个封装用于呈现后台通过 websocket 推送到前台页面的实时消息模块;

pay 组件: 一个封装用于实现商品支付的模块

share 组件: 一个封装用于实现商品、文章、视频在各社交平台分享的模块

只抛出一个栗子,组件内部实现略~

这里注意组件抽取的粒度,组件的抽离以一个完整的连续性交互为目地。

组件依赖数据、交互事件、控制权的暴露需要考虑全面,不同的上层业务部门都有自己对组件可配置的不同渴望。需要权衡,不能把配置化给捣鼓的永无止境到很难堪的局面。笔者曾经就参与一个项目的组件化,组件抽离的面目全非,各种依赖、环境、状态的配置,导致最后只有组件编写人员在看文档加回忆的情况下才能搞清楚其来龙去脉.

从简单的开始~

1、初始化组件库目录

创建一个空项目

// 新建一个项目
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
│   

目录结构可以更具需要调整.

2、修改 vue.config.js 配置

vue cli3 提供一个可选的 vue.config.js 配置文件。这个文件存在则他会被自动加载,所有的对项目和webpack的配置,都在这个文件中。

修改 vue.config.js 配置的目的主要是:

使 Demo 可访问,实现对 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 目录的编译处理

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的访问.

3、编写 packages 组件库

创建一个 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



需要注意的是,组件 mesage 必须声明 name 属性,这个 name 就是组件的标签,如:

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
}

到此,构建组件库的环境准好好了

### 4、发布组件库到 npm

packages 目录的编译打包

package.jsonscripts 字段中新增一下命令:

"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

  libkui.umd.min.js    8.08 KiB                   4.55 KiB
  libkui.umd.js        17.78 KiB                  7.31 KiB
  libkui.common.js     17.41 KiB                  7.19 KiB
  libkui.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 才能发布到 npm

license: 开源协议

参考配置:

{
  "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)

# 在组件中使用

完!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102145.html

相关文章

  • 搭建前端组件

    摘要:手牵手搭建前端组件库本文梳理如何搭建和构建前端组件库了解几个问题为何需要组件化大部分项目起源都是源于业务方的各种各样的奇葩需求。作者是否私有,需要修改为才能发布到开源协议参考配置添加文件发布时,只有编译后的目录才需要被发布。 手牵手搭建前端组件库 本文梳理如何搭建和构建前端组件库. showImg(https://segmentfault.com/img/bVboZDt?w=1200&...

    forrest23 评论0 收藏0
  • SegmentFault 技术周刊 Vol.35 - WebGL:打开网页看大片

    摘要:在文末,我会附上一个可加载的模型方便学习中文艺术字渲染用原生可以很容易地绘制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以说是 HTML5 技术生态链中最为令人振奋的标准之一,它把 Web 带入了 3D 的时代。 初识 WebGL 先通过几个使用 Web...

    objc94 评论0 收藏0
  • GitHub 值得收藏的前端项目[每月更新...]

    摘要:也是一款优秀的响应式框架站点所使用的一套框架为微信服务量身设计的一套框架一组很小的,响应式的组件,你可以在网页的项目上到处使用一个可定制的文件,使浏览器呈现的所有元素,更一致和符合现代标准。 GitHub 值得收藏的前端项目 整理与收集的一些比较优秀github项目,方便自己阅读,顺便分享出来,大家一起学习,本篇文章会持续更新,版权归原作者所有。欢迎github star与fork 预...

    maxmin 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<