惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Vercel News
Vercel News
SecWiki News
SecWiki News
WordPress大学
WordPress大学
小众软件
小众软件
博客园 - 司徒正美
酷 壳 – CoolShell
酷 壳 – CoolShell
V
Visual Studio Blog
Y
Y Combinator Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
云风的 BLOG
云风的 BLOG
MyScale Blog
MyScale Blog
K
Kaspersky official blog
T
The Exploit Database - CXSecurity.com
腾讯CDC
Scott Helme
Scott Helme
I
InfoQ
Cyberwarzone
Cyberwarzone
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Security Latest
Security Latest
The Register - Security
The Register - Security
Project Zero
Project Zero
F
Fortinet All Blogs
C
CERT Recently Published Vulnerability Notes
A
Arctic Wolf
C
Cisco Blogs
L
LINUX DO - 热门话题
P
Privacy International News Feed
IT之家
IT之家
U
Unit 42
P
Privacy & Cybersecurity Law Blog
H
Help Net Security
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Palo Alto Networks Blog
F
Full Disclosure
宝玉的分享
宝玉的分享
Simon Willison's Weblog
Simon Willison's Weblog
L
Lohrmann on Cybersecurity
Google DeepMind News
Google DeepMind News
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
H
Hacker News: Front Page
Know Your Adversary
Know Your Adversary
PCI Perspectives
PCI Perspectives
Hugging Face - Blog
Hugging Face - Blog
AWS News Blog
AWS News Blog
MongoDB | Blog
MongoDB | Blog
S
Schneier on Security
Recent Announcements
Recent Announcements
Forbes - Security
Forbes - Security
Cisco Talos Blog
Cisco Talos Blog

蚊子的前端博客

