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

「17」如何开发一个基于 Vue 的 ui 组件库(一) #20

Open
BuptStEve opened this issue Jan 7, 2019 · 0 comments
Open

「17」如何开发一个基于 Vue 的 ui 组件库(一) #20

BuptStEve opened this issue Jan 7, 2019 · 0 comments
Labels

Comments

@BuptStEve
Copy link
Owner

BuptStEve commented Jan 7, 2019

开发模式

预览 demo

在开发一个 ui 组件库时,肯定需要一边预览 demo,一边修改代码。

常见的解决方案是像开发一般项目一样使用 webpack-dev-server 预览组件,比如通过 vue-cli 初始化项目,或者自己配置脚本。

文艺一点儿地可能会用到 parcel 来简化 demo 的开发配置(比如 muse-ui)。

展示文档

作为一个 ui 组件库,也肯定要有自己的组件展示文档。

一般业界常见方案是自己开发展示文档...

但这样会带来一个组件库和文档如何同步的问题。

为何不用 vuepress?

由于 vuepress 支持在 markdown 中插入组件,所以我们其实可以很自然地边写文档边开发组件。

从开发步骤上来说,甚至可以先写文档说明,再具体地编写代码实现组件功能。这样一来文档即是预览 demo,与组件开发可以同步更新。

p.s. React 的组件文档可以试试这俩库:

类型声明

在开发和使用过程中如果对于一些对象、方法的参数能够智能提示,岂不美哉?

如何实现呢?

其实就是在相应文件夹中添加组件相关的类型声明(*.d.ts),并通过 src/index.d.ts 导出。

{
    "typings": "src/index.d.ts",
}

一开始将声明文件都放在 types/ 文件夹下,但在实践中觉得还是放在当前文件夹下比较好。一方面有利于维护,另一方面是读取源码时也有类型提示。

如何打包

打包工具

和打包库一样,选了 rollup。

单文件组件

在开发中用不用 *.vue 这样的单文件组件来开发呢?

  • muse-ui 完全不写 <template> 只使用 render 函数。
  • iviewelementvant 使用 .vue 文件,但样式单独写。
  • ant-design-vue 使用 .jsx 文件,样式也单独写。
  • vux 使用带 <style>.vue 文件,但在使用时必须用 vux-loader
  • cube-ui 使用带 <style>.vue 文件,但有一些配置

讲道理,完全不写 <template> 有点儿麻烦,所以添加了 rollup-plugin-vue 插件用于打包 .vue 文件。

但碰到一个问题:如何打包 <style> 中的样式?

  • 首先尝试不写 <style>,直接在 js 里 import scss 文件。没问题,但是写组件时不直观,同一组件的代码也分散在了两个地方
  • 接着尝试配置 rollup-plugin-vue,碰到一个 source-map 报错的问题。我提了个 issue

加载方式

区分场景

为了区分不同的场景使用不同的 js,所以一共打包了三份 js(commonJses moduleumd),以及一份压缩后的 css(dist/tua-ui.css)。

{
    "main": "dist/TuaUI.cjs.js",
    "module": "dist/TuaUI.es.js",
}

完整加载

大部分 ui 库都支持完整加载,和把大象装冰箱一样简单(但 vux 只支持按需加载):

  1. 引入 js
  2. 引入 css
  3. 安装插件
import TuaUI from '@tencent/tua-ui'
import '@tencent/tua-ui/dist/tua-ui.css'

Vue.use(TuaUI)

因缺思厅的是 cube-ui 把基础样式也写成 Vue 插件,导致按需引入的时候还要单独引入 Style,emmmmmmmmm...

import {
  /* eslint-disable no-unused-vars */
  Style, // <-- 不写这行按需引入时就没基础样式
  Button
} from 'cube-ui'

按需加载

ui 库若是只能完整加载,显然会打包多余代码。

所以各种库一般都支持按需加载组件,大概分以下几种。

tree-shaking

webpack 其实在打包的时候是支持 tree-shaking 的,那么我们能不能直接引用源码实现按需加载呢?

注意源码必须满足 es 模块规范(import、export)。

import { TuaToast } from '@tencent/tua-ui/src/'

Vue.use(TuaToast)

尝试打包,发现 tree-shaking 并没有起作用,还是打包了所有代码。

sideEffects

其实问题出在没有在 ui 库的 package.json 中声明 sideEffects 属性。

在一个纯粹的 ESM 模块世界中,识别出哪些文件有副作用很简单。然而,我们的项目无法达到这种纯度,所以,此时有必要向 webpack 的 compiler 提供提示哪些代码是“纯粹部分”。 —— 《webpack 文档》

注意:样式部分是有副作用的!即不应该被 tree-shaking

若是直接声明 sideEffectsfalse,那么打包时将不包括样式!所以应该像下面这样配置:

{
    "sideEffects": [ "*.sass", "*.scss", "*.css" ],
}

vuepress 组件样式

用 vuepress 写文档的时候,一般会在 docs/.vuepress/components/ 下写一些全局组件。

开发时没啥问题,但是发现一个坑:打包文档时发现组件里的样式 <style> 全丢了。

猜一猜原因是什么?

这口锅就出在上一节的 sideEffects,详情看这个 issue。解决方案就是在 sideEffects 里加一条 "*.vue" 即可。

测试数据

下面咱们打包一下安装了 ui 库的项目,看看按需加载的效果怎么样。

  • Origin
    • dist/js/chunk-vendors.71ea9e72.js ----- 114.04 kb
  • TuaToast
    • dist/js/chunk-vendors.beb8cff5.js ----- 115.03 kb
    • dist/css/chunk-vendors.97c93b2d.css ----- 0.79 kb
  • TuaIcon
    • dist/js/chunk-vendors.25d8bdbd.js ----- 115.00 kb
    • dist/css/chunk-vendors.eab6517c.css ----- 6.46 kb
  • TuaUI
    • dist/js/chunk-vendors.6e0e6390.js ----- 117.39 kb
    • dist/css/chunk-vendors.7388ba27.css ----- 8.04 kb

总结一下就是:

  • 原始项目的 js 打包出来为 114.o4kb
  • 只添加 TuaToast 后 js 增加了 0.99kb,css 增加了 0.79kb
  • 只添加 TuaIcon 后 js 增加了 0.96kb,css 增加了 6.46kb
  • 添加完整 TuaUI 后 js 增加了 3.35kb,css 增加了 8.04kb

可以看出按需加载还是有效果的~

以上 to be continued...

参考资料

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