暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

开源中间件通迅(2020年第1卷,第1期)

开源中间件 2021-09-10
315

因为工作关系,开源通迅没有及时得到更新。

经过考虑,今后以短篇幅的简报形势发布,类似于开源软件的发布理念,“尽早发布,尽快迭代”。


本期内容要和大家介绍一些前端技术的趋势。


前端技术应该说是技术更新换代最快的,别说早已淘汰的Applet,XUL等,就是曾经大红大紫的JQuery,Flash等,目前也早已被代替。


目前主流前端技术是基于Javascript的框架,如React,Angular等,除了可以运行在较新的浏览器上,也可以适配各种尺寸的移动终端,还有原生APP的框架,如React Native, Ionic等。受益于NodeJS高效编译和运行技术,Javascript各代语法特性和进化语言,快速纷呈发展。P


C端跨平台的高生产里的UI技术,如基于Electron和NW.js的应用,像目前大火的IDE Vscode,制作小程序的开发工具等,也都是JS框架技术。可以说,现在做前端,不懂JS将寸步难行。


从三个侧面介绍去年下半年以来出现的一些趋势。


一,Web Components技术已经越来越被更多的浏览器作为标准技术进行实现。


用一段代码来说明吧:


index.html:

<html lang="en">

<head>

  <title>Web Component</title>

  <link rel="import" href="./world.html">

</head>

<body>

  <h1>Web Component</h1>

  <!--2. 使用web component -->

  <world id="wd" title="helle world"></world>

  <script>

    通过更新组件的属性,来触发title的改变

    setTimeout(function() {

      document.querySelector('#world').setAttribute('title', '你好, 世界!');

    }, 1000)

  </script>

</body>

</html>


world.html:

<template>

  <style>

    .title {

      color: red;

    }

  </style>

  <h1 class="title">你好</h1>

</template>

<script>

  (function () {

      var thisDoc = document.currentScript.ownerDocument;

      var template = thisDoc.querySelector('template').content;

      var element = Object.create(HTMLElement.prototype);

      初始化创建的时候回调

      element.createdCallback = function() {

        var clone = document.importNode(template, true);

        开启shadow的子根节点,这样才能 this.shadowRoot.querySelector('.title')获取到h1

        var shadowRoot = this.attachShadow({ mode: 'open' });

        shadowRoot.appendChild(clone);

      }

      属性改变的时候触发的回调

      element.attributeChangedCallback = function(attr, oldVal, newVal) {

        this.shadowRoot.querySelector('.title').innerText = newVal;

      }

      document.registerElement('world', {

        prototype: element

      })

  }());

</script>


利用这段文字,可以自行定义元素名称,如"world",实现元素界面的扩展。

目前 W3C 对 Web Components的定义包括:

  1. Custom Elements自定义元素。

    就是上面体现的特性,提供一种方式让开发者可以自定义 HTML 元素,包括特定的组成,样式和行为。

    支持 Web Components 标准的浏览器会提供一系列 API 给开发者用于创建自定义的元素,或者扩展现有元素。

  2. HTML Templates HTML模板。

    提供了一个 template 标签来存放以后需要但是暂时不渲染的 HTML 代码。

  3. Shadow DOM 旨在提供一种更好地组织页面元素的方式,来为日趋复杂的页面应用提供强大支持,避免代码间的相互影响。

  4. JSON, CSS, HTML Modules。

    对各种资源文件提供统一的模块化引入机制。


看到这个规范内容,让我想到XML格式又会引起纷争,还有20年前就已经定义完备的XUL语法。技术界的轮回真是一次又一次。


二,Martin Fowler提出的Micro Frontends模式


Martin的PEAA是软件架构的经典之作,也几乎踏准了每一次的技术演进。Micro Frontends这个词,我们可以按照MicroService的方式,翻译成微前端。

经典的Web架构,分拆前后端之后,前端和后端可以都看作“单体”,即把所有的功能都混合在一起,组成完备的应用。目前业界已经完全接纳了微服务后端体系,那么前端也可以进行分拆吧。


按照目前的技术,实现“微前端”的方式可以有几种方法:


  • 1. 服务器端的模板组合。通过服务器,可以同时渲染多个页面到单一页面中。这种方式容易实现,但需要服务器配合。

  • 2. 构建时集成。目前JS框架写成的前端,有构建(编译)的过程,用来减少体积,提升效率和适度混淆,可以利用这个过程进行多个模块的集成。

  • 3. 通过iframes在运行时集成。通过JS代码,分析请求并在子frame中加载不同的页面。这种方法也容易理解,只是子frame方式割裂了整体页面完整性。

  • 4. 通过JS在运行时集成。通过JS代码,分析请求并将路由导入不同的页面和JS代码中。这种方法是目前主要采用的方式。

  • 5. 通过Web Components运行时集成。和上面的方法相同,只是利用前面谈到的标准Web组件的方式。应该是最“优雅”的方式。


