PWA开发中遇到的坑:缓存策略会导致 URL 参数的问题,和中文可能乱码的问题(二)

技术文摘1年前 (2023)更新 8KMM
7.4K 0 0

 花了半天时间, 开发出了wordpress版的pwa应用。 没有借助其它组件, 比如没有使用wp service work插件。全靠纯手工,


实现pwa的步骤:

  1. 注册 Service Worker:在 JavaScript 文件中编写一个 Service Worker 的注册脚本,以便在页面加载时进行注册。例如:
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js').then(function(registration) {
      console.log('Service worker registered with scope: ', registration.scope);
    }, function(err) {
      console.log('Service worker registration failed: ', err);
    });
  });
}

2. 编写 Service Worker 脚本:在 sw.js 文件中编写 Service Worker 的逻辑和功能代码,包括缓存资源、拦截网络请求、离线访问等功能。例如:

Copy Code

'use strict';


const currentCache ='s_cache_0910v1';
const CACHE_FILES = [
"https://www.8kmm.com/img/8kmm.css",
"https://www.8kmm.com/img/8kmm.js",
"https://www.8kmm.com/img/logo_315_80_w.png",
"https://www.8kmm.com/img/logo_315_80.png",
"https://www.8kmm.com/img/logo_200.png",
"https://www.8kmm.com/wp-content/themes/onenav/css/style.min.css",
"https://www.8kmm.com/wp-content/themes/onenav/js/lazyload.min.js",
"https://www.8kmm.com/wp-content/themes/onenav/js/theia-sticky-sidebar.js",
"https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/fancybox/3.5.7/jquery.fancybox.min.js",
"https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/fancybox/3.5.7/jquery.fancybox.min.css",
"https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-ms/bootstrap/4.6.1/js/bootstrap.min.js",
"https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-ms/bootstrap/4.6.1/css/bootstrap.min.css",
"https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/Swiper/7.4.1/swiper-bundle.min.css",
"https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.5.1/jquery.min.js",
"https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jqueryui/1.12.1/jquery-ui.min.js",
"https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js",
"https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/Swiper/7.4.1/swiper-bundle.min.js",
"https://cdn.staticfile.org/popper.js/1.16.0/umd/popper.min.js",
"https://www.8kmm.com/wp-content/themes/onenav/images/bg2.svg",
"https://www.8kmm.com/wp-content/themes/onenav/images/b.cur",
"https://www.8kmm.com/wp-content/themes/onenav/images/a.cur",
"https://www.8kmm.com/wp-content/themes/onenav/css/fonts/iconfont.woff2",
"https://at.alicdn.com/t/font_2102415_t3lkts5zst.woff2",
'https://www.8kmm.com/wp-content/themes/onenav/css/iconfont.css',
'https://at.alicdn.com/t/font_2102415_t3lkts5zst.css',
"https://www.8kmm.com/wp-content/themes/onenav/js/html5.min.js",
"https://www.8kmm.com/wp-content/themes/onenav/js/app.min.js",
"https://www.8kmm.com/wp-includes/js/wp-embed.min.js",
"https://www.8kmm.com/img/r12.jpg",
"https://www.8kmm.com/img/r2.jpg",
"https://www.8kmm.com/img/r3.jpg",
"https://www.8kmm.com/img/r1.jpg",
"https://www.8kmm.com/img/r4.jpg",
"https://www.8kmm.com/img/r7.jpg",
"https://www.8kmm.com/img/r8.jpg",
"https://i.8kmm.com/2022/04/808.png",
"https://i.8kmm.com/2021/04/475eb-e40c5-6f662-6aff0-49ec4-6293f-33930-3f31b-322aa-3d2a2-9e15a-5fda4-c209a-d20d4-cefd7-QQ%E6%88%AA%E5%9B%BE20210217214526.png",
"https://i.8kmm.com/2021/04/beace-e6e3f-79c56-db1d9-b7cb8-73c5a-826cb-edda7-9fe51-73fcd-b556b-6248f-5eddc-28ddd-94522-88_911_6d6ed16888d04b62dc93951aee3e754a_641fff0c51fcce8f88eb2d8f75568c33.png",
"https://i.8kmm.com/2020/09/cropped-favicon-32x32.png",
"https://i.8kmm.com/2020/09/cropped-favicon-192x192.png",
"https://i.8kmm.com/2020/09/cropped-favicon-180x180.png",
"https://i.8kmm.com/2020/09/cropped-favicon-270x270.png",
"https://www.8kmm.com/img/logo_315_80_2.png",
"https://www.8kmm.com/wp-content/uploads/avatars/2.jpg?_=1640833906",
"https://www.8kmm.com/wp-content/themes/onenav/images/favicon.png",
"https://i.8kmm.com/2021/03/20200616174016.png",
'https://img.alicdn.com/tps/i3/T1OjaVFl4dXXa.JOZB-114-114.png',
'https://www.8kmm.com/2020/logo/20200921092954.png',
'https://i.8kmm.com/2022/01/maxthon_pic.jpg',
'https://www.8kmm.com/2020/logo/20200923141056.png',
'https://i.8kmm.com/2021/12/2Q__.jpg',
'https://www.8kmm.com/2020/logo/20200918215609.png',
'https://www.8kmm.com/2020/logo/20200918213938.png',
'https://i.8kmm.com/2021/11/www.91cha.jpg',
'https://i.8kmm.com/2021/03/20200921105914.png',
'https://www.8kmm.com/2020/logo/wxlogo.jpg',
'https://i.8kmm.com/2021/03/tt0.top-QQ%E5%9B%BE%E7%89%8720210323213527.png',
'https://www.8kmm.com/2020/logo/20200921092732.png',
'https://www.8kmm.com/2020/logo/20200921110336.png',
'https://i.8kmm.com/2022/01/20200616174757.png',
'https://i.8kmm.com/2021/05/20210519072205_102ac2843906.png',
'https://www.8kmm.com/2020/logo/20200921110416.png',
'https://www.8kmm.com/2020/logo/20200921104849.png',
'https://www.8kmm.com/2020/logo/20200925161108.png',
'https://www.8kmm.com/2020/logo/20200921092813.png',
'https://www.8kmm.com/2020/logo/20200922150608.png',
'https://www.8kmm.com/2020/logo/20200922150453.png',
'https://www.8kmm.com/2020/logo/20200921093640.png',
'https://www.8kmm.com/2020/logo/20200918203121.png',
'https://www.8kmm.com/2020/logo/20200922145319.png',
'https://www.8kmm.com/2020/logo/20200918204421.png',
'https://www.8kmm.com/2020/logo/20200918221117.png',
'https://www.8kmm.com/2020/logo/20200918220103.png',
'https://www.8kmm.com/2020/logo/20200922170039.png',
'https://i.8kmm.com/2021/03/logo.png',
'https://www.8kmm.com/2020/logo/lolsodu.png',
'https://i.8kmm.com/inter-v7-latin-500.woff2',
'https://i.8kmm.com/inter-v7-latin-700.woff2',
'https://i.8kmm.com/inter-v7-latin-600.woff2',
'https://at.alicdn.com/t/c/font_3738566_6w51ry967on.woff',
'https://i.8kmm.com/inter-v7-latin-regular.woff2'
];