微说 | 有的人觉得只要不考XX,一定能考好!-蚊子的前端博客 微说 | 春天来了-蚊子的前端博客 明天和意外不知道哪个先来-蚊子的前端博客 微说 | 既然错过了路口,就及时止损,重新规划路线上路-蚊子的前端博客 微说 | 2025年的出生人口数是792万-蚊子的前端博客 微说 | 工作年终总结,让写对接的接口的数量?-蚊子的前端博客 微说 | 温家宝:没有政治体制改革的成功 经济体制改革不可能进行到底-蚊子的前端博客 微说 | 违法犯罪了该不该被禁言?-蚊子的前端博客 微说 | 不明白为什么在推荐去俄罗斯旅游-蚊子的前端博客 微说 | 易中天论骗子-蚊子的前端博客 微说 | 一场大风吹散了秋天-蚊子的前端博客 微说 | 既要、又要、还要、更要!-蚊子的前端博客 又是一年的国庆雨季-蚊子的前端博客 微说 | 预估下2025年的出生人口数据-蚊子的前端博客 微说 | 可惜了我那些小时候的书本-蚊子的前端博客 微说 | 牛马有的是,驴不够了!-蚊子的前端博客 微说 | 能否有一条非户口也能高考的路-蚊子的前端博客 微说 | 小聊中医-蚊子的前端博客 微说 | 将要制作的一款新产品-蚊子的前端博客 微说 | 做人要有信-蚊子的前端博客 微说 | 好一个正义联盟-蚊子的前端博客 微说 | 都是见过吃过的主儿-蚊子的前端博客 微说 | 追求8小时工作制有错吗?-蚊子的前端博客 微说 | 如果尖锐的批评完全消失-蚊子的前端博客 微说 | 很好!-蚊子的前端博客 微说 | 封禁用户可以,但要告知具体原因-蚊子的前端博客 微说 | 面朝大海,春暖花开-蚊子的前端博客 微说 | 程序员的悲哀是什么?-蚊子的前端博客 微说 | 2025年出生人口的预测-蚊子的前端博客 前端在 LiveKit 中如何获取所有的参与者-蚊子的前端博客 在 Electron 中使用 LiveKit 实现屏幕共享-蚊子的前端博客 在 Electron 应用中,如何获取 Mac 的摄像头和麦克风权限-蚊子的前端博客 微说 | 不要总让台湾艺人表态-蚊子的前端博客 微说 | 他们总说要更开放-蚊子的前端博客 自己封装 uuid 踩的一个小坑-蚊子的前端博客 CKEditor5 光标在粘贴的图片下一行-蚊子的前端博客 软考出成绩了,没过-蚊子的前端博客 微说 | 也许有一天我们这个社会会进步-蚊子的前端博客 好久没有更新文章了-蚊子的前端博客 微说 | 中共中央关于进一步全面深化改革,推进中国式现代化的决定-蚊子的前端博客 微说 | 关于惩罚性赔偿-蚊子的前端博客 微说 | 生孩子是谁的事儿!-蚊子的前端博客 微说 | 给群众一些选择电视剧的空间-蚊子的前端博客 微说 | 活着-蚊子的前端博客 微说 | 借用睡前消息里面的一段话-蚊子的前端博客 微说 | 曾经梦寐以求的,现在却没了追求-蚊子的前端博客 微说 | 我小时候的那些书本-蚊子的前端博客 给博客添加了一个微说的功能-蚊子的前端博客 今年的双 11 很平静-蚊子的前端博客 微说 | 贪就是贪-蚊子的前端博客 微说 | 总有人说穿越小说为什么不发展工业和科技!-蚊子的前端博客 微说 | 花了很多时间和精力,-蚊子的前端博客 2025 年终于是增加了 2 天的假期-蚊子的前端博客 微说 | 这是我的第一条微说,-蚊子的前端博客 如何手写 Array 的 forEach 方法-蚊子的前端博客 看到聚美优品的没落,真是唏嘘-蚊子的前端博客 如何手写 Array 的 map 方法-蚊子的前端博客 秋意正浓时-蚊子的前端博客 收藏几个常用但访问比较慢的组件的官网网址-蚊子的前端博客 从 Axios 源码分析如何支持 fetch 方法的-蚊子的前端博客 1024,给博客评论区所有的头像戴上一顶可爱的帽子-蚊子的前端博客 使用 GitHub 搭建了一个静态博客-蚊子的前端博客 在 JavaScript 如何判断变量是否为空-蚊子的前端博客 我为什么还在坚持我的个人博客-蚊子的前端博客 不要再手动拼接 URL 参数,请使用 URLSearchParams-蚊子的前端博客 使用 NodeJs 向百度资源推送链接-蚊子的前端博客 工具链极度内卷,留给开发者的性能优化手段已经不多了-蚊子的前端博客 在 React 中显示多个标签,超出省略并可以 hover 显示更多-蚊子的前端博客 蚊子的前端博客:探索与分享前端技术的奇妙之旅-蚊子的前端博客 互联网程序员前景真的一片黑暗吗?-蚊子的前端博客 Deno2.0 正式发布,向 Node.js 兼容-蚊子的前端博客 React 请求数据别再使用 useEffect 和 useState,试试 SWR 吧!-蚊子的前端博客 React 的 useEffect 的一些使用场景和技巧-蚊子的前端博客 前端趣闻之 JavaScript 语言的诞生和发展-蚊子的前端博客 如何合并同一接口的相同参数的请求-蚊子的前端博客 百度搜索中关于蚊子前端博客的奇怪的检索数据-蚊子的前端博客 使用 React 实现 todo list 的 curd 操作-蚊子的前端博客 React 模板中为什么可以用逻辑与运算符-蚊子的前端博客 评论回复在一张表里的评论系统如何进行分页-蚊子的前端博客 React 组件多次调用时如何区分不同的 div 容器-蚊子的前端博客 安全赋值运算符,再也不用写 try-catch 了-蚊子的前端博客 使用 nextjs 重构我的个人博客-蚊子的前端博客 基于 gitlab 的 webhook 向飞书发通知-蚊子的前端博客 数字转换为更高量级单位的工具方法-蚊子的前端博客 如何避免旧请求的数据覆盖掉最新请求-蚊子的前端博客 JavaScript 中 toString 的冷知识-蚊子的前端博客 React 中 useState 和 useRef 与全局变量的区别-蚊子的前端博客 从面试官的角度分析下简历中存在的问题-蚊子的前端博客 使用 React 实现 6 个输入框的短信验证码功能-蚊子的前端博客 反驳那些要实时刷新页面的前端部署方案-蚊子的前端博客 JSON stringify 的一些不常见使用-蚊子的前端博客 JavaScript 中数组 Array 的常见操作-蚊子的前端博客 前端如何提升用户的交互体验-蚊子的前端博客 没有日的日期在iOS中报 Invalid Date 的探究-蚊子的前端博客 飞书很好,但还是没抗住-蚊子的前端博客 给 Antd 的 DatePicker 组件实现带有至今的功能-蚊子的前端博客 antd 的 InputNumber 输入框添加左右的加减按钮-蚊子的前端博客 给想进国央企的同学介绍一款招聘软件「国聘」-蚊子的前端博客 基于 React 和 antd 实现的图片裁剪压缩功能-蚊子的前端博客 uniapp 中 checkbox 中的 checked 不生效的方案-蚊子的前端博客
service worker在新闻红包活动中的应用-蚊子的前端博客
author · 2019-02-26 · via 蚊子的前端博客

