约 1222 字
预计阅读 3 分钟
解决Swup导致的JavaScript加载失效问题
2024-07-26
博客
AI 摘要
109酱

各位老友们好,我是 Chlorine。本期又是前端小白的魔改历险记。

我目前使用的主题 Efímero 是我基于 Hugo Landscape 的魔改版本。Landscape 使用 Swup 作为页面的过渡,平滑的效果深得我心。

但是在我的网站使用过程中遇到了一个很烦人的问题:有一些功能常常加载不出来,比方说说说页面、代码一键复制、评论等等。奇怪的是,刷新一次就好了。

之前我并没怎么在意这件事。但是由于今天太闲且强迫症作祟,我就想着修复一下。

我的切入点是我的说说页面 whisper.html。我相当肯定问题在 JavaScript 部分(毕竟 HTML 和 CSS 能有什么坏心思捏),然而凭借我有限的知识看了半天还是无果,AI 也不行。

我打开了控制台,发现在初次加载的时候,报出了错误:

Hooks.ts:435 Error in hook 'page:view': ReferenceError: init is not defined
    at VM35:6:36
    at index.ts:37:2
    at new Promise (<anonymous>)
    at Hooks.ts:433:8
    at index.ts:37:31
    at Hooks.ts:435:26
    at t (Hooks.ts:438:6)

whisper/:1385 Uncaught ReferenceError: init is not defined
    at HTMLDocument.<anonymous> (whisper/:1385:101)

看起来有一个神秘的 init 没有定义。我相当肯定我的 whisper 中没有什么 init,但是问题都摆在眼前了,总不能摆烂(还真能)。

前往定义,在挖呀挖呀挖了半天后,终于发现了一个所谓的 init

const swup = new Swup({
        plugins: [new SwupPreloadPlugin()]
    });
document.readyState === "complete" ? init() : document.addEventListener("DOMContentLoaded", ()=>init()),
swup.hooks.on("page:view", ()=>init())

嘶,好像有点熟,但是也就是有点熟,然后就没有然后了。

试着在项目里搜索这段代码,还真有,在 baseof.html 中。这看起来是创建了一个 JavaScript 的 swup 实例。把 init 去掉,发现不报错了,但是还是不行;随便写一个 init,发现还是没用。

中间经过了多少稀奇古怪的尝试我已经忘了。不过我是一点不慌,别问,问就是 Git 配享太庙。

一筹莫展之际,我又仔细翻了翻代码,发现了个正常到不能再正常的事情,就是 document.addEventListener。我不太了解 JavaScript,但是前几天写 Java+XML 的经验让我大致能猜出其意思。二者的绑定方式还有点像。

嗯?既然 document.addEventListener 是在页面加载完的时候进行,那如果页面没加载完呢?更进一步,如果根本没加载呢?

听上去荒谬,但是我瞬间来精神了。Swup 能做到切换这么丝滑,难道是根本没加载新的页面,只是做了点替换?

说干就干,我在我的 HTML 顶端加了条测试语句:

<script>
    console.log("whisper.html");
</script>

然后重启本地服务器,打开控制台……果然没打印!

破案了家人们,这个 Swup 根本没加载新的页面——至少是没加载新页面的 JavaScript。而刷新会强制加载这个页面,所以就好使了;而前面的 baseof 的代码,就是让 Swup 接管这些加载活动。

那下面就想办法解决好了。我翻了半天,在这里找到了解决方法(准确来说是被 issue 引过去的)。琢磨了一会儿,我决定采取省事的 Script Plugin。至于内存泄漏,算了先不管了。

<script src="https://unpkg.com/@swup/scripts-plugin@2"></script>
{{/* ... */}}
<script data-swup-ignore-script>
    document.addEventListener('DOMContentLoaded', function() {
        const swup = new Swup({
            plugins: [
                new SwupPreloadPlugin(),
                new SwupScriptsPlugin()
            ]
        });
    });
</script>

速度慢的话可以自己去找镜像。

其他部分都好了,就是这个评论还是不行。找了半天,发现是按钮本身绑定的 JavaScript 的事情。

首先把 Twikoo 的 CDN JavaScript 单独拎出来加载,然后再加一个钩子:

swup.hooks.on('page:view', () => {
    const loadCommentsBtn = document.getElementById('load-comments-btn');
    if (loadCommentsBtn) {
        loadCommentsBtn.addEventListener('click', function () {
            const container = document.getElementById('comments-container');
            if (container) {
                container.style.display = 'block'; // 显示评论容器
                this.style.display = 'none'; // 隐藏按钮
            }
        });
    }
});

目前这个方案虽然还不完善,但是已经可以用了。

本来打算明天在高铁上写的,但是太过激动,今天就写出来了。

明天大作业验收啦……祝我好运!

解决Swup导致的JavaScript加载失效问题
https://www.yoghurtlee.com/swup-modifying/
作者
Chlorine
发布于
2024-07-26