你的web应用支持离线访问和策略缓存吗?

沉醉在生命的优美。看着星,想象你本身跟它们在奔驰。——哲学家,马克·奥勒留javascript

  • 微信公众号 《JavaScript全栈
  • 掘金 《合一大师
  • Bilibili 《合一大师

性能始终在时间与空间上相互权衡取舍,计算机系统的优化须要借助各类缓存策略,从CPU到内存,从接口到外设。若是有一天,硬件成本和实现难度再也不是阻碍,也许便没有了“优化”这个字眼。css

当下,前端面临的优化与挑战更多,复杂的终端环境,各类不一样的浏览器内核,尺寸不一的浏览设备,兼容要作。复杂不稳定的网络环境,愈来愈多的资源,优化要作。对于缓存,咱们并不陌生,可是咱们想有主观意识的缓存,我想缓存什么,缓存多久,缓存和请求资源的策略是什么都有本身来定,service worker 能帮咱们作到。html

使用 service worker 前,须要建立一份注册文件,不妨在项目下建立一个名为 sw.js 的文件前端

console.log('Hello, I am sw.js file')
复制代码

而后在应用中经过这个文件进行注册,经过如下代码就能完成应用中 service worker 的注册,后面关于 service worker 相关的处理,在 sw.js 文件中进行java

<script> // 检查当前浏览器是否支持service workers if ('serviceWorker' in navigator) { // 确保资源加载完成,再注册service worker window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js'); }); } </script>
复制代码

刷新页面,就能看到控制台打印了这句话,表示 service worker 注册成功webpack

打开控制台 Application ,一切在掌控之中, service worker 注册成功web

到这里完成了,完成了 service worker 的注册,关于其相关的配置和处理,咱们一块儿去 sw.js 文件中定义吧!正则表达式

Google推出的、标准统一api操做的、基于 service worker 的策略缓存库,它有一下几点让人称赞的特色npm

  1. Precaching
  2. Runtime caching
  3. Strategies
  4. Request routing
  5. Background sync
  6. Helpful debuggin
  7. Greater flexibility and feature set than sw-precache and sw-toolbox

我想起了一句话,简单的概念复杂化,通俗的概念神秘化,这是为了展现本身的不凡,😆,开个玩笑。相信大多人看到这些概念是蒙的,咱们只须要围绕一个概念:缓存 ,而且是策略性的,存什么是能够控制的,也给咱们开发离线应用提供了思路。api

使用Workbox

还记得那个 sw.js 文件吗?如今咱们把中心放在它身上,由于后续相关的操做要在这个文件中进行,ready?go!

###导入Workbox

首先在 sw.js 第一行导入 workbox.js 语法以下

importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js');
复制代码

这样就导入成功了吗?写段代码测试一下吧!

if (workbox) {
  console.log(`Yay! Workbox is loaded 🎉`);
} else {
  console.log(`Boo! Workbox didn't load 😬`);
}
复制代码

更改完成后,回到浏览器,此时刷新浏览器没有任何变化,这里须要提醒一点,更改完 service worker 注册文件须要终止重启或者更新。

开始使用Workbox

Workbox 定义了标准统一API,咱们来看如何借助它提供的API逐步优化项目

路由请求定义缓存

Workbox 中,最核心的概念要数基于路由的策略缓存了,这里抓住两个关键词,基于路由策略 。接下来的重点即是放在如何基于路由,如何体现策略。

前端的大多资源都是经过 HTTP 请求得来的,包括 jscss 、 图片等等,既然这些内容都须要请求,那我能不能在请求发出后,作一些处理呢?就像房东租房,房东与租客之间的信息多是不对称的,这时中介出现了,它可以在房东出租房子以前作一些处理,好比加收中介费。网页在发起资源请求时,咱们也能够作一些决定,是从缓存拿,仍是去请求。而针对不一样的资源,正是经过资源请求地址来实现的,这即是__基于路由__,示例以下

workbox.routing.registerRoute(
  /\.js$/,
  …
);
复制代码

以上代码咱们定义了一个路由缓存策略,即:全部后缀为 .js 的请求都会进入该策略进行处理,那,咱们须要作什么处理呢?就会有针对匹配该路由的资源定义不一样的关于缓存的策略,好比,咱们要求指定资源 网络请求优先

