「前端」尚妆 UI 组件库工程实践(weex vue)
本文来自尚妆前端团队南洋
发表于尚妆github博客,欢迎订阅!
前言
尚妆大前端团队使用 weex 进行三端统一开发有一段时间了,截止本文发表「达人店」APP大部分页面都已经用 weex 进行了重构,在此期间也积累了一些基础组件和业务组件。
之前维护组件的方式是在达人店项目的工程内维护一个 components 文件夹,随日常开发迭代,并行需求与开发人员的增多,这种维护方式也暴露出一些问题。
1、开发人员可以随意跟随需求开发修改 components 内的组件,破坏约定好的规范,或埋入 bug。
2、定义组件缺少规范,比如在某个需求开发中, A 开发人员觉得这个功能可以抽离成组件,就直接在 components 内定义并使用,但实际却是伪需求,用了一次就再也没有人使用,造成 components 组件库的部分冗余。
3、组件抽离过程无法协同使用,比如 A 开发同学切了个特性分支 feature/A
,并根据项目抽了个通用组件 ComponentA
,B 开发切了个特性分支 B,也想使用这个 ComponentA
组件,但此时两人在不同分支,代码并不能共享。
4、。。。
基于上述不便之处,我们尝试将 components 抽离出来,放到内部私有 npm 仓库中以 npm 包的形式去维护。
也就是我们将 spon-ui(内部组件库名称)
作为单独的一个项目去维护,加以约束形成组件库开发规范,能有效的解决上述问题。
此文就是此次抽离过程的一些实践,包含了组件的调试、文档调试、npm使用、组件 发布等内容。当然 weex 的语法同 vue,这些实践也同样适用于 vue。
1、组件库的调试
先看下 spon-ui
组件库项目的目录结构。
|- spon-ui
||-- build
||-- docs
||-- examples
||-- packages
|||--- weex-field
||||---- index.js
||||---- field.vue
||||---- example.vue
||||---- readme.md
||||---- package.json
||-- src
复制代码
- build 中存放一些脚本执行文件,用于工程的调试、发布。
- docs 中存放文档调试的脚本,生成一个文档调试服务器。
- examples 中存放组件调试的脚本,生成一个组件调试服务器。(不存放组件例子)
- packages 存放真实组件,以及组件的文档和例子。
- src 存放组件可以使用的公共方法。
组件的调试
examples 文件夹内就是组件调试的相关脚本,这个文件夹在组建开发过程中是不需要变动的,只是定义了调试服务器的一些逻辑。并不包含真实的组件例子。
而真实的例子存放在相应组件目录下,example.vue
中引入当前目录下的 vue 组件,调试时是针对 example.vue
进行调试,因为调试组件需要模拟使用组件的场景(改变传入值,用户交互等)。
当执行 npm run dev:components
时,开发同学会看到浏览器打开页面:
选择想要调试的组件,比如说 weex-dialog ,进入到 weex-dialog 的调试界面。
开发同学此时修改 packages 目录中的 weex-dialog 的组件内容,会实时看到修改内容,进行调试。
console 中输出二维码
另外我们开发的组件是基于 weex 的,意味着开发的组件需要支持三端(iOS android H5),所以在 console 中会打印当前组件js的二维码,用于 native 调试。
如何在console中输出二维码也是个小trick,首先利用js的二维码库将资源生成二维码图,然后利用console输出背景图的机制打印二维码。
console.log("%c", "padding:75px 80px 75px;line-height:160px;background:url(" + base64 + ") no-repeat;background-size:160px");
复制代码
整个调试页面是通过单页面的形式展现的,使用 vue-router
进行路由控制,weex 也支持 vue-router
,所以这个单页面在 native 中也能良好运行。
自动生成组件相关信息
在每次执行 npm run dev:components
命令时,会根据 packages 目录下的组件自动生成 nav-list.js
文件,这个索引文件用来定义 vue-router
的路由信息,以及调试主页的组件列表。这样做可以完全将调试过程抽离成黑盒,开发人员只需关注 packages
目录下的开发即可。
const routes = navList.map((item) => {const path = item.path;return {path,// 需要加vue后缀,不然webpack会将examples下的所有文件都require一下component: require('examples/' + item.exampleRequire + '.vue'),};
});
routes.push({path: '/',component: require('./app.vue'),
})
复制代码
// 组件列表也通过 nav-list.js 渲染
<spon-cell-group><spon-cellv-for="(page, jndex) in item.list":key="jndex":title="page.title":is-link="true"@click="changePage(page)"></spon-cell>
</spon-cell-group>
复制代码
webpack require 动态的资源
本文使用 webpack 3.x.x
上节提到的 require 动态的模块时,如果不表明文件类型,webpack会将该目录下所有资源都 require 一遍,造成的问题是如果目录下有某类型的文件,而又没有使用对应的loader,在编译过程就会报错。上节中如果不加 .vue
后缀, webpack会将 examples 目录下所有资源都require一遍。
所以在定义各路由的component时,需要加上 vue 后缀,查找vue文件。
component: require('examples/' + item.exampleRequire + '.vue'),};
复制代码
webpack的文档说明在 https://webpack.js.org/guides/dependency-management/#require-context
在 webpack 的官方文档里列出了动态 require 的原理,对于 require("./template/" + name + ".ejs");
含表达式的引用,webpack 解析此处的 require,得到两个信息:
1、 目录为 ./template
2、匹配规则为 /^.*\.ejs$/
然后 webpack 会根据这两个信息得到一个 context module,这个模块包含了 ./template
目录下所有以 .ejs
为后缀的模块。
{"./table.ejs": 42,"./table-row.ejs": 43,"./directory/folder.ejs": 44
}
复制代码
还有一个 require.context()
方法可以自定义动态引用的规则,文档中也有示例,官网给出了一个基于此的demo,引入一个目录中所有符合规则的模块。
function importAll (r) {r.keys().forEach(r);
}importAll(require.context('../components/', true, /\.js$/));
复制代码
文档的调试
组件开发的差不多了,就要编写相应的文档,方便同事小伙伴使用,执行 npm run dev:docs
会开启文档调试服务器,方便开发同学编写文档。
文档服务器的逻辑放在 docs
目录下,同样与组件代码解耦,左侧的组件信息动态取自 packages 目录下的组件信息,右侧的组件预览直接使用 examples
目录下的组件调试逻辑,中间的部分取自 组件中的 readme.md
文件。
整个文档应用也是基于 vue + vue-router
开发。
<div class="nav-bar-container"><page-nav></page-nav>
</div><div class="document-area-container markdown-body"><router-view></router-view>
</div><div class="mock-phone-container"><page-preview :component-name="componentName"></page-preview>
</div>
复制代码
<router-view>
就是对应的路由所展示的文档内容,相应的在定义路由信息时需要确定路由以及路由所对应的 readme.md
路径。
const routes = navList.map((item) => {const path = item.path;return {path,component: require('mds/' + item.mdRequire + '.md'),};
});const router = new VueRouter({routes,
});
复制代码
markdown 转换 vue
在引用组件时使用了 .md
后缀,这里是采用了 vue-markdown-loader
饿了么出品的loader。这个loader还是借助vue-loader,首先会将 md 的内容转换成 html ,然后再转换成 vue 所需要的单文件形式给vue-loader。
var renderVueTemplate = function(html, wrapper) {// 本文作者注// 传入的html是根据 markdown插件将md转换而来var $ = cheerio.load(html, {decodeEntities: false,lowerCaseAttributeNames: false,lowerCaseTags: false});...// 本文作者注// 将html转换成 vue-loader 所需的字符串形式result =`<template><${wrapper}>` +$.html() +`</${wrapper}></template>\n` +output.style +'\n' +output.script;return result;
};
复制代码
var result ='module.exports = require(' +loaderUtils.stringifyRequest(this,'!!vue-loader!' +markdownCompilerPath +'?raw!' +filePath +(this.resourceQuery || '')) +');';// 本文作者注// 将转换好的字符串传给 vue-loaderreturn result;
复制代码
2、基于 npm 脚本实现工程化
"scripts": {"bootstrap": "npm i","dev:components": "node build/bin/dev-entry.js","dev:docs": "node build/bin/docs-dev-entry.js","build:docs": "node build/bin/docs-build.js","pub:docs": "npm run bootstrap && npm run clean && node build/bin/release.js","pub:components": "node build/bin/prepublish.js && lerna publish --skip-npm --skip-git && node build/bin/publish.js","clean": "rm -rf docs/dist && rm -rf docs/deploy","add": "node build/bin/add.js"},
复制代码
本项目中将所有常用的命令都进行了抽离,开发同学使用的命令最后暴露出4个:
npm run dev:components 组件的调试
npm run dev:docs 文档的调试
npm run pub:docs 文档的发布
npm run pub:components 组件的发布
复制代码
推荐看阮一峰的博客 npm scripts 使用指南 ,将npm 脚本很细致的介绍了一遍。
自动生成脚手架
npm run add
会自动添加一个组件所需的脚手架信息,方便开发同学添加新组件。
这里推荐使用 json-templater/string
模块处理 string 模板的问题。
脚手架文件中的某些值会根据组件名的不同而不同,根据组件名自动生成对应的脚手架内容,更加方便开发。
npm link
组件在本地开发完成了,例子和文档都编写完毕,但不知在真实项目中使用会不会出现奇怪bug。
最原始的方法可以将组件复制到项目中的npm包中进行真实调试。
当然 npm 也提供了 方法专门解决这种问题。
1、首先在 spon-ui
组件库的根目录执行 npm link
2、回到项目目录,执行 npm link spon-ui
,两条命令就能将项目中原本引用的spon-ui 映射到本地的spon-ui
目录中去。
3、npm unlink
取消软链。
3、源码依赖
上节提到的npm 脚本并没有提到组件打包的流程,因为如果在组件这层就进行打包,会增加一些webpack的冗余代码,增加字节,而且这个组件库目前完全属于内部项目使用,打包环境在项目中就存在,没有必要提前进行打包。
所以发布出去的组件包就是packages下的所有组件,项目中所依赖的都是组件的源码,称为源码依赖。
要做到源码依赖,需要修改业务项目中(非本组件项目)的babel的配置。排除掉 spon-ui
组件
module: {rules: [{test: /\.js$/,exclude: /node_modules(?!\/.*(spon-ui).*)/,loader: 'babel-loader',options: {cacheDirectory: true,},},],},
复制代码
滴滴有篇webpack 应用编译优化之路有讲到源码依赖所带来的好处。
4、发布组件
我们使用了 lerna 来管理组件的发布,lerna 有两种发布方式,一种是一个项目的所有组件作为一个发布包,还有一种可以将一个项目中的多个组件分别发布。
我们使用了第一种,即所有组件统一成一个发布包。这种方式发挥不出 lerna 的威力,但是作为发布前的版本号管理还是不错的。未来如果要将各个组件单独发布,改一下配置就ok。
版本管理
测试版本的管理
在前文就提到过目前组件库的开发还是依赖于需求的迭代,小团队没有人专门开发组件,组件的开发会跟随需求的迭代而迭代。
那么在前期组件变更需求通过评审会后,就会跟随项目正式进入开发流程。项目开发会区分测试环境和预发全量环境,那么组件的版本号也需要区分测试环境和全量环境。
npm publish --tag
介绍一下 publish 的 tag,发布的 npm 包默认会有一个 latest
标签,每次执行 npm publish
都会自动将 tag 设置为 latest,也可以理解为稳定版,所以我们要做的是再添加一个 tag
npm publish --tag dev
这个命令代表添加一个名为 dev
的tag,并将此次发布的版本号贴上 dev
标签。
执行 npm dist-tag ls spon-ui
可以查看当前的标签所对应的版本号信息。
➜ spon-ui git:(master) npm dist-tag ls spon-ui
dev: 0.1.0-12
latest: 0.1.0
复制代码
在项目中安装spon-ui的时候,根据情况分别执行
npm i spon-ui@dev
npm i spon-ui@latest
复制代码
5、npm5 package-lock.json
组件发布完成了,就可以在项目中使用了,我们从npm3.x更新到了npm5,但是发现执行 npm i
时的现象跟网络上的科普文不太一致。
有提到不管怎么修改package.json文件,重复执行npm i,npm都会根据lock文件描述的版本信息进行下载。
也有提到重复npm i时,npm会不顾lock的信息,根据package.json中的包Semantic versioning 版本信息下载更新模块(lock貌似没啥用了)。
查阅资料得知,自npm 5.0版本发布以来,npm i的规则发生了三次变化。
1、npm 5.0.x 版本,不管package.json怎么变,npm i 时都会根据lock文件下载
https://github.com/npm/npm/issues/16866 这个 issue 控诉了这个问题,明明手动改了package.json,为啥不给我升级包!然后就导致了5.1.0的问题...
2、5.1.0版本后 npm install 会无视lock文件 去下载最新的npm
然后有人提了这个issue https://github.com/npm/npm/issues/17979 控诉这个问题,最后演变成5.4.2版本后的规则。
3、5.4.2版本后 https://github.com/npm/npm/issues/17979
大致意思是,如果改了package.json,且package.json和lock文件不同,那么执行npm i
时npm会根据package中的版本号以及语义含义去下载最新的包,并更新至lock。
如果两者是同一状态,那么执行npm i
都会根据lock下载,不会理会package实际包的版本是否有新。
总结
以上就是我们将UI组件从项目中迁移出来单独以npm包的形式去维护的实践过程,不完美还有待时间的考验,希望其中的一些内容能帮助到大家。
「前端」尚妆 UI 组件库工程实践(weex vue)相关推荐
- 热门的前端UI组件库
移动端 移动端组件库名称及简述 官网链接 Vant,轻量.可靠的移动端 Vue 组件库 Vant 移动端组件库 Mint UI,基于 Vue.js 的移动端组件库 MintUI 移动端组件库 Vant ...
- 16款优秀的Vue UI组件库推荐
16款优秀的Vue UI组件库推荐 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可. 在公司的Web前端项目开发中,多个项目采用 ...
- 17款优秀的Vue UI组件库汇总
17款优秀的Vue UI组件库推荐 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可. 在公司的Web前端项目开发中,多个项目采用 ...
- Vue UI组件库总结推荐
基于Vue的Quasar Framework 介绍 这个框架UI组件很全面,准备下次使用这个框架了 基于Vue的Quasar Framework 中文网 http://www.quasarchs.co ...
- 优秀的Vue UI组件库
Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可.在公司的Web前端项目开发中,多个项目采用基于Vue的UI组件框架开发,并投入正 ...
- OnsenUI - 专为混合开发/手机 web 应用打造的开源移动端 UI 组件库
具有原生应用外观的组件库,性能表现也非常不错,适合用来开发 App,值得关注和学习使用. 关于 Onsen UI Onsen UI 是一套专为移动应用设计的丰富的 UI 组件库,使用前端开发者熟悉的j ...
- iview图表_Vue高效UI组件库—iView开发实践
前段时间在微软参加活动,分享了 TalkingData 开源的基于 Vue.js 的高效 UI 组件库 iView 的一些开发经验,现整理成文,和大家探讨. 关于 iView 开发历程和命名 Talk ...
- 创建, 发布自己的 Vue UI 组件库
创建, 发布自己的 Vue UI 组件库 前言 在使用 Vue 进行日常开发时, 我们经常会用到一些开源的 UI 库, 如: Element-UI_, _Vuetify 等. 只需一行命令, 即可方便 ...
- vue相关UI组件库
vue相关UI组件库 以下是关于vue相关比较热门和实用的组件库,学习vue的童鞋至少要会下面1到2个,然后基本就都会用了,用法差异不大. element-ui (适用与pc端和后台系统界面开发) h ...
- 与element-UI相媲美的前端UI组件库ArcoDesign 开源啦
ArcoDesign 是由字节跳动 GIP UED 团队和架构前端团队联合推出的企业级设计系统.在打磨了近 3 年之后,通过字节内部大量业务沉淀和验证,我们开源了 ArcoDesign 设计系统.旨在 ...
最新文章
- 无闪烁刷新页面 php,AJAX_Ajax实现无闪烁定时刷新页面实例代码,在Web开发中我们经常需要实现 - phpStudy...
- 中移动飞信2010Beta1.0体验版
- 用SMS2003部署Windows XP SP3:SMS2003系列之十
- java实现短信验证码发送(架子是springboot 服务平台选择腾讯云短信服务)
- node-glob学习
- JDK的bin目录下所有程序的使用介绍
- Android应用开发——系统自带样式Android:theme
- 【DFS + backtracking】LeetCode 216. Combination Sum III
- CDH5 Hadoop如何支持读写OSS
- 冲刺一阶段———个人总结08
- 关于电商行业网络安全解决方案
- java 向量 内积_向量内积外积
- 22、了解网卡和IP地址
- 有关winRAR32相关问题
- 短期不看好 KotLin 原因
- win7计算机还原点建立,win7系统每次启动自动创建还原点的处理技巧
- 迅为stm32mp157开发板资料手册+实战教程+视频教程
- onenote 思维导图_印象笔记、OneNote、熊掌记 哪个笔记App更适合文字工作者?
- MIPI RFFE扫盲(1)
- 阿里云ECS通用型g7云服务器支持vTPM第三代神龙架构性能评测