HTML页面加载事件和性能评价指标

前端页面的性能一直都是一个热议的话题,从老早雅虎提出的35条”军规”开始我们就一直在关注页面的性能问题。

在前面巨人们的身后每个人也有自己的一些页面性能的经验,本文主要是介绍页面加载事件和性能评价指标。

浏览器渲染页面

首先给一张直观图:

HTML页面性能指标

这是在网上找的一张图,虽然是用来描述 performance 的 API 但是也很好的描述了浏览器是怎么处理一个页面渲染的。

这是我们在 PC 时代考虑的浏览器性能,主要在服务端响应、文档下载、文档渲染三个阶段,性能优化大部分也集中在这三个阶段。 针对这部分的监控、分析非常的普遍了。

两个事件

DOMContentLoaded

MDN的解释:当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。

意思是HTML下载、解析完毕之后就触发。

load

MDN的解释:load 应该仅用于检测一个完全加载的页面 当一个资源及其依赖资源已完成加载时,将触发load事件。

意思是页面的html、css、js、图片等资源都已经加载完之后才会触发 load 事件。

四个指标

一般页面性能有四个常见的指标

白屏时间

指浏览器发起请求到开始显示第一个页面元素的时间。现代浏览器不会等待CSS树(所有CSS文件下载和解析完成) 和DOM树(整个body标签解析完成)构建完成才开始绘制,而是马上开始显示中间结果。所以经常在低网速的环境中, 观察到页面由上至下缓慢显示完,或者先显示文本内容后再重绘成带有格式的页面内容。

首屏时间

首屏时间(FirstScreen Time),是指用户看到第一屏,即整个网页顶部大小为当前窗口的区域,显示完整的时间。 常用的方法有,页面标签标记法、图像相似度比较法和首屏高度内图片加载法。

可交互时间

用户可以进行正常的点击、输入等操作,默认可以统计DOMContentLoaded事件发生的时间。

整页时间

整页时间(Page Load Time),页面所有资源都加载完成并呈现出来所花的时间,这个就是load事件发生的时间。

DevTools下的三个时间

在使用Google Chrome开发者工具的是,使用Network测试网络性能时候,下面有三个时间。

  • Finish: 1.31s -表示整个页面加载时间为640ms,包括load事件发生后还有一些异步资源也加载完成。
  • DOMContentLoaded: 329ms -发生在页面DOMContentLoaded事件的启动时间点,对应上图蓝色竖线。
  • Load: 1.25s -表示页面load事件的启动时间点,对应上图红色竖线。
0

使用cnpm淘宝镜像代替npm

介绍

安装NodeJS之后使用npm来安装包使用的是国外的地址,经常会出现超时错误,可以通过修改为国内的淘宝源来加速安装。

配置

临时使用

永久使用

直接配置

通过如下命令可以查看是否配置成功

如果需要恢复成原来的官方地址只需要执行如下命令:

使用cnpm

安装淘宝的cnpm,然后在使用时直接将npm命令替换成cnpm命令即可

然后安装时使用如下命令

 

0

如何写一个自己的 Chrome 谷歌浏览器插件?

前言

有的公司的网络不可以直接上外网,需要在一个 OA 管理网站上请求授权后有 2 小时连接外网的时间。所以需要每隔 2 小时去这个 OA 网站上点击一下按钮。那就可以写一个 JS 脚本来有事没事续一秒。

之前也曾预研过 Chrome 插件写法。于是学着写一个简单的插件。功能不复杂,也遇到了一些问题,在此记录一下。

Chrome 插件结构

mainfest.json 定义了插件的配置

backgroud 字段指明 background.js 为在后台永远默默执行的代码。content_scripts 字段指明当我们在地址栏打开 http://oa.com/* 匹配的网站时,它会去执行 content.js,相当于监听正则表达式匹配的网站。default_popup 字段指明点击插件按钮时弹出来的框的页面内容 popup.html,其实就是一个普通网页,如下所示,它需要单独的 popup.js 来进行交互。弹窗页面的 js 是打开后执行一次,生命周期和普通网页一样。

