browserSyncのproxyとは?自動リロードが効かないときは試してみよう
今回はちょっとした小ネタです。
browserSyncってありますよね。あのローカルサーバーを簡単に立てられるやつです。
その中でオプションで「proxy」というものがあるのですがその「proxyってなんだ?」というお話です。
proxyと聞いてすぐに思い浮かぶのはプロキシサーバーとかだと思いますが、まさにこのプロキシサーバーを実現するためのオプションのよう。
ざっとプロキシサーバーの概要を説明するとこんな感じです。(大雑把な理解なので間違ってたらすいません...)
まあ中間管理職みたいな感じですよねきっと。どっちかっていうとエージェント...??
ということで、プロキシサーバは上記のように振る舞うことで、二つのシステムを一つのシステムであるかのように動かすことができるという理解に落ち着きました。
では実際にどのような動作になるのか、ということを確認していきます。
まず、今回のプロジェクトはバックエンド・フロントエンド共にLaravelを使用して作成しています。
環境
- サーバーサイド
Dockerにて、「9000」ポートでLaravelプロジェクトをホスティング
- フロントエンド
「3000」ポートでbrowserSyncを起動
もちろんリロードすれば9000番ポートの方でも変更は反映されるのですが、自動リロード効かないんすよね...
ということでオプション「proxy」の出番です!
コード
mix.browserSync({ files: [ "resources/views/**/*.blade.php", "public/**/*.*" ], proxy: { target: "localhost:9000", } });
browserSyncの設定は上記のみ。
filesは監視対象のファイルですね。
さて、proxyオプションを確認すると「 target: "localhost:9000"」と記載されていますね。
このように指定することで現在Laravelプロジェクトがホスティングされている9000番ポートのシステムと同期し、3000番ポートの方でも同じように9000番ポートの内容が反映されることになります。
そして、browserSyncが起動しているのは3000番ポートの方なのでプロジェクトを編集する際は「localhost:3000」を開きながら編集することで自動リロードもできているはずです。
以上、大雑把な小ネタでした...
GoogleMapsAPIで地図を実装! 基本からカスタムパノラマの実装、パノラマ間の遷移までまとめ
以前初めてGoogleMapの実装案件があったので、備忘録的にメモ。
今回の流れは下記の様な流れで進んでいきます。
1. GoogleMapの簡単な表示例
2. ストリートビューの簡単な表示例
3. GoogleMapにマーカーを立てる・マーカーにイベントを設置
4. カスタムパノラマの作り方
まず、簡単な例からいきましょう。
単なるGoogleMapを表示したい場合、必要となるのは下記のようなコードです。
<div id='map'></div> <script async defer src="https://maps.googleapis.com/maps/api/js?key=[自分のAPIキー]"></script>
#map { width: 100vw; height: 100vh; }
const initMap = ()=> { const latLng = {lat: 35.659063, lng: 139.700641}; const map = new google.maps.Map(document.getElementById('map'), { center: latLng, zoom: 14 }); } initMap();
これで緯度: 35.659063, 経度: 139.700641(渋谷ハチ公)を中心とする地図を表示することができました。
まあでもこのあたりはみなさん知っていると思います。
さて、まずGoogleMapAPIには大きく分けて二つのオブジェクトがあります。
1. GoogleMapオブジェクト
2. StreetViewPanoramaオブジェクト
GoogleMapオブジェクトはみなさんがいつもみているような地図のオブジェクトです。
ではStreetViewPanoramaオブジェクトとはどのようなものなのでしょう?
const initMap = ()=> { const latLng = {lat: 35.659063, lng: 139.700641}; const map = new google.maps.Map(document.getElementById('map'), { center: latLng, zoom: 14 }); const stv = map.getStreetView(); // mapのストリートビュー情報を取得 stv.setPosition(latLng); // ストリートビューの位置を指定 stv.setVisible(true); // ストリートビューの表示をアクティブに変更 } initMap();
先ほど地図を表示できたコードにコメントアウトで説明を入れている三行を追加しました。
こちらのコードを実行すると、ハチ公のストリートビューが表示されているはずです。
では一旦ここで解説です。
まず、GoogleMapオブジェクトからそれに紐づくStreetViewオブジェクトを取得するには「getStreetView()」メソッドを使用します。
これによって、変数stvにはStreetViewオブジェクトが代入されています。
そしてStreetViewオブジェクトで使用することのできるメソッドを使って、位置を指定し表示を切り替えている、というわけですね。
setPositionは入れなくてもいい気がしていたのですが、こちらのメソッドで明示的に位置情報をセットしないといけないよう。
これらのメソッドに関してはSyncerの記事がかなりよくまとまっていたのでぜひ参考にしてみてください。
https://lab.syncer.jp/Web/API/Google_Maps/JavaScript/
まず、GoogleMapとストリートビューの切り替えに関しては基本的にこのような流れで進んでいきます。
では次に、必ずと言っていいほど実装するマーカーの実装について説明していきます。
というのも、今回の案件ではマーカーをクリックするとカスタムパノラマが表示されるという実装もあったためです。
const initMap = ()=> { const latLng = {lat: 35.659063, lng: 139.700641}; const map = new google.maps.Map(document.getElementById('map'), { center: latLng, zoom: 14 }); const marker = new google.maps.Marker({ position: new google.maps.LatLng(latLng.lat, latLng.lng), map: map, title: 'サンプルマーカー', icon: { url: 'img/marker-icon.png', scaledSize: new google.maps.Size(128, 128) } }); } initMap();
このマーカーはもちろんGoogleMapの地図上に表示されるため、マーカーを立てることができるのはGoogleMapオブジェクトに対して、ということになります。
iconプロパティで画像を指定するだけで簡単にアイコン画像を変えることができるのは便利ですね。
ただ、「size」ではなく「scaledSize」にしないとアイコン画像がうまいこと拡縮しないので、そこだけは注意が必要です。
さて、次はイベントの指定です。
const initMap = ()=> { const latLng = {lat: 35.659063, lng: 139.700641}; const map = new google.maps.Map(document.getElementById('map'), { center: latLng, zoom: 14 }); const marker = new google.maps.Marker({ position: new google.maps.LatLng(latLng.lat, latLng.lng), map: map, title: 'サンプルマーカー', icon: { url: 'img/marker-icon.png', scaledSize: new google.maps.Size(128, 128) } }); marker.addListener('click',()=>{ // addListenerなのに注意! alert('clicked marker!'); }); } initMap();
追加したのはコメントが付いている箇所ですね。
コメントにも記載しましたが、addEveneListenerではなくaddListenerであることに注意しましょう。
これはGoogleMap独自のメソッドで、GoogleMapオブジェクトやStreetViewオブジェクトに対してイベントを設定する際にはこのaddListenerメソッドを使うことになります。
では、ここまでの内容で次のような実装をしてみましょう。
- GoogleMapの中心座標は渋谷ハチ公
- ハチ公にはマーカーを立てる
- マーカーをクリックするとハチ公のストリートビューが表示される
const initMap = ()=> { const latLng = {lat: 35.659063, lng: 139.700641}; const map = new google.maps.Map(document.getElementById('map'), { center: latLng, zoom: 14 }); const stv = map.getStreetView(); const marker = new google.maps.Marker({ position: new google.maps.LatLng(latLng.lat, latLng.lng), map: map, title: 'サンプルマーカー', icon: { url: 'img/marker-icon.png', scaledSize: new google.maps.Size(128, 128) } }); marker.addListener('click',()=>{ stv.setPosition(latLng); stv.setVisible(true); }); } initMap();
さて、実装できたはいいもののスポットが一つであることは珍しく、現状のままの実装ではいけません。
では複数のスポットに対応してみましょう。
const initMap = ()=> { let markers = []; // マーカーを格納する配列 const spotList = [ // マーカーの位置情報を格納している配列 { lat: 35.659063, lng: 139.700641, name: 'ハチ公', }, { lat: 35.658625, lng: 139.701057, name: 'モヤイ像', } ]; const map = new google.maps.Map(document.getElementById('map'), { center: {lat: spotList[0].lat, lng: spotList[0].lng}, zoom: 14 }); const stv = map.getStreetView(); spotList.forEach((spot, index) => { //spotListの数だけマーカーを設置、イベントを設定 markers[index] = new google.maps.Marker({ position: new google.maps.LatLng(spot.lat, spot.lng), map: map, title: spot.name, icon: { url: 'img/marker-icon.png', scaledSize: new google.maps.Size(128, 128) } }); markers[index].addListener('click',()=>{ stv.setPosition(markers[index].position); stv.setVisible(true); }); }); }
今回も追加したのはコメントが記載されている部分です。
ポイントとなるのは、位置情報を格納している配列「spotList」とマーカーを格納する配列「markers」ですね。
見ていただけるとわかると思いますが、一旦生成したマーカーをmarkersに格納して、その後にクリックイベントを設定しています。
一旦配列に入れることで後々マーカーに対する操作も行いやすくなるので、この方法はオススメです。
さて、ここまでで一旦GoogleMapのデフォルトの機能である「地図」、「ストリートビュー」、「マーカー」を使うことができたと思います。
ただ、なかなかこれで終わりというわけにはいかないんですよね...
そう、今回のメインとなる「カスタムパノラマ 」の実装について見ていきたいと思います。
カスタムパノラマの情報はGoogleMapAPIのドキュメント上に載っているのには載っているのですが、かなり情報が少なかったです...
とりあえず、カスタムパノラマ を表示してみましょう。
<div id='pano'></div> <script async defer src="https://maps.googleapis.com/maps/api/js?key=[自分のAPIキー]"></script>
const initMap = ()=> { const customStv = new google.maps.StreetViewPanorama( document.getElementById('pano'), { pano: 'custompanorama', }); customStv.registerPanoProvider(() => { return { location: { pano: 'custompanorama', description: 'カスタムパノラマ', latLng: new google.maps.LatLng(35.6595126, 139.7005696) }, links: [ { heading: 250, description: 'カスタムパノラマ2', pano: 'custompanorama2' } ], copyright: '©︎2019 Google 日本', tiles: { tileSize: new google.maps.Size(1024, 512), worldSize: new google.maps.Size(1024, 512), centerHeading: 105, getTileUrl: function (pano, zoom, tileX, tileY) { return `img/${pano}_${zoom}_${tileX}_${tileY}.jpg`; } } }; }); } initMap();
今回カスタムパノラマ画像として、下記のような画像を用意しました。
ちなみに、ストリートビューで公開されている画像は下記の手順でDLすることができます。
http://sanshonoki.hatenablog.com/entry/2017/05/12/215744
先ほどと比較するとなんだかわからないものがいっぱい出てきてしまった感があります笑
ただ、流れとしては単純で下記のような流れでカスタムパノラマを表示することができます。
1. StreetViewPanoramaオブジェクトを作成
2. StreetViewPanoramaオブジェクトのregisterPanoProviderメソッドでカスタムパノラマの情報を登録
一番ややこしそうなのは「registerPanoProvider」メソッドの中だと思います。
GoogleMapAPIのドキュメントでは、カスタムパノラマを表示するにはregisterPanoProviderメソッド内でStreetViewPanoramaDataを返却する必要がある、と記載しています。
つまり、returnで返却しているオブジェクトの部分 = StreetViewPanoramaDataということになりますね。
では、StreetViewPanoramaDataの中で重要なものだけピックアップして説明していこうと思います。
- location
StreetViewオブジェクトの位置情報やパノラマID等、大枠に関する情報を指定するプロパティです。
パノラマIDは最重要と言ってもいいかもしれません。
- links
ストリートビュー内で矢印が表示されていると思いますが、矢印の部分がこのlinksです。
linksで指定した通りに矢印が表示され、クリックするとlinksのpanoに記載されているパノラマIDのストリートビューに遷移します。
headingは角度なので、好きな角度を指定することができます。
- tiles
カスタムパノラマ画像の情報を指定するプロパティです。
getTileUrlはよしなに自オブジェクトのパノラマIDを見て画像を探してくれるので、基本的にこのままで問題ないと思います。
さて、簡単に説明していきましたがカスタムパノラマが一枚の場合はいいですが、二枚三枚となると一々この処理をしないといけないのか...と鬱になってきますよね。
ということで、このあたりの処理を関数化していきましょう!
const initMap = ()=> { const customStvList = { // カスタムパノラマの情報を格納する配列 custompanorama: { pano: 'custompanorama', description: 'カスタムパノラマ', links: [ { heading: 195, description: 'カスタムパノラマ2', pano: 'custompanorama2' } ], lat: 35.6595126, lng: 139.7005696, } }; const customStv = new google.maps.StreetViewPanorama(document.getElementById('pano'), {}); const initCustomStv = (pano) => { // カスタムパノラマを生成する関数 customStv.setPano(pano); registerCustomStv(customStv, createCustomStv( customStvList[pano].pano, customStvList[pano].description, customStvList[pano].links, customStvList[pano].lat, customStvList[pano].lng )) }; const registerCustomStv = (stv, stvPanoramaData) => { // カスタムパノラマを登録する関数 stv.registerPanoProvider(() => { return stvPanoramaData; }); }; const createCustomStv = (pano, description, links, lat, lng) => { // streetViewPanoramaDataを返却する関数 return { location: { pano: pano, description: description, latLng: new google.maps.LatLng(lat, lng) }, links: links, copyright: '©︎2019 Google 日本', tiles: { tileSize: new google.maps.Size(1024, 512), worldSize: new google.maps.Size(1024, 512), centerHeading: 105, getTileUrl: function (panoId, zoom, tileX, tileY) { panoId = pano; return `img/${panoId}_${zoom}_${tileX}_${tileY}.jpg`; } } }; }; initCustomStv('custompanorama'); } initMap();
さて、関数化してみるとなんとなくさっきよりも処理が追いやすくなったのではないかなと思います。
まず、カスタムパノラマを生成するにあたって必要な情報をあらかじめ配列「customStvList」として作成します。
で、「registerCustomStv」の中で引数として指定されたパノラマIDをもとに一致するデータをセットしていくわけですね。
最終的には「initCustomStv」の引数としてパノラマIDを指定すると、そのパノラマIDに応じたカスタムパノラマを生成してくれる処理となっています。
これで、あとは「customStvList」の中にどんどんカスタムパノラマの情報を格納していけばカスタムパノラマを生成することができます。
では、カスタムパノラマの情報を追加してカスタムパノラマの中を移動してみましょう。
const initMap = () => { const customStvList = { // カスタムパノラマの情報を格納する配列 custompanorama: { pano: 'custompanorama', description: 'カスタムパノラマ', links: [ { heading: 195, description: 'カスタムパノラマ2', pano: 'custompanorama2' } ], lat: 35.6595126, lng: 139.7005696, }, custompanorama2: { pano: 'custompanorama2', description: 'カスタムパノラマ2', links: [ { heading: 25, description: 'カスタムパノラマ', pano: 'custompanorama' } ], lat: 35.6525126, lng: 139.7001696, } }; const customStv = new google.maps.StreetViewPanorama(document.getElementById('pano'), {}); const initialSpot = 'custompanorama'; const initCustomStv = (pano) => { // カスタムパノラマを生成する関数 registerCustomStv(customStv, createCustomStv( customStvList[pano].pano, customStvList[pano].description, customStvList[pano].links, customStvList[pano].lat, customStvList[pano].lng )) }; const registerCustomStv = (stv, stvPanoramaData) => { // カスタムパノラマを登録する関数 stv.registerPanoProvider(() => { return stvPanoramaData; }); }; const createCustomStv = (pano, description, links, lat, lng) => { // streetViewPanoramaDataを返却する関数 return { location: { pano: pano, description: description, latLng: new google.maps.LatLng(lat, lng) }, links: links, copyright: '©︎2019 Google 日本', tiles: { tileSize: new google.maps.Size(1024, 512), worldSize: new google.maps.Size(1024, 512), centerHeading: 105, getTileUrl: function (panoId, zoom, tileX, tileY) { panoId = pano; return `img/${panoId}_${zoom}_${tileX}_${tileY}.jpg`; } } }; }; const setCustomStvEvent = () => { customStv.addListener('pano_changed',()=>{ let currentPano = customStv.getPano(); initCustomStv(currentPano); }); }; const initialize = () => { customStv.setPano(initialSpot); initCustomStv('custompanorama'); setCustomStvEvent(); }; initialize(); } window.onload = () => { initMap(); }
さて、カスタムパノラマの情報を一つ追加して処理もまとめてみました。
ちゃんとカスタムパノラマ間を移動することができていますね。
矢印をクリックしたら、というイベントはないのですが「pano_changed」というパノラマIDが変わったら発火する、というイベントはあるんですね。
先ほども言った通り、矢印をクリックするとその矢印に紐づいているパノラマIDのカスタムパノラマに遷移しようとする、つまりパノラマIDが書き換わるため、このイベントが発火する、ということになります。
なので、こちらのイベントで先ほど定義したカスタムパノラマを生成する関数「initCustomStv」を次のパノラマIDを引数にして実行してあげれば次のカスタムパノラマに遷移することができるわけです。
ちょっと引っかかるのが「次のパノラマID」だと思いますが、「pano_changed」というパノラマIDが変わったら発火する、というイベントですのでこのイベント内で「getPano()」という現在表示されているカスタムパノラマのパノラマIDを取得するメソッドを実行すると次のパノラマIDが取得できるということですね。
というわけでGoogleMapsAPIの基本的な使い方をご紹介してみました。
有料になっちゃいましたがまだまだ動的に地図を作成したいときには使うことが多いツールだと思いますので少しでも参考になれば嬉しいです。
Javascriptの変数宣言でカギ括弧がついてるやつってなんなん?
変数宣言で見かける、という人はもしかしたら少ないかもしれませんがもっともよく目にするのはパッケージのImport文だと思います。
import {DynamoDB, S3 } from 'aws-sdk';
的なやつですね。
これ、es6の分割代入というものでして普通に変数宣言にも使えます。
const human = { name: 'tanaka', sex: 'male' } const { name } = human; // tanaka
パッケージのインポートは何気なしにやってたんですが、そういや普通に使えるんだなと笑
Nuxt.jsで環境ごとにdotenvで.envファイルの読み込みを切り替える
なんかパッと解決できなかったので備忘録。
Nuxt.jsではcreate-nuxt-appをするときに「dotenv使うかー?」的なこと聞かれてインストールする方も多いと思います。
初めは一つの.envファイルに下記のように一つのファイルに設定してコメントアウトして切り替えていました。
# 本番用 BASE_URL = 'honban.com' API_BASE_URL = 'https://honban/endpoint/' # 開発用 # BASE_URL = 'kaihatsu.com' # API_BASE_URL = 'https://kaihatsu/endpoint/'
ただ、やっぱだるいのでenvファイルを分けたくなり、結局「.env.prod」と「.env.dev」の二つのファイルを作成し、環境変数で読み込めるようにしました。
使うモジュール的には「dotenv」と「cross-env」で、package.jsonにまず下記のように環境変数を指定します。
"scripts": { "dev": "cross-env NODE_ENV=\"dev\" nuxt-ts", },
これで「yarn dev」したときに環境変数には「dev」が入ります。
そのため、nuxt.config.jsで下記のように読み込ませます。
require('dotenv').config(); export default { mode: 'universal', // 省略 buildModules: [ '@nuxt/typescript-build', '@nuxtjs/vuetify', ['@nuxtjs/dotenv', { filename: `.env.${process.env.NODE_ENV}` }] ] }
dotenvモジュールのホムペ見たら書いてありましたねオプション笑
github.com
やっぱドキュメントが一番!
slackの自作アプリで「not_in_channel」のエラーが出る場合の権限
slackのアプリを作って、Botユーザーに権限与えた時にちょっとハマったやつです。
やりたいこととしては、webAPIを使って
- チャンネル一覧取得
- チャンネルに投稿
という二点だったので、権限としては「channels:read」と「chat:write」の二つを「Bot Token Scopes」に設定してました。
ただ、アプリをインストールしているチャンネルでは正常に投稿できるのですが、インストールしていないチャンネルでは投稿できませんでした。
と、そこでもう一度見直してみると「chat:write.public」という権限が。
こちらよく見ると「インストールしてなくても投稿できまっせ」的なことが書いてあったので権限を変更して再度試すと無事投稿できました。
英語ちゃんと読もうね、ってやつでした。笑
JavaScriptでオブジェクトから値を検索し、ソートする方法
最近まで会員サイトの構築に追われておりましたが、無事リリースすることができひと段落できました。
さて、今回はタイトルの通りJavaScriptのオブジェクト(連想配列)の値を検索してソートする方法についてご紹介していきたいと思います。
基本的なところだとは思うのですが、意外とJavaScriptのオブジェクトの扱いって難しかったりするんです。
ということで今回は下記のようなオブジェクトを検索&ソートしていきたいと思います。
const target = [ { id: 1, name: '田中一郎', nameKana: 'タナカイチロウ', point: 0, }, { id: 2, name: '田中二郎', nameKana: 'タナカジロウ', point: '', }, { id: 3, name: '田中三郎', nameKana: 'タナカサブロウ', point: 3, }, { id: 4, name: '田中四郎', nameKana: 'タナカシロウ', point: 5, }, { id: 5, name: '田中五郎', nameKana: 'タナカゴロウ', point: 6, }, { id: 6, name: '佐藤一郎', nameKana: 'サトウイチロウ', point: '', } ];
今回実装してみるのは下記の検索&ソートです。
- 名前の部分一致検索
- idの昇順/降順
- pointが空のユーザーの検索
後述しますが、pointの昇順降順もidと同じように実装することができます。
では、実際のコードを見てみましょう。
/** search text **/ const searchTxt = (el,txt) => { return el.reduce((acc, val) => { if(val.name.indexOf(txt) !== -1 || val.nameKana.indexOf(txt) !== -1) { acc.push(val); } return acc; }, []) } const searchNoPoint = (el) => { return el.reduce((acc, val) => { if(val.point === '') { acc.push(val); } return acc; }, []) } /** sort **/ // aに二番目の値、bに一番目の値が入る const sortUp = (a, b) => { return a.id - b.id; } const sortDown = (a, b) => { return b.id - a.id; }
そして実際に動かしてみているのが下記になります。
やはりarray.reduceは便利ですね。
Array.prototype.reduce() - JavaScript | MDN
配列にしちゃえばなんでもreduceでなんとかなるのではないでしょうか?
また、sort関数ですが独自にソート用の関数を定義することができるため自由にソート条件をカスタマイズすることができます。(今回はただの昇順降順ですが...)
結局のところオペランドの真偽値で順番が決まるので、文字の昇順降順とかもいけるみたいです。
Array.prototype.sort() - JavaScript | MDN
そんなに濃い内容ではなかったですが、意外と使う機会が多い内容だったのではないでしょうか?
では今回はこのへんで...
Nuxt.jsのビルドについてまとめてみた デプロイに際して最適な方法は?
最近仕事でオーディションサイトを「Serverless+Nuxt.js」で作っているのですが、今回は初めてイケてると話題のNuxt.jsを業務で取り入れてみました。
右も左も分からなかったのですが、学習&実務で学習したことをお話ししていこうと思います。
今回お話しするのはNuxt.jsの「ビルド」についてです。
Nust.jsの「ビルド」とは
Nuxt.jsのビルドに関しては二つ種類があり、大別すると「SSR」か「そうでないか」だと思います。
SSRとは
SSRとは、サーバーサイドレンダリングの頭文字をとった単語ですがこちらはちゃんとSSRするには意外とめんどくさかったりします。
というのも、サーバーサイドレンダリングを行うにはNuxt.jsの中で下記のコマンドを実行しないとならないため。
```
nuxt build
nuxt start
```
こちらを実行しなければならないため、通常の静的なホスティング(S3など)ではNuxt.jsにおいてSSRを実現できないわけです。
というのも、nuxt startを実行するとポートが立ち上がりそれを解決しないと外部からのアクセスができないからですね。
しかし、後述するSPAモードやStaticモード(nuxt generateした場合)とは違い、Nuxt.jsのメリットであるSEOに適したビルドや非同期を用いたミドルウェアも実現できるので可能であればSSRでデプロイまでいけるのが一番最適な方法だと思います。
では、「そうでない方」はなんなのか
そうでない方(静的なビルド)とは
そうでない方は、SSRしないビルドです。
詳しく言えばNuxt.jsのSPAモードがそれにあたるでしょう。
また、modeはuniversalですが「nuxt generate」で静的なファイルを書き出している場合もこちらにあたります。
こちらの場合は、静的なホスティングになるのでデプロイ自体は簡単です。
SPAモードの場合は「nuxt.config.js」の「mode」を「spa」にして「nuxt build」をすると「dist」配下にソースが書き出されます。
また、「nuxt generate」の場合はも同じように 「dist」配下にソースが書き出されます。
この「dist」配下に書き出されたものをアップロードすればいいのでSSRモードのようにサーバー上でコマンドを実行しなければならない、ということはないわけです。
普通のhtmlをアップロードするような感覚でいけるわけですね。
では、Nuxt.jsにおいてSPAモードと「nuxt generate」で書き出した場合で何が違うのでしょうか?
Nuxt.jsのSPAモードと「nuxt generate」の違いについて
これらの違いですが、SPAモードでは
- ミドルウェアやasyncDataで非同期が使える
一方「nuxt generate」で書き出した静的なファイルの場合には
- vue-metaが使える
- レスポンスが早い
というそれぞれのメリットがあると思います。
ただ、ほとんどの場合でSPAモードのメリットを享受したい場合はSSRモードでデプロイすると思います....
しかし、完全に静的なファイルで書き出すとなるとミドルウェアでAPIを叩いてどうこうする、といったことができなくなるのでmetaタグが全ページで同じであればいい、ということあればSPAモードは非常に有用です。(実際に今回の案件ではSPAモードで実装しようと考えているので...)
かなり案件の要件によってビルドの方法は変わってくると思いますが、出来るだけSSRモードでビルドした方がNuxt.jsの恩恵を受けられるでしょう。
しかし、s3などの静的ホスティングの場合、つまりレスポンスが重要でそこまで動的にルーティングや情報が変わらない場合はSPAモードか「nuxt generate」で書き出した方がいい場合もあります。
Nuxt.jsは個人的にかなり気に入ったので次回はこれらを踏まえて早めの段階からデプロイを見据えて検討しようと思います。