前端下半场:构建跨框架的 UI 库

2018 年 8 月 13 日 phodal

如果用一个 UI 库不能解决问题,那就用两个 UI 库;如果用一个 UI 框架不能解决问题,那就用两个框架。

跨框架的 UI 库,即前端 UI 库可以不经任何修改,直接能运行在 React、Angular、Vue 等框架上。

在开源电子书《微前端的那些事儿》 中,我们讨论到了 Web Components 技术,一种新的 Web 前端容器化技术。在电子书里,我们主要介绍的是:如何使用 Web Components 来构建微服务。而在这篇文章里,我们讨论的是 Web 组件的下半场:跨框架的 UI 库

背景

最近的一段时间里,我花费大量地时间在练习微前端技术。在我的新 Markdown 编辑器 Phodit 中,我有意无意地去拆分出一个个的小组件,每个小的组件使用不同的技术构建,React、Angular、Stencil.js、原生 JavaScript 等等。如:

  • Stencil.js + Web Components 来放置 Terminal 的关闭窗口

  • React.js 制作了左侧的树形文件树

  • Angular 6 完成了重命名文件的交互

  • sweetalert 用来做 Dialog 提醒

  • ……

编辑器仍然在开发中,这并不是最后的所有技术。引入这么多框架的 “hello, world”,然后构建一个个简单的组件,大概、可能、也许是为了 炫技 练习。虽是这么说,事实是 SimpleMDE 已经封装了 CodeMirror 的一系列 API,为了能快速用上自己的编辑器,我决定地接基于SimpleMDE 来修改。而 SimpleMDE 并不能直接用在 Angular 等前端框架上,这也意味着,因为这个 Editor 的存在,我不得不将页面撕裂成几部分:左侧菜单、Terminal 窗口栏、辅助栏、状态栏等等的几部分。

换句话来说,就是这是一个组件化架构最好的应用场景。

过去我们谈论前端的组件化架构时,通常指的是框架限制的组件化架构。而当我们拥有基础的 UI 组件库时,我们的架构则是基于 UI 组件库的组件化架构,两者间的不同在于共性的第一次提取。而当我们在业务组件的基础上,进行对一些通用业务组件的封装时,我们的架构则基于基于 UI 组件库和业务组件的组件化架构

组件金字塔

可不论是哪种方式,最后我们都限定于框架限制——我们将系统绑定在框架上。而对于团队的技术决策者来说,绑定上框架的实现是一种冒险的作法。未来,这些都是风险,那么有没有可能将底层的 UI 组件库、 复合组件和业务组件库通用呢?

铺垫:React 中引入 Angular 组件

为了在我的编辑器中使用 Angular,我用 Angular 编写了一个重命名功能。而为了使用它,我得再次使用一次 customEvent,而在这个微前端架构的系统中,其事件通讯机制已经相当的复杂。在这部分的代码进一步恶化之前,我得尝试有没有别的方式。于是,我想到了之前在其它组件中使用的 Web Components 技术,而 Angular 6 正好可以支持。

HTML 中引入 Web Components

我所需要做的事情也相当的简单,只需要将我的组件注册为一个 customElements,稍微改一下 app.module.ts 文件。在这种情况之下,我们就可以构建出独立于框架的组件。

如下是原始的 module 文件:

  
  
    
  1. @NgModule({

  2.  declarations: [AppComponent],

  3.  imports: [BrowserModule],

  4.  bootstrap: [AppComponent]

  5. })

  6. export class AppModule { }

如下则是新的 module 文件:

  
  
    
  1. @NgModule({

  2.  declarations: [InteractBar],

  3.  imports: [BrowserModule],

  4.  entryComponents: [InteractBar]

  5. })

  6. export class AppModule {

  7.  constructor(private injector: Injector) {

  8.  const interactBar = createCustomElement(InteractBar, {injector});

  9.  customElements.define('interact-bar', interactBar);

  10.  }

  11. }

然后,只需要就可以在 HTML 中传递参数: <interact-bar filename="phodal.md"></interact-bar>,或者监听对应的 @Output 事件

  
  
    
  1. const bar = document.querySelector('interact-bar');

  2. bar.addEventListener('action', (event: any) => {

  3.  ...

  4. })

事实证明,使用 Angular 构建的 Web Components 组件是可以用的。于是,我便想,不如在 React 中引入 Angular 组件吧。

React 中引入 Angular 组件

于是,便使用 create-react-app 创建了一个 DEMO,然后引入组件:

  
  
    
  1. <div className="App">

  2.  <header className="App-header">

  3.  <img src={logo} className="App-logo" alt="logo" />

  4.  <h1 className="App-title">Welcome to React</h1>

  5.  </header>

  6.  <p className="App-intro">

  7.  To get started, edit <code>src/App.js</code> and save to reload.

  8.  <interact-bar filename="phodal.com" onAction={this.action}></interact-bar>

  9.  </p>

  10. </div>

