小编在开发www.8kmm.com导航的PWA(Progressive Web Apps,渐进式 Web 应用)时遇到问题。
问题一: 在跳转时,遇到URL参数带中文后乱码;
问题二:在使用了PWA后, url带参数就会影响service works缓存问题。
特记录一下:
先解决问题二,顺便把问题一也解决了。
本站做为默认搜索引擎时,
https://s.8kmm.com?wd=测试
会301跳转到:
https://www.8kmm.com/bookmark/?wd=测试
这个时候,当主站www.8kmm.com启用了pwa时, 搜索跳过来就会报: 会提示:https://www.8kmm.com/bookmark/?wd=测试 的网页可能暂时无法连接,或者它已永久性地移动到了新网址。 ERR_FAILED,
注销掉“开发者工具”=》Serivce works中的工作进程就又可以。
思来想去, 应该是URL带了参数,会导致sw缓存出问题, 第一次访问是正常的, 第二次用同样的参数过来,就会报这个错,本质上问题是重定向到了新 URL,而缓存策略并没有正确地处理这种情况。在这种情况下,在fetch
事件中判断响应是否为重定向,并相应地进行处理,应该就能解决问题。
我们只需要判断在需要接收url参数的页面,进行单独处理:
self.addEventListener('fetch', event => {
const request = event.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));
}
}
// 其他处理逻辑不变
...
});
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;
}
这段代码检查了响应状态是否为 301 或 302,如果是则获取重定向目标 URL 并记录。然后更新requestUrl
,并循环进行fetch
,直到响应不再是重定向。最后,如果响应是重定向,会返回一个Response.redirect()
,并将响应存储在缓存中。
注意:const encodedUrl = url.origin + url.pathname + encodeURI(url.search); 中的encodeURI将中文编码,用于解决中文乱码的问题。
另外, 在使用PHP做301跳转时,如果出现中文乱码问题,可以使用
header(‘HTTP/1.1 301 Moved Permanently’);
header(‘Location: ‘ . $myurl);
header(‘Content-Type: text/html; charset=UTF-8’);
示例代码:
$myurl='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
if (isset($_GET['wd']) && $_GET['wd'] !== '') {
if (strpos($myurl, '?') === false) {
$myurl .= '?wd=' . urlencode($_GET['wd']);
} else {
$myurl .= '&wd=' . urlencode($_GET['wd']);
}
}
if (isset($_GET['t']) && $_GET['t'] !== '') {
if (strpos($myurl, '?') === false) {
$myurl .= '?t=' . urlencode($_GET['t']);
} else {
$myurl .= '&t=' . urlencode($_GET['t']);
}
}
header('HTTP/1.1 301 Moved Permanently');
header('Location: ' . $myurl);
header('Content-Type: text/html; charset=UTF-8'); //可在此处进行指定字符集操作。
exit;