从 SPA 到 PWA

Web PWA SPA

AJAX(Asynchronous JavaScript + XML,异步JavaScript和XML)开始应用, 尤其是 AngularJS 推出之后 SPA(Single Page App,单页应用)已经成为前端 App 的必选方案。 SPA 可以在客户端提供完整的路由、页面渲染、甚至一部分数据处理; 这往往需要一个比 jQuery 时代更重的 JavaScript 框架,来实现这些原本发生在后端的逻辑。 多数框架如 ReactVue 还会内置组件化机制来帮助开发者组织代码, 它们甚至进化到专门负责视图组件的程度,路由和数据交由各种插件来处理, 比如 vuexReduxVue Router 等等。 这些工具已经相当先进和完整,提供了路由方案、服务器端渲染方案、前端状态管理方案。

但 SPA 的本质还是浏览器端 App,底层技术仍然依赖 history APIdefinePropertyAJAX。 这些 API 的能力和完备性,决定了 SPA 能达到的用户体验和上层架构设计。 也正是这些底层 API 的不足和缺陷使得 SPA 很难企及原始 Web 的架构优势。 比如在内容可访问性(Accessibility)、服务的独立部署和演化(Independent Deployment) 等方面远不及十年前搭建的同类站点。同时还在不同程度上破坏了 HTTP、URL、HTML 的语义, 这些缺陷使我们需要花费大量精力去修复日志统计、性能优化、首屏渲染、静态分析和测试等环节。 而陷阱在于决策使用 SPA 方案时不一定能有足够的远见看到这些问题对架构带来的深远影响。

与此同时 Web 标准也在持续迭代,诸如 Web Bluetooth、Push API、Web of Things、Service Worker 的标准已经在主流浏览器(尤其考虑国内 webkit 内核的普及程度)有不同程度的支持。 尤其是 PWA(Progressive Web App,渐进式 Web 应用)概念的提出, 给出了一种在不破坏 Web 架构的前提下实现流畅用户体验的方式。 本文就 SPA 架构的一些不足展开讨论, 并探讨 PWA 方案(这里说是方案,其实更是一种技术方向的选择)的价值和私有平台的最佳演化方式。

ES Modules 和 ES5 Script 之间相互引用

CommonJS ES6

ES5 没有定义文件之间引用方式,在浏览器中文件之间引用需要通过类似 define, require, __webpack_require__ 这样的全局变量,它们由不同的模块化框架定义。 ES Modules 从标准上定义了 JS 文件间的引用方式,而且现在主流浏览器和 Node.js 都已经有了实现。 本文介绍 Node.js 中新写的 ES Modules 怎么和旧的 CommonJS 模块相互引用, 以及如何引用 npm 上成千上万的 CommonJS 模块。即 ES Modules 和 ES5 Script 间的互操作问题。 ES5 Script 有多种模块化实现,本文集中讨论 Node.js 中的 CommonJS。

『开发者体验』骗局(译)

Web 性能

这是 Harttle 在去年发布在 百度 Web 开发者中心 的译文。为便于传播也转载在这里。 原文:https://infrequently.org/2018/09/the-developer-experience-bait-and-switch/。 作者:Alex Russell。翻译:Harttle

摘要:如果我们继续使用这么多的 JavaScript,Web 就不会走向繁荣。现在多数开发者仍然在不加限制地使用 JS。即使有很多无 JS 和 TTI 友好的工具,但是我们陷入 JS 的泥潭无法自拔。鉴于 JS 的不对称成本,我们需要重新讨论“开发者体验”。

TypeScript 中如何继承 Error 类

TypeScript Error 原型链

在 JavaScript 中很多时候都需要自定义错误,尤其是开发 Node.js 应用的时候。 比如一个典型的网站服务器可能需要有 NetworkError, DatabaseError, UnauthorizedError 等。 我们希望这些类都拥有 Error 的特性:有错误消息、有调用栈、有方便打印的 toString 等。 最直观的实现方式便是 继承 Error 类。 但考虑 TypeScript 需要编译到 ES5 兼容性问题会较为复杂, 本文用来帮助理解 TypeScript 中继承 Error 的问题来源以及对应的几种解决方式。

事件循环是如何影响页面渲染的?

JavaScript Microtask setTimeout requestAnimationFrame Promise

JavaScript 是单线程的,但提供了很多异步调用方式比如 setTimeoutsetIntervalsetImmediatePromise.prototype.thenpostMessagerequestAnimationFrame, I/O,DOM 事件等。 这些异步调用的实现都是事件循环,但根据插入的队列不同和取任务的时机不同他们的表现也不同。 尤其在涉及与页面渲染的关系时。

TL;DR

  • 页面渲染/交互任务也会插入在 Task Queue 中,会与各种异步机制插入的任务交错执行。
  • Microtask Queue 会在下一个任务开始之前清空。
  • 单个耗时任务和 Microtask Queue 都会阻塞页面交互,Task Queue 则不影响。
  • 渲染时机可以通过 requestAnimationFrame 精确控制。
  • setImmediate 与 setTimeout 一样使用 Task Queue,但克服了 4ms 限制。

如何调试 Vim 脚本

Vim-Practice Vim 调试 日志

使用 -D 参数可以开启 Debug 模式, 在 Debug 模式中可以使用 cont, next, interrupt, step, quit 等调试命令, 以及 breakadd, breakdel 来添加和移除断点。 使用 -u 来禁止加载任何配置文件,使用 :source 命令逐个加载。 使用 :set verbose:set verbosefile配置变量 可以设置日志级别和输出文件, -V 启动参数也可以起到同样的作用。

下一页