Better

Ethan的博客,欢迎访问交流

阅读笔记:Error、同构、微前端、HTTP 与构建提速

近期阅读文章的一点小笔记,主要内容有 JavaScript Error 深入学习,同构应用容易被忽略的地方,微前端介绍、webpack 构建速度优化的几个思考方向。

JavaScript Error

追溯栈格式,每一帧由以下三个部分组成

  • 一个函数名
  • 发生错误的脚本在网络中的地址
  • 发生错误代码的行数和列数

为方便解析追溯栈,推荐这样做

  • 为匿名函数取名 / 将函数赋值给一个变量
  • displayName 属性:除了IE11,函数名的展现也可以通过给函数定义一个displayName 属性,displayName 会出现在浏览器的 devtools debugger 中

window.onerror 捕获错误

  • 存在的问题
    • No Error object provided:Safari 和 IE10还不支持在 window.onerror 的回调函数中使用第五个参数
    • Cross domain sanitization:Firefox、Safari 或者 IE11 中,并不会引入跨域的 JS 错误,Chrome 是唯一一个能够通过 window.onerror 检测到其他源上面的文件错误的浏览器,要么将其过滤掉,要么为其设置合适的跨域头信息
  • window.addEventListener(“error”):和 window.onerror API 相同
  • 并不能够阻止错误显示在浏览器控制台中,这通常是正确的,也是开发需要的,因为开发者可以很容易从控制台中看到错误信息。如果你不希望这些错误在生产环境中显示给最终用户,那么在 window.addEventListener 中使用 e.preventDefault() 可以有效的避免错误显示在控制台上。

try/catch 问题

  • 不能够捕获所有错误,比如异步错误
  • try/catch 不利于性能优化,不能够被 V8 编译器优化。
  • Protected Entry Points
    • 通过这些入口代码抛出的 JS 错误能够被 window.onerror 捕获到,但是遗憾的是,在浏览器中这些代码入口抛出的错误并不是完整的 Error 对象
    • 由于 try/catch 也不能够捕获到代码入口产生的 JS 错误
    • 对这些入口代码进行包装,这样就是的在函数调用之前我们就可以引入 try/catch 语句,这样也就能够捕获入口代码抛出的错误了。

一个 JavaScript 的代码入口就是指任意开始执行你代码的浏览器 API。例如,setTimeout、setInterval、事件监听函数、XHR、web sockets、或者 promise。都可以是代码入口。

保护代码入口例子

function protectEntryPoint(fn) {
  return function protectedFn() {
    try {
      return fn();
    } catch (e) {
      // Handle error.
    }
  }}
var _oldSetTimeout = window.setTimeout;
window.setTimeout = function protectedSetTimeout(fn, time) {
  return _oldSetTimeout.call(window, protectEntryPoint(fn), time);};

Promises

  • Promise 中的错误只会被 rejection 处理函数捕获到,window.onerror 是无法捕获到 promise 中的错误的
  • 可以使用 Protected Entry Points 来包装一些 Promise 的方法,在其中添加一个 try/catch 语句来处理错误,使用这种方法可使得我们捕获更多错误信息。

Promise 封装例子

var _oldPromiseThen = Promise.prototype.then;
Promise.prototype.then = function protectedThen(callback, errorHandler) {
    return _oldPromiseThen.call(this, protectEntryPoint(callback), protectEntryPoint(errorHandler));
};

Web Workers

  • Dedicated workers
  • Shared workers
  • Service Workers

同构应用

同构应用能够实现的本质条件是虚拟 DOM,基于虚拟 DOM 我们可以生成真实的 DOM,并由浏览器渲染;也可以调用不同框架的不同 APIs,将虚拟 DOM 生成字符串,由服务端传输给客户端。