活动页面大多是单页面应用,加载js后,再通过js进行页面的渲染,因此js的加载速度直接影响了页面呈现的速度。这里是想通过service worker缓存静态资源,期望能直接从缓存中加载静态资源,加载页面的呈现速度

首先声明下我们组的技术负担:前端没有自己的服务器,是依托于新闻 CMS 发布系统的。在这种情况下如何将 service worker 应用在新闻红包活动中呢?

1. 技术支持程度 #

活动页面大多是单页面应用,加载 js 后,再通过 js 进行页面的渲染,因此 js 的加载速度直接影响了页面呈现的速度。这里是想通过 service worker 缓存静态资源,期望能直接从缓存中加载静态资源,加载页面的呈现速度!

news.qq.com域名全面支持 https 后,service worker 就可以提上日程了。首先进行技术支持程度的检测,使用'serviceWorker' in navigator检测功能的支持。在 iOS12.0 中,微信、QQ 和新闻客户端,均不支持 service worker,safari 支持;在 Android 中,微信、QQ 和新闻客户端都是支持的。

因此我们着重于 Android 下 service worker 的使用。同时,Android 测试版新闻客户端,可是使用 USB 进行调试,调试 service worker 的工作状态。

2. 活动中的使用 #

2.1 尝试缓存相对路径的静态资源 #

刚开始在缓存资源时,因为知识储备的不足,钻了牛角尖,只想着缓存相对路径的资源,毕竟 cms 静态服务也是支持静态资源的相对路径的,可是在实验时发现,无论字段iscdn是否为 true,图片类型的资源都会自动上传到 CDN,那么就会造成 js/css 的地址和图片资源的地址不一致,毕竟 baseUrl 只能指定一个值,要么是 js/css 地址,要么是图片资源的地址。

刚开始想的是改造脚手架,用两个值分别来表示 js/css 地址和图片资源地址,但是脚手架的改造成本也是很高的!

2.2 缓存 CDN 中的资源 #

代码架构中的资源都上传到 CDN,那么 js/css/img 都会在mat1.gtimg.com的 CDN 目录下,如果要加载并缓存 CDN 中的资源,CDN 资源服务器的 response 中 Access-Control-Allow-Origin 中包含当前的页面所在域或者为*;幸运的是,mat1.gtimg.com 服务器是支持的:

response:

access-control-allow-origin: https://news.qq.com
access-control-expose-headers: X-Client-Ip,X-Server-Ip,X-Upstream-Ip
cache-control: max-age=60
content-encoding: gzip
content-length: 50356
content-type: application/javascript; charset=utf-8
date: Tue, 15 Jan 2019 09:02:29 GMT
expires: Tue, 15 Jan 2019 09:03:29 GMT
last-modified: Tue, 15 Jan 2019 02:53:58 GMT
server: NWSs
status: 200
vary: Origin

