Open5

nuxt.js(ver2) のSSGとswiftでwebview iOSアプリ実装

yunayuna

経緯

元々、iOSアプリで、webview(WKWebView) を使ってサーバーにアップした静的サイトを見に行く実装をしている
アプリがあったのですが、

nuxt.js(ver2) のSSGサイトという事もあり、初回読み込みに時間がかかるためかネットワークが安定していない場合などで、
初期表示が行われないなど、動作が安定しない事象がありました。

対応

対策として、nuxt.jsでgenerateしたファイル群をそのままiOSのプロジェクト下に置き、
webviewからはローカルファイルを参照しにいくことで解決しました。

具体的な対応

パスをローカルファイルに設定する

ローカルにあるindex.jsを見にいくように設定し、
かつ自動的にURLの最後に/をつけないよう、trailingSlashの設定をfalseにする。

nuxt.config.js
  router: {
    trailingSlash: false,
    base: './',

ローカルファイルはcacheが使えないのでlocalStorageを利用

代わりにlocalStorageを利用するように変更。
localStorage自体には、期限の設定ができないので、
あらかじめ期限情報を含むObjectをJSON.stringifyなどでserializeして保存・適切に期限の処理を入れる

routerの変換を行う

初回アクセス時、context.route.fullPath がローカルの絶対パスになってしまい、
nuxtのrouter挙動がおかしくなるので、プロジェクトのmiddlewareを作成し、
パスを変更するようにする。

nuxt.config.js
router: {
    trailingSlash: false,
    base: './',
    middleware: [
      'authRedirect',
    ],

(※実際のredirect処理は、もう少し複雑ですが、今回のポイントに絞って簡略化してます)

authRedirect.js

export default async context => {
// static ディレクトリが、nuxt generateしたファイル(dist)の中身を全て入れいている場所
      if (context.route.fullPath.indexOf('static/')>0 ) {
        
        //絶対パスから、static/ 以降の相対パスに修正してます。(細かい挙動間違いあるかもしれないのでお試しください)
        var newPath = context.route.fullPath.replace(/.*?\/static(\/[^/]+)\/index\.html/, '$1');
        context.redirect(newPath);
      }
yunayuna

余談

このアプリはiOSだけの実装で、
かつswiftでBLE周りの処理などネイティブの操作を色々行っているので、

このようなWKWebViewアプリを作る場合は
react nativeやcapacitor などのフレームワーク使うよりシンプルかも?

React NativeもCapacitorも詳しく無いのですが、これらを使う方法に加えて、
生で静的サイトを置くというのも一つの方法かもしれません。(もちろんbackendのswift <- -> frontendのjs間通信もできます)

https://reactnative.dev/
https://capacitorjs.com/

swiftとWKWebView間の通信に関する参考記事
https://web-y.dev/2020/11/02/ios-wkwebview-javascript-communication/

yunayuna

余談2

おそらくnuxt3でも同じことはできると思います。(いずれnuxt3対応があれば、記事追加しようと思います)

yunayuna

nuxt3での検証結果

結論としては難しそうなので、iOS側でlocal webserver立てることで対応した。
https://github.com/Building42/Telegraph#installation

検証した内容

cdnの設定はこれでいけた

nuxt.config.ts
export default defineNuxtConfig({
    app: {
        cdnURL: './',
    },

trailingSlashはnuxt3に無く、route strictを記述
https://router.vuejs.org/api/interfaces/RouterOptions.html#Properties-strict

nuxt.config.ts
export default defineNuxtConfig({
router: {
        strict: true,

baseのパスを設定すると、generate時にうまくいかない。

nuxt.config.ts
export default defineNuxtConfig({

    app: {
        baseURL: './',
    },