0%

使用 Quasar 时,如何完成浏览器兼容性的配置。

制定兼容范围

在进行实际配置前,首先必须确定要支持浏览器的版本,而确定浏览器版本则需要先明确业务对象的情况。

为什么不干脆把标准定的越高越好呢?比如支持100%的用户。这是因为支持率越高,可用的新语法越少,意味着更多的转译代码和 polyfill,这会带来额外的代码量,从而导致下载数据量增加,以及运行速度变慢的问题,为了0.01%影响99.99%用户的体验并增加他们的流量开销,是否合适呢?这就需要根据实际业务进行取舍和平衡。

比如我们的业务对象既有企业用户,也有公众用户,企业用户主要使用钉钉,并可对其PC浏览器进行要求,而公众用户主要使用微信。

确定常用浏览器版本

PC浏览器可以指定,那么对浏览器版本就不需要过多考虑,但是部分客户还有XP系统,那么也就确定了 Chrome 浏览内核的版本不可以超过 49;

微信用户可能在手机登录,也可能在PC登录,而PC中的微信内置是QQ浏览器9,其内核版本是 Chrome 53;

电脑端的钉钉内置浏览器已经是 Chrome 91;

手机端的话考虑到安卓手机使用寿命比苹果要短,且微信和钉钉都可以内置新版本的引擎,而苹果手机必须使用系统自带的 Safari 浏览器内核,因此手机端的版本以支持 Safari 为目标,目前苹果官方支持的最老的设备是2015年发布的 iPhone 6s,如果用户从来没有升级过系统,那么自带的就是 Safari 9;

因此主要的浏览器版本支持就是 Chrome 49 与 Safari 9。

通过 browserslist 完成浏览器版本配置

在 package.json 中添加 browserslist,保持其他配置为默认值,修改 Chrome 和 ios_saf 的版本:

"browserslist": [
  "ie 11",
  "Chrome >= 43",
  "ios_saf >= 9",
  "last 10 Firefox versions",
  "last 4 Edge versions",
  "last 7 Safari versions",
  "last 8 Android versions",
  "last 8 ChromeAndroid versions",
  "last 8 FirefoxAndroid versions",
  "last 10 iOS versions",
  "last 5 Opera versions"
],

处理第三方库

采用上述配置会使 Quasar 在转译时调用 babel ,并根据指定的目标浏览器转换用户编写的代码,使其能在上述浏览器中运行。但是对于通过 npm install 安装的第三方库,并不会进行转译。比如函数式编程工具库 rambda 会用到 Object.values 这个方法,但 Chrome 49 并不支持这个方法,不对其进行处理就会报找不到方法的运行时错误。

处理方式也很简单,通过 quasar.conf.js 的配置告诉 babel 哪些第三方库需要被转译即可。 将 build 中的 transpile 设为 true,并在 transpileDependencies 中添加 rambda 选项。

build: {
  ...
  transpile: true,
  transpileDependencies: ['rambda'],
  ...
}

持续改进

完成上面的配置,可以初步估算我们的程序至少可以支持99.5%以上的用户。根据 caniuse.com 中的统计,国内大约还有 0.1% 的用户在使用 iOS 9 之前的版本以及 0.36% 的用户在使用 Android 5 之前的版本,但考虑到我们的程序未必一定使用了某些不被支持的特性,以及微信和钉钉自带浏览器也会采用比原始系统更新的内核,所以实际的支持率可以更乐观一些。

回到实际生产环境,上述都是理论推断,最终还是需要以实际情况为准。

比如 iOS 9 理论上支持 const 但不能在 use strict 模式中使用,这会导致 babel 7 编译的代码无法在早期的 iPhone 中使用,最终我们通过添加 ios_saf >= 8 将版本进一步降低才解决了这个问题。这类问题都是在实际使用过程中才能发现的,因此需要不断的根据现实反馈才能正确支持目标用户,并控制好生成出来的最终代码量。

而随着时间推移,旧手机的用户比例会进一步降低,到时候又可以将支持的浏览器版本往前推移,使编译结果能使用更多新语法,从而提升大多数用户的体验。

常用工具

因为技术方向的调整,去年底开始学起了 Java,也不是正儿八经的学,看了点 Spring Boot 的基础,拿起项目直接套用其他语言的经验跑起来再说。增删改查嘛,除了库不熟,效率低点,实现功能是没有压力的。

现在酝酿的差不多,渐渐要开始搞自己的框架了,便打算补补基础知识,通过翻阅网上各种荐书的讨论,最终定下来从《Head First Java》入手。正好 O’Reilly Learning 上面也出了第三版的预览,便翻来看了。

这个系列的书我见过不少,但从没看过,因为一看封面就会觉得很浮燥,不怎么正经的感觉。

直觉很准,这本书确实不像其他技术书籍那么“正经”,尤其是里面配的照片,甚至有些搞笑。但作者很真诚,配合讲解的手绘插图也非常细致,足够 Head First,对大脑很友好,也许直白点叫 Brain Friendly 我就能抓到他的点了。