嗯,it works。至少 filename 参数可以成功地传递到 Angular 代码中,而 action 在当前似乎还不行。但是毫无疑问,它在未来是可用的。

Demo 见:https://phodal.github.io/wc-angular-demo/

Repo 见:https://github.com/phodal/wc-angular-demo

这个时候,我遇到了一个问题,我使用 Angular 构建的这个组件,大概是有 257kb。这个大小的组件,但是有点恐怖。

Web Components 框架构建组件

在那些微前端相关的文章中,我们指出类似于 Stencil 的形式,将组件直接构建成 Web Components 形式的组件,随后在对应的诸如,如 React 或者 Angular 中直接引用。

如下是一个使用 Stencil 写的 Web Components 的例子:

  
  
    
  1. @Component({

  2.  tag: 'phodit-header',

  3.  styleUrl: 'phodit-header.css'

  4. })

  5. export class PhoditHeader {

  6.  @State() showCloseHeader = false;

  7.  componentDidLoad() {...}

  8.  handleClick() {...}

  9.  render() {

  10.  if (this.showCloseHeader) {...}

  11.  return (<div></div>);

  12.  }

  13. }

使用它构建出来的组件,大概可以在 30kb 左右的大小。

不论是不是一个经量级的方案,但是它至少证明了组件复用的可行性。

跨平台 UI 库

在有了上面的技术基础之后,我们可以发现:我们可以构建跨 UI 框架的组件库。那么,它就可以解决我们在构建内部 UI 库时,面对不同技术框架,需要编写不同业务逻辑的问题。这个时候我们的 UI 架构,就会发生一系列的变化。原先我们需要为 React、Angular 和 Vue 等几个不同框架写几个不同的 UI 组件库,但是现在,我们只需要写一套 UI 组件库即可:

UI 架构变化

自此,我们的 UI 库架构变得更加简单、轻量。

那么问题来了,为什么还没有这样的 UI 库?原因主要有两个:

技术不够成熟。主要原因是,现有的前端框架对于 Web Components 的支持并不是那么好,诸如我尝试使用 React 来使用时,遇到一些问题。与此同时,前端框架都能支持构建出这样的组件,那么也需要浏览器对于 Web Components 的支持。我们需要诸如 custom-elements-es5-adapter.js 等的支持,而像 Polymer 这样的 Web Components 框架也需要 IE 11+ 的支持。

Web Components 技术重写组件。是的,我们需要将之前使用 TypeScript 或者 JSX 或者 .vue 编写的组件,使用更轻量级框架来构建。UI 框架中的很多要素,是我们在编写组件的时候不需要的——我们只在需要的时候,引入我们所需要的组件即可。

而现在,正是构建这种跨平台 UI 库的最好时机。

打开你的 GitHub,开始造一波 star 吧


登录查看更多
1

相关内容

【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
FPGA加速系统开发工具设计:综述与实践
专知会员服务
65+阅读 · 2020年6月24日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【新书】Java企业微服务,Enterprise Java Microservices,272页pdf
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
【电子书】Flutter实战305页PDF免费下载
专知会员服务
22+阅读 · 2019年11月7日
前端微服务在字节跳动的落地之路
前端之巅
41+阅读 · 2019年9月19日
微信小程序支持webP的WebAssembly方案
前端之巅
19+阅读 · 2019年8月14日
美团:基于跨平台框架Flutter的动态化平台建设
前端之巅
14+阅读 · 2019年6月17日
专访阿里亚顿:Serverless与BFF与前端
前端之巅
45+阅读 · 2019年5月8日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
使用 C# 和 Blazor 进行全栈开发
DotNet
6+阅读 · 2019年4月15日
React Native 分包哪家强?看这文就够了!
程序人生
13+阅读 · 2019年1月16日
开源巨献:Google最热门60款开源项目
程序猿
5+阅读 · 2017年7月12日
Arxiv
6+阅读 · 2020年4月14日
Star-Transformer
Arxiv
5+阅读 · 2019年2月28日
Arxiv
8+阅读 · 2018年5月21日
Arxiv
6+阅读 · 2018年5月18日
Arxiv
6+阅读 · 2018年1月11日
VIP会员
相关资讯
前端微服务在字节跳动的落地之路
前端之巅
41+阅读 · 2019年9月19日
微信小程序支持webP的WebAssembly方案
前端之巅
19+阅读 · 2019年8月14日
美团:基于跨平台框架Flutter的动态化平台建设
前端之巅
14+阅读 · 2019年6月17日
专访阿里亚顿:Serverless与BFF与前端
前端之巅
45+阅读 · 2019年5月8日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
使用 C# 和 Blazor 进行全栈开发
DotNet
6+阅读 · 2019年4月15日
React Native 分包哪家强?看这文就够了!
程序人生
13+阅读 · 2019年1月16日
开源巨献:Google最热门60款开源项目
程序猿
5+阅读 · 2017年7月12日
Top
微信扫码咨询专知VIP会员