通过“微前端”技术定义,前端开发人员也可以进行分工协作,完成各自的工作模块。其实目前的JS框架都有模块的概念,这个从规范性进一步明确定义。


三,WebAssembly


WebAssembly中有汇编Assembly,从名字上就能知道是给Web使用的汇编语言,可以通过浏览器执行二进制语法。


但WebAssembly并不是直接用汇编语言,而提供了中间语言机制(LLVM IR),把高级语言(C,C++和Rust)编译为WebAssembly,在浏览器中运行。可以解决目前JS语言的效率问题,设计目标为快速,内存安全和开放。


所以是一种运行机制,一种字节码格式(.wasm)。简单来说,可以认为浏览器从之前的解释执行 js 变为直接运行二进制格式的代码,


通过LLVM等工具,可以编译不同的语言到字节码wasm格式。WebAssembly 模块,它可以加载到 JavaScript 中使用。

function fetchAndInstantiate(url, importObject) {

   return fetch(url).then(response =>

     response.arrayBuffer()

   ).then(bytes =>

     WebAssembly.instantiate(bytes, importObject)

   ).then(results =>

     results.instance

   );

 }


.wasm文件包括必须的和可选的部分。


必须部分:

  • Type:在模块中定义的函数的函数声明和所有引入函数的函数声明。

  • Function:给出模块中每个函数一个索引。

  • Code:模块中每个函数的实际函数体。


可选部分:

  • Export:使函数、内存、表(tables)、全局变量等对其他 WebAssembly 或 JavaScript 可见,允许动态链接一些分开编译的组件。

  • Import:允许从其他 WebAssembly 或者 JavaScript 中导入指定的函数、内存、表或者全局变量。

  • Start:当 WebAssembly 模块加载进来的时候,可以自动运行的函数(类似于 main 函数)。

  • Global:声明模块的全局变量。

  • Memory:定义模块用到的内存。

  • Table:使得可以映射到 WebAssembly 模块以外的值,如映射到 JavaScript 的对象。这在间接函数调用时很有用。

  • Data:初始化导入的或者局部内存。

  • Element:初始化导入的或者局部的表。


目前主流的语言基本已经都有对WebAssembly的支持。Java语言中,也有一些开源项目。


TeaVM是一个AOT编译器,可以将Java文件编译成wsam格式,Java语法采用和GWT类似的方式。


import org.teavm.jso.ajax.XMLHttpRequest;

import org.teavm.jso.browser.Window;

import org.teavm.jso.dom.html.HTMLButtonElement;

import org.teavm.jso.dom.html.HTMLDocument;

import org.teavm.jso.dom.html.HTMLElement;

public final class Client {

    private static HTMLDocument document = Window.current().getDocument();

    private static HTMLButtonElement helloButton = document.getElementById("hello-button").cast();

    private static HTMLElement responsePanel = document.getElementById("response-panel");

    private static HTMLElement thinkingPanel = document.getElementById("thinking-panel");


    private Client() {

    }


    public static void main(String[] args) {

        helloButton.listenClick(evt -> sayHello());

    }


    private static void sayHello() {

        helloButton.setDisabled(true);

        thinkingPanel.getStyle().setProperty("display", "");

        XMLHttpRequest xhr = XMLHttpRequest.create();

        xhr.onComplete(() -> receiveResponse(xhr.getResponseText()));

        xhr.open("GET", "hello");

        xhr.send();

    }


    private static void receiveResponse(String text) {

        HTMLElement responseElem = document.createElement("div");

        responseElem.appendChild(document.createTextNode(text));

        responsePanel.appendChild(responseElem);

        helloButton.setDisabled(false);

        thinkingPanel.getStyle().setProperty("display", "none");

    }

}

熟悉Javascript和GWT的开发者可以很容易理解这段代码,通过编译成wasm文件供浏览器加载执行。


JWebAssembly 是一个Java二进制的编译器,可以编译代码片段,使用方式和上面的TeaVM类似,不过没有使用GWT类似的封装方式。


另外GraalVM项目也宣布了发布GraalWasm项目,提供一个引擎运行wasm格式文件。作为Graal的外部项目,通过gu命令进行安装。Java应用程序可以使用GraalWasm引擎来执行wasm文件。


总结


前端技术进入一个有趣的新阶段,以上介绍的技术还有待继续成熟。

作为中间件后端技术的爱好者,我认为上述前端很有前途,可以和后端中间件新技术更好的配合使用,更高效的开发软件应用。


文章转载自开源中间件,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论