同构应用中往往被忽略的细节

  • 打包环境区分:服务端运行的代码如果需要依赖 Node 核心模块或者第三方模块,就不再需要把这些模块代码打包到最终代码中了。因为环境已经安装这些依赖,可以直接引用。这样一来,就需要我们在 webpack 中配置:target:node,并借助 webpack-node-externals 插件,解决第三方依赖打包的问题。
  • 注水和脱水:涉及到数据的预获取。也是服务端渲染的真正意义。
  • 请求认证处理:透传 cookie 信息
  • 样式问题处理:isomorphic-style-loader
  • meta tags 渲染:React-helmet
  • 404 处理
  • 安全问题:serialize-javascript
  • 性能优化
    • 使用缓存
    • 采用 HSF 代替 HTTP
    • 对于服务端压力过大的场景,动态切换为客户端渲染。
    • NodeJS 升级。
    • React 升级。

微前端

微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。

微前端架构具备以下几个核心价值:

  • 技术栈无关:主框架不限制接入应用的技术栈,子应用具备完全自主权
  • 独立开发、独立部署:子应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
  • 独立运行时:每个子应用之间状态隔离,运行时状态不共享

MPA VS SPA

  • MPA 方案的优点在于部署简单、各应用之间硬隔离,天生具备技术栈无关、独立开发、独立部署的特性。缺点则也很明显,应用之间切换会造成浏览器重刷,由于产品域名之间相互跳转,流程体验上会存在断点。
  • SPA 则天生具备体验上的优势,应用直接无刷新切换,能极大的保证多产品之间流程操作串联时的流程性。缺点则在于各应用技术栈之间是强耦合的。

Stitching layer 作为主框架的核心成员,充当调度者的角色,由它来决定在不同的条件下激活不同的子应用。因此主框架的定位则仅仅是:导航路由 + 资源加载框架。而具体要实现这样一套架构,我们需要解决以下几个技术问题:

  • 路由系统及 Future State
  • App Entry
    • 构建时组合 VS 运行时组合
    • JS Entry vs HTML Entry
    • 模块导入
    • 应用隔离
    • 样式隔离:Shadow DOM?CSS Module? BEM? Dynamic Stylesheet !
    • JS 隔离:如何确保各个子应用之间的全局变量不会互相干扰,从而保证每个子应用之间的软隔离?

HTTP 协议

OSI 参考模型

  • 物理层:光纤和网卡等,负责通信设备和网络媒体之间的互通
  • 数据链路层:以太网,用来加强物理层功能
  • 网络层:IP 协议和 ICMP 协议等,负责数据的路由的选择与数据转寄
  • 传输层:TCP 协议和 UDP 协议等,承上启下,控制连接,控制流量
  • 会话层:建立和维护会话关系
  • 表达层:把数据转换为接受者系统可兼容的格式
  • 应用层:HTTP、FTP、SMTP 和 SSH 等,粗犷的理解为程序员层

TCP/IP 参考模型

  • 网络连接层:主机与网络相连的协议,如:以太网
  • 网络互联层:IP 协议和 ICMP 协议等,负责数据的路由的选择与数据转寄
  • 传输层:TCP 协议和 UDP 协议等,控制端对端的连接、流量和稳定性
  • 应用层:HTTP、FTP、SMTP 和 SSH 等,粗犷的理解为程序员层

HTTP 协议的网络层基于 IP 协议,传输层基于 TCP 协议,因此就引出了我们开头说到的:HTTP 协议是基于 TCP/IP 协议的应用层协议。

这部分内容作者写的十分详细,更多请点击末尾链接

Webpack 构建优化

构建打点:speed-measure-webpack-plugin,它能够测量出在你的构建过程中,每一个 Loader 和 Plugin 的执行时长

优化策略:缓存、多核、抽离以及拆分

  • 缓存
    • 大部分 Loader 都提供了 cache 配置项
    • 如果没提供,则使用 cache-loader
  • 多核:happypack
  • 抽离
    • webpack-dll-plugin
    • Externals
  • 拆分:微服务

提升体验工具

  • progress-bar-webpack-plugin
  • webpack-build-notifier
  • webpack-dashboard

来源



留言