这里我不想讨论书的内容,而是更留意其写作的方法,体会较深的有这么几点:

  1. 在某个例子里,先不去考虑边界情况,尽管代码有BUG,但简短很多,这样读者就抓住重点,作者还一箭双雕,利用这个BUG自然的引出下文要解决的问题。 我之前写过不少教程类的东西,总是事无具细,把自己能想到的漏洞和各种可能发生的问题都写在解决过程中,别人如果照着做确实不容易出错,因为大多数异常情况都考虑到了,但是不曾想过可能会让读者迷失重点,对于有经验的人读起来也会比较浪费时间。也许采用备注等形式,把异常情况的处理跟在全文的最后,能让读者更能把握整体脉络。

  2. 某些例子中,某个具体功能的实现,作者会给出一段代码,称作 Ready-Bake Code,让读者先别管它是怎么来的,只管照抄进去,被跑出正确结果就行,这样读者的重心就可以放在作者希望读者关注的地方,而不用理会暂时不必关心的细节。 和上面一样,不必立刻详细的去解释所有东西,只要关注重点,有必要解释的,可以另外开一篇文章,让读者选读。

  3. 书的整体内容安排上,使左右脑交互使用,作者引用脑科学的研究提出大脑和手臂一样,连续使用右脑就和持续用右手提重物一样,需要休息,换另一边来,才能提高效率。 这个表述我第一次见到,但结果应该是没差了,《Learning How to Learn》的核心也是切换,但更强调有意识和潜意识之间的切换。不过真要把输出的内容整理成图文并茂,左右半脑并用,还是要下非常大的功夫在上面的。

  4. 明确的采用 prep code → test code → real code 的步骤,这个倒和我的做法有些许相似,对一些复杂的内容,我会先写注释,把步骤描述一下,然后再写具体代码。 虽然作者主要是从 TDD 的角度讲这个事情,但我发现很多代码逻辑理不清的都是没有把层级分解好,一股脑把代码堆进一个很长的函数中,导致难以理解和维护。先用注释将过程一步一步讲下来,然后换成几行对应的代码或者一个函数,可以很好的分解问题。

  5. 还有其他非常多样的形式:文字、代码、图片、问答、猜字谜、模拟人物访谈、顺口溜,花样百出,还给每种不同的题目类型设计了场景。甚至前面提到的“不正经”、夸张、搞笑也算是情绪方面的手段了。

好吧,写到最后,我才知道这个系列的中文版叫《深入浅出***》,确实配得上,希望自己也能做到吧。

软件版本的选择 一文中提到过一个原则:通过使用前后端通用的组件来减少组件的总体数量。由于 webpack 等工具的存在,许多原本设计给 Node.JS 使用的库,也能在未经修改的情况下给浏览器使用,乍看之下组件的通用度大幅提高了,但实际用下来,却发现存在着导致编译结果体积膨胀的问题。

因此在实际使用过程中,对库的选择还要进一步审视和辨别,正如该文中所说:

裁剪不能过度的牺牲功能、性能或用户体验。
阅读全文 »

技术背景

下面所列的是本项目中主要用到的技术和工具,以及你需要对它们掌握到什么程度才能顺利的阅读本文。

本文及相关代码在 macOS 下写作,如果你使用其他系统,下面的部分命令可能需要相应调整。

PostGraphile

PostGraphile 可以根据 PostgreSQL 数据库中的内容自动生成 GraphQL 接口。 开发人员设计好数据库中:表的结构、表之间的关系、用户的操作权限, PostGraphile 就能自动将这些关系映射到最终的 GraphQL 接口中。 表中的注释会被用于接口的说明,更有智能注释提供额外功能。 这被开发者称为 DDGD(Database-Driven GraphQL Development),即数据库驱动的 GraphQL 开发。

本文主要就是介绍这个工具,所以目前不要求你对它有所了解。

PostgreSQL

PostGraphile 只支持 PostgreSQL 数据库,并充分利用了它的强大能力。 比如通过行级权限实现细致的访问控制,通过触发器实现订阅等。

本文不要求你使用过 PostgreSQL ,但你必需要有最基本的数据库理论知识。 你可以从 这里下载到 PostgreSQL 的安装包,也可以通过自己熟悉的包管理工具安装它。

GraphQL

GraphQL 是一种用于接口的查询语言,其最大的特点是灵活,数据按需取用。 甚至将原先只能在服务器上通过 SQL 查询实现的联表等能力转移给了客户端。

本文会对它的基本使用进行介绍,想要详细掌握可以考虑阅读 Learning GraphQL 一书。

Node.js 与 Express

PostGraphile 本身使用 Node.js 编写,既可以作为独立的命令行工具使用, 也可以嵌入到 Express 应用中作为大系统的一个组成部分使用。

阅读本文需要你对 Node.js 与它的包管理工具 npm 有基本的了解。

nanographql

一个最轻量的 GraphQL 查询生成器,只负责生成请求 body 的功能,因此可以和各种请求库整合,且不受客户端类型的限制。既可以用在 H5 页面,也可以用在小程序等场合。

你不需要预先对其有所了解。

todomvc/vanilla-es6

