【swiper】webpack4 × Vue3環境で導入【Navigation, Pagination】

## 概要
カルーセルといえばなswiperを気軽に導入しようとしたらwebpack4との相性が悪すぎて大苦戦したので備忘録残しておきます。

## 注意事項
本来はESMの解決ができるよう、いろいろなxxx-loader達の設定を駆使して使用するみたいですが、今回はとりあえず **全部無視して動くようにした。** というだけなので多分正解じゃないです。きっともっとスマートな解決方法があると思いますが、どうにか動かしたいんだという方は参考にしていただければと思います。

## 環境
windows10
Vue v3.2.x
webpack v4
swiper v7.x

投稿時点でのswiperの最新はv11ですが、v7が相性よかったみたいです。知らんけど。
たぶんv11でも動かせる気がしますがもうしんどいのでやりません。無理。

## 完成形
swiperv7のvue componentを使用していきます。

```vue
<!-- swiper導入したいよコンポーネント.vue -->
<template>
    <swiper
        :modules="modules"
        :navigation="true"
        :pagination="{ clickable: true, type: 'fraction' }"
    >
        <swiper-slide><img src="hoge1.png" /></swiper-slide>
        <swiper-slide><img src="hoge2.png" /></swiper-slide>
        <swiper-slide><img src="hoge3.png" /></swiper-slide>
    </swiper>
</template>
<script>
// ここからインポート地獄
import { Swiper } from 'swiper/vue/swiper.js'
import { SwiperSlide } from 'swiper/vue/swiper-slide.js'
import 'swiper/swiper-bundle.css'
import Pagination from 'swiper/modules/pagination/pagination.js'
import Navigation from 'swiper/modules/navigation/navigation.js'

export default {
    components: {
        Swiper,
        SwiperSlide
    },
    setup() {
        return {
            modules: [Pagination, Navigation]
        }
    }
}
</script>
<style>
/* なぜ表示されないのか本当に謎 */
.swiper-button-prev::after {
    content: '<'
}
.swiper-button-next::after {
    content: '>'
}
</style>
```

## 詰まったところ
まず、何につまづいたかというとmodule not foundエラーです。
swiper公式では `import { Swiper, SwiperSlide } from 'swiper/vue'`でコンポーネントを呼び出すと記載がありますが、まずここで `swiper/vue`が読み込めない。

また、追加モジュールのNavigation,Paginationも同様に、公式では `import { Pagination, Navigation } from 'swiper/modules'` で呼び出せると記載がありますが、やはりmodule not foundで呼び出せません。

どうやらwebpack4はESM対応というのができていないらしく、この呼び出し方だと解決できないようです。
（v5であれば問題ないらしいが依存関係の問題もありバージョンアップという選択肢はなかった）

この問題を解決すべく、babel-loaderに以下の設定を追加

```js
// webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                type: 'javascript/auto',
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                },
                exclude: /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/
            }
        ]
    }
}
```

してみましたが変わらずmodule not found.

css-loaderやstyle-loaderの設定追加も試してみましたが、バージョンの依存関係がよろしくなかったのかビルド時点でエラーを吐いてしまい、うまくいかず。

swiper v9以降で対応しているweb componentでの導入も試しましたが、同様の要因で`register()`が呼び出せず実装できませんでした。

あれこれ試しているうちに、ファイルまで指定すると呼び出しできることがわかりました。
`node_modules/swiper`から必要なファイルを自力で探し、1つずつインポート…という結果に至ったわけです。
※cssは公式だとmoduleごとにインポートしていますが、`swiper-bundle.css`がmoduleも含んだcssを持っていたのでこの書き方(bundle)だと必要ないみたいです。

## Pagination, Navigationの設定について
公式だとnavigationは`<swiper navigation>`だけで問題ないようですが、私の環境ではなぜか効いていませんでした。
丁寧に`<swiper :navigation="true">`と書くことでナビゲーションが動作するようになりました。

また、paginationに設定している`type: 'fraction'`は全体ページ数と現在のページ数を分数で表示するための設定項目です。


## ナビゲーションの矢印が表示されない
ここまでで動作は問題なく動くようになりましたが、私の場合なぜかNavigationの矢印（＜＞こういうやつ）が表示されず、`prev` `next` という文字で表示されていました。

CSSを確認するとボタンはそれぞれ`content: 'prev'` `content: 'next'`となっていました。
＜＞はデフォルトで表示されるはずなんだけどな…

本来であればどこかからprevとnextという情報をもとに＜＞の画像？とかを呼び出してくるものかと思いますが、なぜか呼んできてくれないので仕方なく上書きすることに。

```css
.swiper-button-prev::after {
    content: '<'
}
.swiper-button-next::after {
    content: '>'
}
```

`!important`等はつけずに上書きすることができました。
`content: ''` にして、svgなどアイコンで自由に変更することも可能かと思います。


## 感想
まさかswiperの導入でこんなに苦戦することになるとは思いませんでした。
webpack、便利なものみたいですがプラグインではなく生のwebpackで動かすのはなかなか設定が大変ですね。必要とされる知識量が多くて大変ですが、使いこなせたら強いと思うので理解を深めていけるよう精進したいと思います。