完成这个需求只需要打开一个 OA 网站的 tab 放在一边,在 content.js 里监听页面中的剩余时间,当剩余时间小于 N 分钟时,提交按钮事件就可以达到目的了。但这个按钮一天只能点 6 次,超过之后必须输入验证码。这时就无能为力了。

排期迭代

功能虽然简单,也要一步步来,分为三期迭代。

一期:跑通 Chrome 插件的例子,理解原理机制

二期:在插件弹窗页面实时显示访问开发网剩余时间;不需要验证码授权时,剩余时间小于阈值则自动授权

三期:需要验证码授权时,把验证码显示在弹窗里,提醒输入验证码后进行授权。后来发现这个功能不好做,验证码模块的 HTML 代码是写在 iframe 中的,这是一个跨域问题啊(敲黑板)!


主要逻辑

主要逻辑在后台代码 content.js 中,使用 setInterval 定时功能固定时间去检测访问情况。

比较奇怪的是单独直接打开 popup.html,它会调用 popup.js,里面也会执行 Ajax 请求 OA 网站,但会出现跨域错误。显然站点服务端是不支持跨域的。

那么写在插件里 JS 又是怎么达到目的的呢。那是因为 Chrome 插件是浏览器自产自销的,不受限于同源策略。

普通网页能够使用 XMLHttpRequest 对象发送或者接受服务器数据, 但是它们受限于同源策略. 扩展可以不受该限制. 任何扩展只要它先获取了跨域请求许可,就可以进行跨域请求。

这里的 Ajax 请求也会带上本地的 Cookie。


iframe 跨域问题

页面引用了单独的验证码模块,一旦使用 getElementById 类似的方法,就会出现

Blocked a frame with origin from accessing a cross-origin frame

