本文来自尚妆前端团队南洋

发表于尚妆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)相关推荐

  1. 热门的前端UI组件库

    移动端 移动端组件库名称及简述 官网链接 Vant,轻量.可靠的移动端 Vue 组件库 Vant 移动端组件库 Mint UI,基于 Vue.js 的移动端组件库 MintUI 移动端组件库 Vant ...

  2. 16款优秀的Vue UI组件库推荐

    16款优秀的Vue UI组件库推荐 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可. 在公司的Web前端项目开发中,多个项目采用 ...

  3. 17款优秀的Vue UI组件库汇总

    17款优秀的Vue UI组件库推荐 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可. 在公司的Web前端项目开发中,多个项目采用 ...

  4. Vue UI组件库总结推荐

    基于Vue的Quasar Framework 介绍 这个框架UI组件很全面,准备下次使用这个框架了 基于Vue的Quasar Framework 中文网 http://www.quasarchs.co ...

  5. 优秀的Vue UI组件库

    Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可.在公司的Web前端项目开发中,多个项目采用基于Vue的UI组件框架开发,并投入正 ...

  6. OnsenUI - 专为混合开发/手机 web 应用打造的开源移动端 UI 组件库

    具有原生应用外观的组件库,性能表现也非常不错,适合用来开发 App,值得关注和学习使用. 关于 Onsen UI Onsen UI 是一套专为移动应用设计的丰富的 UI 组件库,使用前端开发者熟悉的j ...

  7. iview图表_Vue高效UI组件库—iView开发实践

    前段时间在微软参加活动,分享了 TalkingData 开源的基于 Vue.js 的高效 UI 组件库 iView 的一些开发经验,现整理成文,和大家探讨. 关于 iView 开发历程和命名 Talk ...

  8. 创建, 发布自己的 Vue UI 组件库

    创建, 发布自己的 Vue UI 组件库 前言 在使用 Vue 进行日常开发时, 我们经常会用到一些开源的 UI 库, 如: Element-UI_, _Vuetify 等. 只需一行命令, 即可方便 ...

  9. vue相关UI组件库

    vue相关UI组件库 以下是关于vue相关比较热门和实用的组件库,学习vue的童鞋至少要会下面1到2个,然后基本就都会用了,用法差异不大. element-ui (适用与pc端和后台系统界面开发) h ...

  10. 与element-UI相媲美的前端UI组件库ArcoDesign 开源啦

    ArcoDesign 是由字节跳动 GIP UED 团队和架构前端团队联合推出的企业级设计系统.在打磨了近 3 年之后,通过字节内部大量业务沉淀和验证,我们开源了 ArcoDesign 设计系统.旨在 ...

最新文章

  1. 无闪烁刷新页面 php,AJAX_Ajax实现无闪烁定时刷新页面实例代码,在Web开发中我们经常需要实现 - phpStudy...
  2. 中移动飞信2010Beta1.0体验版
  3. 用SMS2003部署Windows XP SP3:SMS2003系列之十
  4. java实现短信验证码发送(架子是springboot 服务平台选择腾讯云短信服务)
  5. node-glob学习
  6. JDK的bin目录下所有程序的使用介绍
  7. Android应用开发——系统自带样式Android:theme
  8. 【DFS + backtracking】LeetCode 216. Combination Sum III
  9. CDH5 Hadoop如何支持读写OSS
  10. 冲刺一阶段———个人总结08
  11. 关于电商行业网络安全解决方案
  12. java 向量 内积_向量内积外积
  13. 22、了解网卡和IP地址
  14. 有关winRAR32相关问题
  15. 短期不看好 KotLin 原因
  16. win7计算机还原点建立,win7系统每次启动自动创建还原点的处理技巧
  17. 迅为stm32mp157开发板资料手册+实战教程+视频教程
  18. onenote 思维导图_印象笔记、OneNote、熊掌记 哪个笔记App更适合文字工作者?
  19. MIPI RFFE扫盲(1)
  20. 阿里云ECS通用型g7云服务器支持vTPM第三代神龙架构性能评测

热门文章

  1. 在Ubuntu5.1中安装NVIDIA TNT2 M64老式显卡驱动程序..
  2. WAP技术与应用(转)
  3. 又是苦海泛起爱恨,在世间难逃命运的新一周
  4. pp影视播放器官方版
  5. php内部网,php – WordPress内部网址重写是如何工作的?
  6. 性格木讷面试时如何脱颖而出?
  7. 基于STM32f407的TSL2561模块的使用
  8. Excel筛选后无法复制粘贴成数值解决办法
  9. Java实现四则运算
  10. 电脑只能上qq不能打开网页