本项目的主要目的是说明 PostGraphile 及相关技术的使用方法,为了便于理解,借用大家都熟悉的待办事项作为实例。 因为重点不在前端,所以这里是对现成的 Todo 项目进行改造,来对接 GraphQL 接口。

todomvc 是一个开源项目,用来比较各种前端框架的 Todo 实现,为了覆盖尽可能多的受众,我们采用 vanilla-es6 版本作为本项目演示的基础。

PostGraphile 是一个可以根据数据库结构生成 GraphQL 接口的工具。 它的自动化程度非常高,实现了表结构、关系、限制、访问权限等的自动映射,能有效提高服务端接口的开发效率。尤其是对于不和第三方对接的系统,甚至可以做到直接免除所有后端开发工作。

我在工作中使用了 PostGraphile,并取得了一定的成功,于是希望将这个好东西推荐给大家。 这里,我想通过为一个待办事项服务搭建 GraphQL 接口的过程,来展示如何使用 PostGraphile 。 如果能引起你想试着用一下它的兴趣,我的目的就算达到了。

这里涉及的大多数内容,在 PostGraphile 的官方文档中其实都能找到,毕竟我也是照着官方文档来学习的。 只不过官方文档以功能为出发点,而我是顺着一个假想的项目需求来介绍。

我们将从一个单机版的待办事项应用开始,逐步改造成一个代办事项服务。 首先,我会介绍一个基于浏览器(SPA)的代办事项软件,事项被保存在浏览器中,不需要与服务器交互; 接着,我会把它改造成可以将数据保存在远程数据库中的联机系统,并在此过程中介绍 PostGraphile 的基本功能; 然后,将其从单用户系统扩展成多用户,引入账号和登录的概念,并在此过程中介绍 PostGraphile 的权限管理功能; 最后,进一步完善系统权限,让用户只能访问到自己的代办事项,并在此过程中介绍 PostgreSQL 的行级权限功能。

除了实现上述功能,我还将在整个过程中穿插自己使用时遇到的问题和解决方法,并在最后讨论一下与外部系统交互的解决方案。

严格来讲,PostGraphile 并不是将后端的工作自动消灭了,而是将后端开发过程中与数据库建设之间重复的工作给消灭了。 你需要更严谨的设计和管理数据库才能达到更高的自动化目标,这会迫使你花更多时间在数据库上面,而这些时间都不会白费,因为你会在完成接口服务的同时,得到了一个更健壮的数据库。

Angular、React 和 Vue 的大流行导致现在越来越多的 Web 项目以单页面应用(SPA)的形式进行发布。

在前端文件的缓存方面,由于我早先是使用 PHP + Riot.js 的组合,虽然也是单页面应用,但主入口由 PHP 提供,默认就不缓存,所以只需在 nginx 中将所有静态文件强制缓存到客户端就行。

而换到 Node.js + Vue 之后,主入口换成了 index.html,并且和其他静态文件一起都是通过 express.static 提供给客户端的,所以要针对性处理才能同时满足性能和功能方面的要求。

记得之前有一次搞过头,把 index.html 也缓存了,从而影响到前端的正常更新,最终只能改回默认的缓存规则。为了尽可能加快用户访问速度,又不把事情搞砸,今天终于静下心来对其进行了合理的优化。

阅读全文 »

两年前(2018年),在使用 PostGrahphile 一段时间后,打算总结自己在实践中的经验,于是陆续用数周闲暇时间,写了 《PostGrahphile入门》 一文。止于2019年4月18日,完成了预计的7个章节中的前5部分,今年想要继续时,发现其中多处已跟不上最新的发展,而自己的认识也已更进一步。遂计划重来一版,先将原有部分翻新,再补上缺失的后两章。用每周更新的博客形式呈现,初步估计需要3个月左右。如果顺利,再花2-3周做成完整的电子书,最后定期迭代,使其紧跟技术更迭和个人认识的发展。

阅读全文 »

一套环境通常不会只部署一遍,你会遇到各种需要重复部署环境的情况:也许是一个项目需要多台服务器来运行;也许是同时需要管理多个项目;也许是需要生产环境和开发、测试环境的一致性。总之,掌握高效的方法和工具是非常必要的。

这周我来讲讲自己在服务器环境部署上经历的四个阶段,以及选择背后的原因。

上周讲了服务器系统的选择,这周回来继续讲软件版本的选择,更具体一点来说是服务端运行环境中软件版本的选择。

每个人遇到的情况不同,做出的选择也不同,所以这个问题并没有标准答案,而会是一些方向性的思考。

我的出发点是让尽量少的人来维护尽量多的项目,所以得出的结论可能会和网上常见的文章不同。

就让我学学《程序员修炼之道》先给出一个一般性原则:

Tip
出于减少开发和维护成本的目的,必须减少组件数量,如果组件数量无法减少,就减少它们组合的数量。

这里的组件是一个非常宽泛的概念,既可以指操作系统,也可以指编程语言里面用到的包或库,还可以指数据库、缓存这样独立运行的应用。

这是一个寻找最大公约数的过程。

阅读全文 »