Astro + Swup で addEventListener が追加できないときの対処法
2024-09-21 03:00 公開
swupとは
swupでは、ページの遷移アニメーションやページの事前ロードによる最適化ができます
カーソルを合わせた時やリンクが画面に入った時に事前ロードを発生させることで、表示を高速化できます
Astro + Swup の公式 Integration を使う
この Intergration
を使うと、Astroのページ遷移のアニメーションやプリロードが簡単に実現できます
インストール方法:
# pnpmの場合
pnpm install @swup/astro
// astro.config.mts
import { defineConfig } from 'astro/config'
import swup from '@swup/astro'
export default defineConfig({
integrations: [swup()], // swup() を追加
})
Swup で移動したときに addEventListener が無効になる
このようなコードで、Astroのページにメニューを追加していました (Astroコンポーネントの説明は省略します、公式ドキュメントを見てください)
<a id="open">
<Icon name="gravity-ui:dots-9" />
</a>
<div id="menu">
<h2>menu</h2>
<!-- メニューの内容 -->
<a id="close">
<Icon name="gravity-ui:xmark" />
</a>
</div>
<script>
import { gsap } from 'gsap'
function init() {
const open = document.getElementById('open')
open.addEventListener('click', () => {
gsap.to(menu, { display: 'block' })
})
}
init()
</script>
(classは省略しています)
このコンポーネントを各ページのLayoutに追加して使っていたのですが、ページを移動するとmenuが押せなくなる問題が発生しました
原因は、swupで移動した際にeventListener
が初期化されてしまうからであることはすぐに分かったのですが、swupの遷移を検知して再登録(つまりinit()
を実行)をするのにとても悩みました
解決策
結論から言うと、以下の方法でイベントの再登録ができました
<script>
import { gsap } from 'gsap'
function init() {
const open = document.getElementById('open')
open.addEventListener('click', () => {
gsap.to(menu, { display: 'block' })
})
}
init()
const setup = () => {
;(window as any).swup.hooks.on('page:view', init)
}
if ((window as any).swup) {
setup()
} else {
document.addEventListener('swup:enable', setup)
}
</script>
同時に、 astro.config.mts
で以下の設定を有効にします
import { defineConfig } from 'astro/config'
import swup from '@swup/astro'
// https://astro.build/config
export default defineConfig({
integrations: [
swup({
globalInstance: true, // この行を追加する
}),
],
})
これによって、
window.swup
インスタンスが登録されたことを検知して、ページが開かれたことを検知するhooksを登録- ページが開かれたことを検知して
init()
を実行 init()
によってEventListener
を再登録
を実行でき、ページの遷移後もメニューを開けるようになりました🎉
2日ぐらい悩みました、これをやっている人がほとんどいなかったので情報がないに等しかったです
そこで
のREADME.md
を隅々まで見返してみると、下の方にNote
として書いてあったのです、いやー気づかなかった!
知見が見つからなかったので書いてみました!
参考になれば幸いです!!

uiro
ご覧いただきありがとうございました!