Angular现在引入了WebComponents啦!哇!哇!哇!~@angular/elements的初印象~

标题是“甲壳虫来了啊!啊!啊!”的模仿作品。

什么是@angular/elements?

@angular/elements是一个用于将Angular组件转换为Web Components的软件包。PullRequest在9月29日被提交,10月28日通过了LGTM,并被移动到labs分支上。这仍然是一项处于实验状态的全新功能。

这可能有些借口,但是@angular/elements的方向仍然不确定,我自己的知识也远远不够。我已经在我理解的范围内总结了目前的情况,但是如果有任何指正或修正,请随时留下评论或编辑请求,谢谢。

Web Components的复习

Web Components 是一个促进在HTML/CSS/JavaScript中实现可重复使用组件的机制。

当使用Web Components时,无论是从哪个应用程序(不仅限于Angular,只要可以访问浏览器的窗口)都可以使用由Angular创建的自定义标签。当然,反过来也是可以的,例如在Vue中创建组件并注册为自定义标签后,在Angular中也可以使用它(但有一些条件)。此外,作为解决Angular独有情况的方案,还可以创建具有多个入口点的Angular应用程序。

为了实现这一点,@angular/elements会为Angular组件进行构建,以适应Custom Elements(WebComponents四天王之一)的接口,并可通过window.customElements进行注册。为什么可以在Angular之外使用呢?因为Custom Elements定义了外部接口规范。通过给定属性或接收事件,可以实现Angular与其他JavaScript应用程序的协同工作。在这种情况下,JavaScript应用程序指的是在script标签中编写的JavaScript函数。请注意,@angular/elements几乎指的就是Custom Elements。

只决定接口是不够的,还需要一个机制来隐藏主机的定制元素。主机的 CSS 和 JavaScript 对象可能会与自定义元素内部发生冲突或被覆盖,反过来,自定义元素的对象也可能对外部产生影响。为此,Shadow DOM (WebComponents 四大组件之一)提供了一个隐藏主机部分的 DOM 空间。

此外,通过ES模块(WebComponents四巨头之一)可以在浏览器中将模块化的内容导入。您也可以在没有改变当前环境的情况下,将Angular自定义标签与阿贝·广场的网站融合在一起。

Web Components是四个强大实体的其中一员。Template(Web Components的第四个实体)是一个在浏览器中加载但处于非激活状态(即不会被渲染)的HTML组件。

@angular/elements的两个背景

浏览器的实现状况得到了进一步改善。

首先的背景是Web Components的规范制定正在推进,浏览器的实现也开始完善。当前的浏览器支持情况如下,涉及到构成Web Components的四个主要元素。

目前,核心的自定义元素还包括黄色和红色行进,但可以确定支持正在Chrome和Safari这两个主要移动浏览器中进行。

自定义元素
https://caniuse.com/#feat=custom-elementsv1
影子 DOM
http://caniuse.com/#feat=shadowdomv1
ES 模块
http://caniuse.com/#feat=es6-module
模板
http://caniuse.com/#feat=template

Angular的用例覆盖已经达到了极限

作为第二个背景,我们要谈到 Angular 的发展问题。自从 Angular2 以后,我们一直努力推动采用 TypeScript 和 AoT 编译的强大单页应用(SPA)开发路线,与此同时,为了换取这种发展,我们弱化了开发者轻松创建 Web 组件、享受开放和协作的互联网、以及使用小工具的路线。

WordPress的下一代编辑器框架选择中,Angular早期便被排除在候选之外。此外,Angular自身的文档网站建设也成为一个问题。关于文档网站的背景信息,请参阅AdventCalender第1天的文章中的“第二个轴:动态应用程序支持”一节。如果你懂英语,我认为你也会对文章中提到的YouTube感兴趣。由于听力有限,我只是通过幻灯片阅读了相关内容。

在构建Angular文档网站时遇到的问题。

视频链接:

幻灯片资料链接:
https://onedrive.live.com/view.aspx?resid=635B97DC223BC5B2!136637&ithint=file%2Cpptx&app=PowerPoint&authkey=!AFgQoakql9CnkD0

为什么要使用@angular/elements?

两个方向

Web Components可以只使用HTML/CSS/JavaScript来创建。使用@angular/elements的原因是可以使用Angular包进行开发。

正如之前提到的,@angular/elements目前仍处于实验阶段。因此,功能尚未确定,使用案例也处于试探阶段。这一点可以从目前参与该项目的人中可以看出,有两个重要的方向。

目前,可观测到的两个方向如下。

    • UI部品のパブリッシュ-ngComponents Everywhere

特定のAngularコンポーネントをWeb Componentsに乗せ、フレームワーク無関係で利用できるようにする