self.addEventListener('install', e => {
  self.skipWaiting();
  e.waitUntil(
    caches.open(currentCache)
      .then(cache => {
        const cachePromises = CACHE_FILES.map(url => {
          const request = new Request(url);
          return fetch(request)
            .then(response => {
              if (response.status === 200) {
                const clonedResponse = response.clone();
                const headers = new Headers(response.headers);
                const now = new Date();
                const expiresDate = new Date(now.getTime() + 2 * 3600 * 1000); // 设置为 2 小时过期
                headers.set('Expires', expiresDate.toGMTString());
                return cache.put(request, new Response(clonedResponse.body, { status: response.status, headers }));
              } else {
                throw new Error(`Failed to get ${url} (${response.status})`);
              }
            })
            .catch(err => console.error(err));
        });
        return Promise.all(cachePromises);
      })
  );
});




self.addEventListener('activate', e => {
e.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== currentCache) {
return caches.delete(cacheName);
}
})
);
})
);
});

self.addEventListener('fetch', event => {
  const request = event.request;
  
  // 处理 /user/index 的请求
  if (request.url.includes('/user/')||request.url.includes('/wp-admin/')) {  
    return event.respondWith(fetch(request)); // 直接返回请求结果,不进行缓存
  }
  

  // 检查请求是否为 bookmark 页面
  if (request.url.includes('/bookmark/')) {
    const url = new URL(request.url);

    // 检查 URL 是否包含查询参数
    if (url.search) {
      // 编码查询参数后再进行 fetch
      const encodedUrl = url.origin + url.pathname + encodeURI(url.search);
      return event.respondWith(fetchWithRedirects(encodedUrl));
    }
  }
  
  //如果访问了下面的页面,则清空缓存
  if (event.request.url.includes('/wp-login.php') || event.request.url.includes('/wp-login.php?action=logout')|| event.request.url.includes('/login/')|| event.request.url.includes('/wp-admin/')|| event.request.url.includes('/user/')) {
        event.waitUntil(
            caches.keys().then(function(cacheNames) {
                return Promise.all(
                    cacheNames.map(function(cacheName) {
                        return caches.delete(cacheName);
                    })
                );
            }).then(function() {
                return self.clients.matchAll();
            }).then(function(clients) {
                clients.forEach(function(client) {
                    client.navigate(client.url);
                });
            })
        );
    }
    
    

    // 其他处理逻辑不变
  // 检查请求方法是否为 GET
  if (request.method === 'GET') {
    event.respondWith(
      caches.match(request)
      .then(response => {
        if (response) {
          return response;
        }

        return fetch(request)
        .then(response => {
          // 如果请求成功,则缓存响应结果
          if (response && response.status === 200) {
            const clonedResponse = response.clone();
            caches.open(currentCache).then(cache => {
              cache.put(request, clonedResponse);
            });
          }

          return response;
        })
        .catch(() => {
          return caches.match('/offline.html');
        });
      })
    );}
 
});

