沉醉在生命的优美。看着星,想象你本身跟它们在奔驰。——哲学家,马克·奥勒留javascript
性能始终在时间与空间上相互权衡取舍,计算机系统的优化须要借助各类缓存策略,从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
我想起了一句话,简单的概念复杂化,通俗的概念神秘化,这是为了展现本身的不凡,😆,开个玩笑。相信大多人看到这些概念是蒙的,咱们只须要围绕一个概念:缓存 ,而且是策略性的,存什么是能够控制的,也给咱们开发离线应用提供了思路。api
还记得那个 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
定义了标准统一API,咱们来看如何借助它提供的API逐步优化项目
在 Workbox
中,最核心的概念要数基于路由的策略缓存了,这里抓住两个关键词,基于路由、策略 。接下来的重点即是放在如何基于路由,如何体现策略。
前端的大多资源都是经过 HTTP
请求得来的,包括 js
、css
、 图片等等,既然这些内容都须要请求,那我能不能在请求发出后,作一些处理呢?就像房东租房,房东与租客之间的信息多是不对称的,这时中介出现了,它可以在房东出租房子以前作一些处理,好比加收中介费。网页在发起资源请求时,咱们也能够作一些决定,是从缓存拿,仍是去请求。而针对不一样的资源,正是经过资源请求地址来实现的,这即是__基于路由__,示例以下
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,
})
);
复制代码
首先安装 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 || []);
复制代码
到这里,能想象经过咱们对于项目中资源的配置,支持离线访问吗?经过这些配置可以极大提高应用性能,策略,你要的才是最美的。
我是合一,英雄再会!