cover_image

技术干货 | 网易云商组件体系建设

Raven 网易智企技术+
2022年09月15日 00:30
图片


图片

导读:对于一个业务团队而言,前端组件及相关的体系建设,对于团队的交付效率和技术沉淀有着重要的作用。

图片

文 | Raven

网易云商



图片

前言


组件的核心意义是「提效」,这里的提效是指研发提效,可有效减少冗余代码、避免重复工作,提高「交付效率」,让我们能够更好更快地进行项目协作和需求开发。一个完善、高效的组件体系可以激发前端同学组件开发的热情,有利于前端物料的积累。本文将介绍网易云商组件体系建设的整体思路和实现原理。



图片

组件体系建设


完善的组件体系需要包含以下考量:

  • 对于组件开发者:集成代码规范、单测、demo 调试的开发环境,开箱即用。

  • 对于组件使用者:提供完善的组件使用文档和示例代码。

  • 对于 QA 同学:能看到组件的变更记录、组件的依赖关系,便于测试回归。

  • 对于业务方:有地方能看到组件在各个业务线中的实际场景和案例。


抽象一下,组件体系需要解决 3 个问题:

  • 如何为开发者提供流畅的组件开发流程 ?

  • 如何保证组件质量和可维护性 ?

  • 组件使用者如何了解已有哪些组件及其使用场景 ?


图片


为了解决这些问题,网易云商的组件体系的整体架构分为 3 部分,覆盖了组件开发、发布、使用 3 个阶段。

  • 首先是组件模板。集成了组件打包、代码规范、单元测试、demo 调试等。

  • 其次是命令行工具(wain cli)。为组件初始化、发布、信息上报提供了一套本地服务。

  • 最后是组件平台。承载组件信息的展示。


 组件模板 


我们要开发一个组件,应该从何开始呢?什么样的工程结构是合理的?应该使用怎么的代码规范?应该打包出怎样的组件产物?这些内容都属于「组件模板」的范畴。


图片


对于组件模板,我们主要考虑两方面的能力:


首先,我们希望为开发者完善友好的开发环境,因此模板中集成支持 demo 调试,方便开发者边开发边调试,具体来说:

  • webpack-dev-server 启动本地服务,支持 HMR。

  • webpack.config.js 中预置了 url-loader、less-loader、postcss-loader 等 rules,覆盖大部分调试场景。


其次,我们集成了组件打包能力,并支持 3 种模式:

  • 采用 Bundless 模式输出  esmodule、commonjs 产物,对源码处理如下:

    TypeScript 模块会被编译为 JavaScript 模块,并且输出对应的 .d.ts 类型文件。

    JavaScript 模块作兼容性处理。

    其他模块会被直接拷贝输出,不做编译。

  • 使用 Bundle 模式打包 umd 产物。


因有些工程希望使 esmodule 模式,有些希望开箱即用,即可以使用 commonjs 模式,还有一些老工程,需要使用 umd 的模式。


最后,为保证组件质量和可维护性,我们在组件模板中集成了 eslint、stylelint、commitlint 以及单测,并在 package.json 中配置 husky,以便在提交代码时,校验 eslint、stylelint、commitlint 是否合规。


// package.json"husky": {    "hooks": {      "commit-msg": "npm run beforecommit"    }}"scripts": {    // ...    "beforecommit": "npm run stylelint && npm run lint && commitlint -E HUSKY_GIT_PARAMS"    //...}


需要强调的是,组件模板的统一是很有必要的,一致的目录结构和代码风格,为后续维护提供了保证。


 wain cli 


有了组件模板,那么现在要开发一个组件,我们应该从何开始呢?


从 git 上 clone 组件模板,然后填写在 package.json 中填写组件信息,如 name 、author 等信息,很明显这太繁琐了,并且大家去填写 package.json 中组件的基本信息,可能会出现信息不全、格式错误等情况,这会影响后续组件平台中组件的展示。所以我们可以将这个流程变得智能一些。


图片


整理流程参见上图,具体环节如下:

我们提供了组件 cli 工具组件开发者使用 init 命令,根据提示填写组件基本信息,即可完成组件工程的初始化,并开始组件的开发。


图片


其中,我们使用:

  • commander[1](完整的 node.js 命令行解决方案))获取用户输入。

  • inquirer.js[2] 提供友好、清晰的终端交互。

  • chalk[3] 彩色输出重要信息。

  • gitlab-download[4] 拉取模版。

  • metalsmith、Handlebars[5] 处理模版编译逻辑。


图片


组件开发完成后,要进行组件发版,之前提到过,我们在组件模板中集成了规范、单测,所以在发版时,设置了卡点,具体的做法是:

  • 组件发版会触发 prepublishonly 的钩子,我们这这个钩子中执行的 cli 工具的 prepublish 命令,校验 lint 规范、单测覆盖率。

  • 另一方面组件发版,意味着功能的更新或者问题的修复等,所以组件发版时,cli 自动生成的 changelog(使用 conventional-changelog[6] 生成)和 gittag,方便后续回溯。


到目前为止,我们有了组件模板和 cli 工具,就可以较为轻松地完成组件开发。

组件开发完成后,我们需要考虑组件信息的展示,前面的架构图中,提到过组件平台会承载组件信息,那么组件信息的来源是哪里呢?这就要提到 cli 的另一部分能力,组件信息上报:

组件发布成功后,会触发 postpublish 钩子,我们在这个钩子中执行了 cli 工具的 afterpublish 命令,构建组件 demo、 package.json 中获取组件基本信息、然后将组件基本信息、readme、changelog 等信息上报。


总结一下,cli 工具主要承担了两部分功能:

  • 组件初始化、组件发版。

  • 组件信息上报、为组件信息展示提供数据支撑。


 组件平台 


图片


通过之前的流程,我们已经可以覆盖从组件初始化到发布的全部流程。


那么问题来了,对于其他发布的组件,我们可以去哪里找,如何高效率地获取我们需要的组件呢?


这里显然需要一个组件平台,对应这里的「消费和使用」阶段,组件平台集成了组件 readme、组件 demo、依赖情况等组件相关信息。到此为止,我们建立了一个完整的组件体系。


 整体工作流 


图片


组件体系的整体工作流

  • wain init 作为组件初始化入口,优化的命令行交互体验提示用户输入组件相关信息,生成组件工程。

  • 组件开发完成后进行发版,通过 prepublishOnly 钩子指定 eslint、stylelint、commitlint 等组件规范性校验。

  • 组件发版成功后,会触发 postpublish 钩子,在这个钩子中,我们触发公共服务。

  • 公共服务会 clone 工程,并执行工程中的 wain afterpublish 命令,进行 demo 构建、将组件信息上报给组件平台。

  • 此外,我们使用 sourcegraph 定时进行依赖检测。



图片

总结


我们通过工程化的方式,实现了整套网易云商组件体系,相比之前的组件开发方式,更加规范化,同时良好的可扩展性和可维护性,目前在网易云商前端落地使用。当然基于目前的能力,还可以拓展组件创建服务化、组件标准化等进阶功能。欢迎大家一起讨论。



 参考资料 


[1] 

https://github.com/tj/commander.js/blob/master/Readme_zh-CN.md?from=from_parent_mindnote

[2] 

https://www.jianshu.com/p/0409cdf0e396?from=from_parent_mindnote

[3]

https://www.npmjs.com/package/chalk/v/2.4.2?from=from_parent_mindnote

[4]

https://www.npmjs.com/package/gitlab-download?from=from_parent_mindnote

[5]

https://www.npmjs.com/package/metalsmith?from=from_parent_mindnote

https://www.handlebarsjs.cn/guide/?from=from_parent_mindnote#%E4%BB%80%E4%B9%88%E6%98%AF-handlebars

[6] 

https://www.npmjs.com/package/conventional-changelog


图片
图片


图片
继续滑动看下一个
网易智企技术+
向上滑动看下一个