async function fetchWithRedirects(requestUrl) {
  let response;
  let redirects = [];

  do {
    response = await fetch(requestUrl, { redirect: 'manual' });

    if (response.status === 301 || response.status === 302) {
      // 获取重定向目标 URL 并记录
      const redirectUrl = new URL(response.headers.get('location'), requestUrl);
      redirects.push(redirectUrl.href);

      // 更新 requestUrl
      requestUrl = redirectUrl.href;
    }
  } while (response.status === 301 || response.status === 302);

  // 响应是否为重定向,如果是则应用重定向
  if (redirects.length > 0) {
    caches.open(currentCache).then(cache => {
      cache.put(requestUrl, response.clone());
    });
    return Response.redirect(redirects[redirects.length - 1], 302);
  }

  // 响应不是重定向,则正常处理
  const cache = await caches.open(currentCache);
  cache.put(requestUrl, response.clone());
  return response;
};

3. 编写 Web App Manifest:在 HTML 文件中添加 Web App Manifest 的 meta 标签,包括应用名称、图标、启动页面等信息。例如:

Copy Code
<link rel="manifest" href="/manifest.json">

4. 编写 Web App Manifest 文件:在 manifest.json 文件中编写 Web App Manifest 的具体信息,例如:

Copy Code
{
  "name": "My PWA",
  "short_name": "MyPWA",
  "start_url": "/index.html",
  "display": "standalone",
  "icons": [
    {
      "src": "images/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "images/icon-96x96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "images/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "images/icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "images/icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "images/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "images/icon-256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "images/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "theme_color": "#3367D6",
  "background_color": "#3367D6"
}

 

遗留问题, fetch下面的判断, 存在优化空间。

 

 

 

© 版权声明

相关文章

文章目录

    暂无评论

    暂无评论...