描述

如果你的网站同时配置了 PjaxPWA

那么在浏览网站时,地址栏则可能会出现意外的后缀。

后缀的内容与 PWAService Worker 的功能实现有关。

使用 workbox-build 的只有 index.html

使用 sw-precache 的类似于 index.html?_sw-precache=d65205fbf6be65ea9e136772f668efdb

分析

PWA

index.html

后缀中的 index.html 路径是根据其静态文件生成的。

通常这种情况,是想在链接中使用目录来访问指定页面。

例如 https://example.com/about/,而不是 https://example.com/about/index.html

但程序并不知道,所以在生成的 precache 清单里,都是带有 index.html 的路径。

_sw-precache

后缀中的 _sw-precache 参数是根据静态文件的内容,生成的 Hash 值。

作用是用来判断文件内容是否发生变化,以便及时更新缓存。

sw-precache 从缓存响应请求时,并没有去掉自己的参数。

workbox-build 虽然也加了参数,叫 __WB_REVISION__

不过从缓存响应请求时,会去掉自己的参数。

Pjax

如果没用 Pjax 的话,这个后缀是不会出现在地址栏的。

Pjax 在改变地址栏时,逻辑优先是响应地址。

所以地址栏就会出现这些后缀。

解决方法

使用 workbox-buildmanifestTransforms 选项。

对生成的清单进行变换,去掉路径中的 index.html,从根源上解决问题。

声明 removeIndex 方法,并在上述选项中引用。

以我用的 v2 版 hexo-offline 插件配置文件为例。

hexo-offline.config.cjs
1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
// 其他配置...
manifestTransforms: [removeIndex]
}

/** 移除 URL 末尾的 index.html */
async function removeIndex(manifestEntries) {
const manifest = manifestEntries.map(entry => {
entry.url = entry.url.replace(/(^|\/)index\.html$/, '/');
return entry;
});
return { manifest };
}

增加一段 Javascript 代码,用来劫持 Pjax 处理响应的方法。

request 对象中的响应地址修改为请求地址。

这里用到了 Object.defineProperty 方法,因为 request.responseURL 是只读变量,无法直接修改。

1
2
3
4
5
6
7
8
// 重定向浏览器地址
pjax.site_handleResponse = pjax.handleResponse;
pjax.handleResponse = function(responseText, request, href, options) {
Object.defineProperty(request, 'responseURL', {
value: href
});
pjax.site_handleResponse(responseText, request, href, options);
}

在Butterfly的具体操作

  1. 将上述代码保存到 source\js\modify.js

  2. 编辑 _config.butterfly.yml,增加以下代码到 inject.bottom 配置项。

    1
    <script defer type="text/javascript" src="/js/modify.js"></script>
  3. 修改完成后,配置类似如下。

    1
    2
    3
    4
    5
    6
    7
    8
    # Inject
    # Insert the code to head (before '</head>' tag) and the bottom (before '</body>' tag)
    # 插入代码到头部 </head> 之前 和 底部 </body> 之前
    inject:
    head:
    # - <link rel="stylesheet" href="/xxx.css">
    bottom:
    - <script defer type="text/javascript" src="/js/modify.js"></script>