的错误,stackoverflow 上也有讨论(http://stackoverflow.com/questions/25098021/securityerror-blocked-a-frame-with-origin-from-accessing-a-cross-origin-frame)。显然在不侵入验证码模块时,无法让两个窗口进行通信,HTML5 的 postMessage 方案也不行。

不过毕竟是 Chrome 的插件,还是有方法获取 iframe 的内容的:使用 content_scripts 的 all_frames = true 选项。content_scripts 是打开匹配的网站时,content.js 进行加载,获取到验证码后和 popup 弹窗进行通信,把提醒消息和验证码发到弹窗。弹窗手动输入验证码后发送消息到 content.js 发起授权。

0

为什么有npm又出现yarn?

npm的缺点

  • npm install就一个字。新项目拉取耗时非常长,删除node_modules,重新install的时候也是如此。
  • 同一个项目在安装时无法保持一致性。由于package.json文件中版本号的特点,下面三个版本号在安装的时候代表不同的含义。

“5.0.3”表示安装指定的5.0.3版本,“~5.0.3”表示安装5.0.X中最新的版本,“^5.0.3”表示安装5.X.X中最新的版本。这就会出现同一个项目,有的同事是OK的,有的同事会由于安装的版本不一致出现bug。

  • 安装的时候,包会在同一时间下载和安装,中途某个时候,一个包抛出了一个错误,但是npm会继续下载和安装包。因为npm会把所有的日志输出到终端,有关错误包的错误信息就会在一大堆npm打印的警告中丢失掉,并且你甚至永远不会注意到实际发生的错误

正是因为npm有这些问题,所以yarn诞生了。

Yarn的优点

  • 速度快 。速度快主要来自以下两个方面:
  1. 并行安装:无论 npm 还是 Yarn 在执行包的安装时,都会执行一系列任务。npm 是按照队列执行每个 package,也就是说必须要等到当前 package 安装完成之后,才能继续后面的安装。而 Yarn 是同步执行所有任务,提高了性能。
  2. 离线模式:如果之前已经安装过一个软件包,用Yarn再次安装时之间从缓存中获取,就不用像npm那样再从网络下载了。
  • 安装版本统一:为了防止拉取到不同的版本,Yarn 有一个锁定文件 (lock file) 记录了被确切安装上的模块的版本号。每次只要新增了一个模块,Yarn 就会创建(或更新)yarn.lock 这个文件。这么做就保证了,每一次拉取同一个项目依赖时,使用的都是一样的模块版本。npm 其实也有办法实现处处使用相同版本的 packages,但需要开发者执行 npm shrinkwrap 命令。这个命令将会生成一个锁定文件,在执行 npm install 的时候,该锁定文件会先被读取,和 Yarn 读取 yarn.lock 文件一个道理。npm 和 Yarn 两者的不同之处在于,Yarn 默认会生成这样的锁定文件,而 npm 要通过 shrinkwrap 命令生成 npm-shrinkwrap.json 文件,只有当这个文件存在的时候,packages 版本信息才会被记录和更新。
  • 更简洁的输出:npm 的输出信息比较冗长。在执行 npm install <package> 的时候,命令行里会不断地打印出所有被安装上的依赖。相比之下,Yarn 简洁太多:默认情况下,结合了 emoji直观且直接地打印出必要的信息,也提供了一些命令供开发者查询额外的安装信息。
  • 多注册来源处理:所有的依赖包,不管他被不同的库间接关联引用多少次,安装这个包时,只会从一个注册来源去装,要么是 npm 要么是 bower, 防止出现混乱不一致。
  • 更好的语义化: yarn改变了一些npm命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰。

Yarn和npm命令对比

npm yarn
npm install yarn
npm install react –save yarn add react
npm uninstall react –save yarn remove react
npm install react –save-dev yarn add react –dev
npm update –save yarn upgrade

npm5.0的改进

有了yarn的压力之后,npm做了一些类似的改进。

  1. 默认新增了类似yarn.lock的 package-lock.json;
  2. git 依赖支持优化:这个特性在需要安装大量内部项目(例如在没有自建源的内网开发),或需要使用某些依赖的未发布版本时很有用。在这之前可能需要使用指定 commit_id 的方式来控制版本。
  3. 文件依赖优化:在之前的版本,如果将本地目录作为依赖来安装,将会把文件目录作为副本拷贝到 node_modules 中。而在 npm5 中,将改为使用创建 symlinks 的方式来实现(使用本地 tarball 包除外),而不再执行文件拷贝。这将会提升安装速度。目前yarn还不支持。

总结

不管是npm5.0还是yarn,甚至是pnpm,cnpm都是可以尝试使用的。

0

vue更新obj类data的属性无效,页面data没刷新解决方法vue.set

问题描述

Vue的data使用有坑啊,它不能直接修改创建的对象的属性,例如想要给 user 添加一个 name 属性,值是 Jay 。

先来一个添加的错误示例(这是一个大坑,请注意),这样写页面不渲染,但是属性添加到了user对象,所以不会报错。

作为一个后端开发,被这个问题困扰了一下午,-_-||

下面介绍几种正确有效的写法

解决方法一

强制刷新数据。 这里用了 $forceUpdate() ,它可以强制刷新数据。

解决方法二

重写整个对象。因为在 data 里面创建了 user 对象,可以直接修改它,缺点是得重写整个对象。

解决方法三

重要知识点。Vue.set 方法。用于设置对象的属性,它可以解决 Vue 无法检测添加属性的限制,语法格式如下:

参数说明
  • target: 可以是对象或数组
  • key : 可以是字符串或数字
  • value: 可以是任何类型
使用代码示例

在Vue中,一般只有在data选项中声明的属性(或者是属性的属性)才是具有响应特性的。如果需要在data选项之外对已有属性添加(Vue 不允许动态添加根级响应式属性)具有响应特性的属性,需要用到Vue的set方法。

Vue文档中的例子

上例中的a就是在data中声明的具有响应特性的属性,而b就不是。

把上面的例子修改一下

在实际操作中,上例的a2虽然不是响应式的,但他却是可以在HTML部分被渲染更新出来。这里就是一个比较容易掉进去的坑了。由于Vue是异步执行DOM更新,虽然更新的动作是由this.a.a1 = “test”触发,可动作的完成是在this.a.a2 = “testtest”之后。

总结

最后我是用this.$set(this.a, ‘bb’, 121);这种方法来解决页面data属性没刷新的问题。

0