Angular特有の課題解決-Dynamic Bootstraping

Angularアプリ全体をWeb Components化して、component単位でbootstrapできる手段を提供し、実行タイミングをコントロールできるようにする

Rob Warmald先生是这个提案的发起人,他最初设计了一个轻量级的Web Components API。Rob先生在6月份发布的angular-elements 3示例库主要关注发布特定的UI组件,它将window.customElements.define()进行了包装,并允许将扩展了HTMLElement的Angular组件作为自定义元素进行发布。这个示例对于我这个作者来说,读起来很顺畅,感觉很容易理解。

一方面,实施了@angular/elements的gkalpak先生似乎非常重视将Angular应用程序的引导进行解构,使其能够按组件进行自我引导。这样做的目的是将现有的Angular应用程序转化为Web组件。他还提到,@angular/elements最终可能会被包含在核心程序包中。老实说,对于这些谈论,作者并没有跟上。他们正在试图实现的内容似乎与另一个实验项目ngiv存在重叠,给人一种流动的感觉。

另外,当Rob在十月和十一月份展示@angular/elements时,双方都被包含在内,所以两者似乎都是@angular/elements的目标。@angular/elements的registerAsCustomElements()的定义也涉及这两种多态性。(两个export函数 + 将两者混合的实际实现共计三个。)

幻灯片资料
https://docs.google.com/presentation/d/1jiXHYwfe1iSUiVLdKLFhSPRHLI_FmIvrI60QTpP6KLk/mobilepresent?slide=id.g26d86d3325_0_0
优酷

在各处发布UI组件:ngComponents

你现在可以创建并在互联网上发布你喜爱的潮流按钮了。与以往不同的是,你现在可以接触到不仅限于Angular用户的人群。

容易理解的是Web Components的资产存储6。例如,MaterialDesign目前在每个js框架中实现,如Material Design Lite(JQuery)、AngularMaterial、Material-UI(react)、VueMaterial、paper-elements(polymer)。然而,如果只需要标准接口,通过存储提供MaterialDesign的提供,无论与js框架有无关系,都可以处理。

(@angular/elements的registerAsCustomElements()的使用方法将在另一篇文章中详细介绍。)

此外,Preact和Angular协调演示也已经展示出来。如下所示,Preact的组件内使用JSX编写了Angular自定义标签。

/** @jsx h */
const { h, render, Component } = Preact;

// Preacのコンポーネントを普通に作る
class Demo extend Component {
  constructor() {
    super();
    this.state.progress = 0;
  }

  ...

  render(props, state) {
    // Angularのカスタムタグを記述
    return <ng-progress-bar progress={state.progress}></ng-progress-bar>;
  }
}

render(<Demo />, document.body);

地球原来只有一个。

Angular所独特的问题解决方式-动态引导

设立多个入口点

这是一个完全针对Angular用户的说明,目前Angular的入口点= bootstrap基本上只注册一个组件。bootstrap本身是一个数组,在之前提到的“在构建Angular文档站点时遇到的问题”中,我们按照现有的bootstrap形式将embeddableComponents作为数组放入entryComponents中。@angular/elements可以全局覆盖bootstrap以注册多个组件。

将main.ts中的platformBrowserDynamic().bootstrapModule(AppModule)替换为registerAsCustomElements(webComponents, bootstrapFn)的形式。

筆者有点跟不上的重点是,用这种方法,与现有的Angular应用程序几乎没有太大的差别。仍然是SPA,通过路由进行跳转。只是main.ts和app.module.ts的描述有所不同,就像是将现有的Angular应用程序转化为Web组件一样。真的吗?

我們可以通過一個簡單的例子來展示差異。

这是现状。我只是为了比较而发布,实际上几乎是刚使用angular-cli的ng new创建的状态。

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

将Web Components化。在示例代码中通过评论,作者会加上自己的困惑或解释。

import { enableProdMode, destroyPlatform } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { registerAsCustomElements } from '@angular/elements';

import { AppModule, webComponents } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

// なんだこれは!?
destroyPlatform();

const bootstrapFn = () => platformBrowserDynamic().bootstrapModule(AppModule);
// 第一引数にWebComponentsとして登録したいcomponentをセットする。
// 第2引数にこれまでのbootstrapをセットしている。
registerAsCustomElements(webComponents, bootstrapFn)
  .then(moduleRef => /* Custom Elements are ready. Do your thing... */);
  .catch(err => console.log(err));
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LikeButtonComponent } from './like-button/like-button.component';

// エントリーポイントにしたいcomponentを並べている。
export const webComponents = [
  AppComponent,
  LikeButtonComponent
];

