nuxt.js(ver2) のSSGとswiftでwebview iOSアプリ実装
経緯
元々、iOSアプリで、webview(WKWebView) を使ってサーバーにアップした静的サイトを見に行く実装をしている
アプリがあったのですが、
nuxt.js(ver2) のSSGサイトという事もあり、初回読み込みに時間がかかるためかネットワークが安定していない場合などで、
初期表示が行われないなど、動作が安定しない事象がありました。
対応
対策として、nuxt.jsでgenerateしたファイル群をそのままiOSのプロジェクト下に置き、
webviewからはローカルファイルを参照しにいくことで解決しました。
具体的な対応
パスをローカルファイルに設定する
ローカルにあるindex.jsを見にいくように設定し、
かつ自動的にURLの最後に/をつけないよう、trailingSlashの設定をfalseにする。
router: {
trailingSlash: false,
base: './',
ローカルファイルはcacheが使えないのでlocalStorageを利用
代わりにlocalStorageを利用するように変更。
localStorage自体には、期限の設定ができないので、
あらかじめ期限情報を含むObjectをJSON.stringifyなどでserializeして保存・適切に期限の処理を入れる
routerの変換を行う
初回アクセス時、context.route.fullPath がローカルの絶対パスになってしまい、
nuxtのrouter挙動がおかしくなるので、プロジェクトのmiddlewareを作成し、
パスを変更するようにする。
router: {
trailingSlash: false,
base: './',
middleware: [
'authRedirect',
],
(※実際のredirect処理は、もう少し複雑ですが、今回のポイントに絞って簡略化してます)
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);
}
余談
このアプリはiOSだけの実装で、
かつswiftでBLE周りの処理などネイティブの操作を色々行っているので、
このようなWKWebViewアプリを作る場合は
react nativeやcapacitor などのフレームワーク使うよりシンプルかも?
React NativeもCapacitorも詳しく無いのですが、これらを使う方法に加えて、
生で静的サイトを置くというのも一つの方法かもしれません。(もちろんbackendのswift <- -> frontendのjs間通信もできます)
swiftとWKWebView間の通信に関する参考記事
余談2
おそらくnuxt3でも同じことはできると思います。(いずれnuxt3対応があれば、記事追加しようと思います)
nuxt2の場合、こちらも参考になりそう(未調査)
nuxt3での検証結果
結論としては難しそうなので、iOS側でlocal webserver立てることで対応した。
検証した内容
cdnの設定はこれでいけた
export default defineNuxtConfig({
app: {
cdnURL: './',
},
trailingSlashはnuxt3に無く、route strictを記述
export default defineNuxtConfig({
router: {
strict: true,
baseのパスを設定すると、generate時にうまくいかない。
export default defineNuxtConfig({
app: {
baseURL: './',
},