因此我们可以在 install 中首先这个 CDN 下的静态资源进行离线缓存,然后在 fetch 中拦截请求,如果命中缓存则直接返回,如果没有命中,则去请求!在请求可控的跨域资源时,需要在请求头中加入{mode: 'cors'}

在 install 中,对首页和首页中一定会用到的静态资源进行缓存:

const version = 'welfare-1.0.0';
const fileList = [
  '/a/b/index.htm',
  'https://mat1.gtimg.com/news/chunk-vendors.f9bab06e.js',
  'https://mat1.gtimg.com/news/app.2677f99a.css',
  'https://mat1.gtimg.com/news/app.af990eeb.js',
];

this.addEventListener('install', (event) => {
  this.skipWaiting();
  event.waitUntil(
    caches.open(version).then((cache) => {
      return cache.addAll(fileList);
    }),
  );
});

然后在 fetch 中拦截:

// 检测当前请求是否应当被缓存
const checkHttpCanCache = (request, response) => {
  // 数据统计、请求的接口不缓存
  // 同时若请求失败或者请求的资源无法控制,也不缓存
  if (
    request.url.indexOf('btrace.qq.com/kvcollect') > -1 ||
    !response ||
    response.status !== 200 ||
    (response.type !== 'basic' && response.type !== 'cors')
  ) {
    return false;
  }
  return true;
};
this.addEventListener('fetch', event => {
  let url = event.request.url;
  let req;
  if (url.indexOf('mat1.gtimg.com') > -1) {
      req = new Request(url, { mode: 'cors' });
  } else {
      req = event.request.clone();
  }

  event.respondWith(
    caches.match(event.request).then(response => {
      // 缓存中存在则直接返回
      if (response) {
        return response;
      }

      // 否则进行请求并返回,这里还可以再多一步,如果可以缓存的资源,也进行缓存
      let request = req.clone();
      return fetch(request).then(httpRes => {
        if (!checkHttpCanCache(request, httpRes)) {
          return httpRes;
        }

        // 请求成功的话,将请求缓存起来
        let responseClone = httpRes.clone();
        caches.open(version).then(cache => {
          cache.put(request, responseClone);
        });

        return httpRes;
      });
    });
  );
});

不过上面的 fetch 事件还不完整,如果页面中有的跨域资源的Access-Control-Allow-Origin不支持时,请求资源就会报错,会被浏览器阻止。比如展示列表中的图片,产品经理那边是把图片上传到img1.gtimg.com域名上,但是这个域名的 Access-Control-Allow-Origin 不支持。

关于这个域名下的请求,是这样处理的,需要在 mode 中加上no-cors

if (url.indexOf('mat1.gtimg.com') > -1) {
  req = new Request(url, { mode: 'cors' });
} else if (url.indexOf('img1.gtimg.com') > -1) {
  req = new Request(url, { mode: 'no-cors' });
} else {
  req = event.request.clone();
}

2.3 验证 service woker 是否起作用 #

有时候会遇到这种情况,Cache Storage 中明明已经有缓存了,但是每次刷新时,缓存不起作用,还是每次都走网络请求。针对这种情况,应当检查下当前页面是否是https链接,同时检查 sw.js 所在的路径是否跟当前页面地址在同一个目录中,比如页面路径为https://news.qq.com/a/b/index.htm,那么 sw.js 的路径也最好是/a/b/sw.js

service worker 是否已生效,可以在 chrome 的 network 面板中查看,强刷缓存后,如果 Size 标识为(from ServiceWorker),则说明 sw 已生效;将网络设置为offline时,页面也依然能访问,service worker 中缓存的数据能把首页的大致框架撑起来,只是没有接口数据了而已!

network中的资源请求

3. 总结 #

service worker 能做的工作除了缓存资源,还有更多的功能可以使用,比如使用 service worker 模拟接口数据,在接口没有开发完成时,可以利用这个进行正常的对接接口开发等。