@NgModule({
  declarations: [
    ...webComponents,
  ],
  // bootstrapのキーは記述せずにentryComponentsにする
  entryComponents: [
    ...webComponents
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
  ],
})
export class AppModule {
  // お前はどこから来た?
  // 手動でbootstrapするためのものらしいが...
  // https://blog.angularindepth.com/how-to-manually-bootstrap-an-angular-application-9a36ccf86429
  ngDoBootstrap() { }
}

SPA和SSR方法的替代选项

这是一个我很少听说过的故事,作为作者,我脑海中构想着一种不使用router的Angular框架。它是作为非SPA(单页应用)存在的,通过服务器路由来保留模板,可以在页面或同一页面中嵌入多个Angular组件的方式。

总的来说,这是一种替代方法,用于构建需要SEO和OGP等应用程序服务的情况,即SSR(服务器端渲染)的需求变得重要。我认为SSR是一种弯曲的解决方案。就是将最初在服务器上创建的模板作为SPA导入到浏览器中,然后再返回到服务器,结果需要另一个node服务器,这太麻烦了!

像Rails和Spring这样的web框架通常都有模板引擎。将@angular/elements与ESModule集成到模板引擎中,就可以按组件单元进行挂载。

因为诚实,所以我觉得将其集成到Web框架中可能会很困难,因为需要使用Node&Angular环境。但是,如果能够像Rails的AssetPipeline一样进行集成,那将会非常方便。关键是使用Custom Elements和ESModule。

只是,我也认为另一个实验项目“ngiv 5”可能会承担起这个角色,正如@lacolaco指出的那样,iv可能是Isomorphic Viewengine的缩写。我找到了作者当时公开的ngiv存储库,但我记得源代码中有一些node的出现,可以看出分别使用了DOM Node的含义和Node.js环境的含义。我只能确认它是基于浏览器API的。

目前阶段可做之事

目前,@angular/elements正在实验性的R&D项目称为lab中开展。同时,它也已经在npm上发布,供使用。

$ npm install angular/elements-builds#labs/elements

在https://github.com/angular/angular/tree/labs/elements中,该代码库提供了分支选择。

筆者曾經複製並娛樂過這個樣板儲存庫。這是指向將SPA保持不變並將其轉換為WebComponents方向的樣本。
https://github.com/playerx/angular-elements-sample

未来的发展

据说作为未来的里程碑,labs将收集反馈,并计划在明年4月的Angular6版本中引入试验性功能,目标是正式发布。另外,在已关闭的Pull Request中,于12月7日添加了一个关于未来路线图的问题评论,gkalpak先生回答如下。4

    • coreに入るかもしれない?

 

    • coreの内部改造を研究中であり、それを受けてngElementsも改良することになるだろう(バンドルサイズの削減など)

 

    • angular.ioでngElementsを投入する

 

    ドキュメントを準備する

另外,3天前,有关于Web Components的问题已经出现。gkalpak先生正在将与@angular/elements有关的议题引导到本讨论串中。
https://github.com/angular/angular/issues/20859

最后

因为这是关于未来的谈论,所以只是我的主观看法,但我认为随着Web组件的全面运行,JavaScript框架的方向将变得解散或融合。

本文中提到的对Bootstrap的解构,可以说是在Angular的优点和缺点之间,通过Web Components的介入而开始进展的动态。这可以看作是在React中,从virtualDOM到Fiber的刷新动态。对于React而言,virtualDOM是其优点,但在canvas和媒体方面则成为了其弱点。Fiber的目标是增加调优功能,但作者注意到它在与DOM的协调方面进行了转变。(可以说是优点和缺点的两面性,根源较深,不太容易简单解决的样子)。

从过去开始,人们认为基于组件化的JavaScript框架是对浏览器在Web Components完成之前的polyfill。虽然Web Components已经完全支持,但我并不认为当前局部优化的各个JavaScript框架的任务已经结束。然而,通过逐渐开放外部接口,我们可以降低互操作性的门槛。Angular和Preact的协同演示是一个象征。我将这称之为融合在一起。

目前的情况下,同时使用多个JavaScript框架并非仅仅解决接口问题,同时还会导致打包文件的增大和开发环境的复杂化等问题。可以说,“虽然可以做,但是否值得去做”是一个讨论点。

然而,只要问题得到明确定义,解决问题就是工程师的责任。Angular已经开始运转。因此,通过Web组件的推动,生态系统和技术人员的技能栈也会发生重大变化,相互操作将得到进一步发展。

地球原来只有一个呢(第二次)

以上是。明天是@ponday先生。

请参考此链接中各个JavaScript框架对自定义元素接口的支持情况。Angular和Vue的支持得分很高,而React稍微拉低了我们的期望。不过,Preact也在不断努力。如果使用小写或kebab-case,则可以进行事件同步。
广告
将在 10 秒后关闭
bannerAds