workbox.routing.registerRoute(
  /\.js$/,
  new workbox.strategies.NetworkFirst()
);
复制代码

此时若是在项目中引入了js文件,这个缓存便会生效,假设项目引入 hello.js

console.log('hello js file')
复制代码

在html中引入

<script src="./hello.js"></script>
复制代码

来到浏览器首先update一下service worker,方法上面介绍过这里不赘述。紧接着刷新,咱们能够看到打印的日志,说明配置成功

万事开头难,咱们已经克服这第一道难题了,接下来先横向拓展,针对不一样类型文件的配置,选用不一样策略。咱们先来看处理不一样文件的配置,很简单

字符串方式
workbox.routing.registerRoute(
    '/logo.png',
    handler // handler 是作缓存策略的回调函数,一般指后面所会降到的 '缓存策略函数'
);
workbox.routing.registerRoute(
    'https://some-host/some-path/logo.png',
    handler
);
复制代码
正则表达式
workbox.routing.registerRoute(
  // 缓存图片.
  /\.(?:png|jpg|jpeg|svg|gif)$/,
  handler
);
复制代码
函数形式
// 经过函数来匹配请求路由
const matchFunction = ({url, event}) => {
    // 若是请求路由匹配了就返回 true,也能够返回一个参数对象以供 handler 接收处理
    return false;
};

workbox.routing.registerRoute(
    matchFunction,
    handler
);
复制代码

上面代码的handler是workbox提供的缓存策略API,经常使用的有如下几种

策略名 API
staleWhileRevalidate 当请求的路由有对应的 Cache 缓存结果就直接返回,在返回 Cache 缓存结果的同时会在后台发起网络请求拿到请求结果并更新 Cache 缓存,若是原本就没有 Cache 缓存的话,直接就发起网络请求并返回结果
networkFirst 网络优先的策略
cacheFirst 直接从 Cache 缓存中取得结果,若是 Cache 缓存中没有结果,那就会发起网络请求,拿到网络请求结果并将结果更新至 Cache 缓存,并将结果返回给客户端
networkOnly 强制使用正常的网络请求
cacheOnly 直接使用 Cache 缓存的结果

通常场景下,以上5种策略基本能知足要求,若是还有不知足的状况,可自定义策略

workbox.routing.registerRoute(
    ({url, event}) => {
        return {
            name: 'workbox'
        };
    },
    ({url, event, params}) => {
        // 返回的结果是:A guide on workbox
        return new Response(
            `I am ${params.name}`
        );
    }
);
复制代码

如下给出一个示例,介绍不一样策略的使用方法

例如,图片类资源,由于不太常更改,因此能够选用优先缓存策略,并为该类资源分组,具体内容能够在 Application -> Cache 查看

workbox.routing.registerRoute(
  /\.(?:png|jpg|jpeg|svg|gif)$/,
  new workbox.strategies.CacheFirst({
    cacheName: 'my-image-cache',
  })
);
复制代码

js等相关文件能够适当选择网络优先

workbox.routing.registerRoute(
  /\.html$/,
  new workbox.strategies.NetworkFirst()
);

workbox.routing.registerRoute(
  /\.js$/,
  new workbox.strategies.NetworkFirst({
    networkTimeoutSeconds: 3,
  })
);
复制代码

webpack中使用workbox

首先安装 workbox-webpack-plugin ,选择使用npm安装

npm install --save-dev workbox-webpack-plugin
复制代码

在webpack配置文件中配置该插件

const workboxPlugin = require('workbox-webpack-plugin');

// ...
webpack({
    plugins: [
        // ...
        new workboxPlugin({
            swSrc: './src/sw.js',
            swDest: './dist/sw.js',
            globDirectory: './dist/',
            globPatterns: ['**/*.{html,js,css}'],
        })
    ]
    // ...
});
复制代码

使用 workbox 提供的 Webpack 插件必须在 app/sw.js 中包含如下代码才能完成预缓存内容列表注入工做

workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
复制代码

到这里,能想象经过咱们对于项目中资源的配置,支持离线访问吗?经过这些配置可以极大提高应用性能,策略,你要的才是最美的。

我是合一,英雄再会!

相关文章
相关标签/搜索