Wujie 简介
由腾讯开发的微前端框架,帮助开发者将复杂的前端项目拆分为多个微前端应用,实现分治开发、独立部署、统一集成的目标。
拥有以下几个特点(官网):
极速
页面切换时速度快,无白屏。(主要是通过开启预加载实现)
预加载
预加载指的是在应用空闲的时候requestIdleCallback将所需要的静态资源提前从网络中加载到内存中。
主流的 PC 屏幕刷新率(FPS)大多在 60Hz,即 1 秒钟对屏幕进行 60 次刷新,平均每次刷新耗时大概是 16.6ms。
requestidlecallback触发的时机有两种:
在一帧的输入渲染合成完成后才会有空闲时间触发
requestidlecallback;一帧内所做的事情如下:
- 输入事件处理:浏览器会处理用户的输入事件,如鼠标点击、键盘输入等,并将这些事件放入事件队列中;
- JavaScript 执行:浏览器会从事件队列中取出事件并执行对应的 JavaScript 代码,如事件处理函数、定时器等;
- 执行 requestAnimationFrame;
- 执行 dom 的回流与重绘;
- 计算更新图层的绘制指令(浏览器会将布局信息转换成绘制指令,并使用 GPU 进行绘制渲染,生成对应的位图);
- 绘制指令合并主线程(浏览器会将多个位图进行合成,生成最终的页面图像),如果有空余时间会执行
requestidlecallback。
在这个过程中,浏览器会尽可能地优化渲染流程,以提高页面的渲染性能和用户体验。实际上就是在 16.6ms 之内完成输入渲染合成,空闲的时间才会留给
requestidlecallback。没有任务执行浏览器会有 50ms 空闲时间,这个时间段也会执行
requestidlecallback。例如直接在控制台输出。
requestidlecallback(function (deadline) {
console.log(deadline.timeRemaining());
});
由于子应用提前渲染可能会导致阻塞主应用的线程,所以无界提供了类似于react-fiber方式来防止阻塞线程:
react16: postMessage + requestAnimationFrame来实现类似requestidlecallback()的功能;
- 使用
postMessage + requestAnimationFrame是因为 react 开发人员经过测试发现requestidlecallback()可能会超过 16ms,超过 16ms 绘制就会看起来很卡,所以 react16 是用postMessage + requestAnimationFrame实现的。- 使用
postMessage来代替setTimeOut()是因为后者即使为 0
react18 :使用MessageChannel实现requestidlecallback()。
强大
支持子应用保活、内嵌、去中心化通信、多应用激活。
子应用保活
简单
框架封装,保持普通组件使用体验一致。
原生隔离
基于 WebComponent 和 iframe,原生物理隔离。
WebComponent
window.onload = () => {
class Wujie extends HTMLElement {
constructor() {
super();
// shadowdom 样式隔离
let dom = this.attachShadow({ mode: "open" });
let template = document.querySelector("#wujie") as HTMLTemplateElement;
dom.appendChild(template.content.cloneNode(true));
console.log(this.getAttr("name"), this.getAttr("url"));
}
private getAttr(attr: string) {
return this.getAttribute(attr);
}
// webComponents的生命周期
connectedCallback() {
console.log("类似于vue的mounted");
}
disconnectedCallback() {
console.log("类似于vue的destory");
}
attributeChangedCallback(name: any, oldVal: any, newVal: any) {
console.log("类似于vue的watch");
}
}
// 使用原生js挂载一个组件
window.customElements.define("wu-jie", Wujie);
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="./index.js"></script>
</head>
<body>
<wu-jie name="fdsf" url="dsafas"></wu-jie>
<div>我是外层的div</div>
<template id="wujie">
<style>
div {
background: red;
}
</style>
<div>我是template里面的div</div>
</template>
</body>
</html>
iframe
将 js 单独存放在 iframe 中。
原生性能
避免 with 语句运行代码,整体的运行性能接近原生。
开箱即用
主、子应用无需做任何适配,开箱即用。
小结
缺陷
- 隔离 js 使用一个空的 iframe 进行隔离。
- 子应用 axios 需要自行适配。
- iframe 沙箱的 src 设置了主应用的 host,初始化 iframe 的时候需要等待 iframe 的 location.orign 从’about:blank’初始化为主应用的 host,这个采用的计时器去等待的不是很优雅。
底层原理:使用 shadowDom 隔离 css,js 使用空的 iframe 隔离,通讯使用的是 proxy。