axiosとLaravelとVue.jsでよく使う設定のプリセット的な連携を紹介します。
Laravelのテンプレート上では静的部の定義をあらかじめ行っておきます。大体、metaタグに埋め込みます。
<head>
<title>{{ config('app.name') }}</title>
<meta charset="UTF-8">
<!-- CSRFトークンをはじめとして、色々常に使う値を定義 -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="user-name" content="{{ optional(auth()->user())->name }}">
</head>
<body>
<!-- Vue.jsを注入する -->
<div id="app"></div>
<!-- mix関数でコンパイルの度にキャッシュ消し機能付き更新をしなくてもいいように -->
<script src="{{ mix('js/app.js') }}"></script>
</body>
axiosの定義です。CSRFトークンを付けた通信をしたり、GETを扱いやすくしたり、エラー時のリダイレクトを定義したりします。
// HtmlHead.ts
/**
* csrfトークンを返す
* @return {string}
*/
export function csrfToken() {
const token = document.head.querySelector('meta[name="csrf-token"]');
if (!(token instanceof HTMLMetaElement)) {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
return token instanceof HTMLMetaElement ? token.content : '';
}
// ApiBaseRepository.ts
import axios, {AxiosInstance, AxiosRequestConfig} from 'axios';
import {csrfToken} from '@/repository/html/HtmlHead';
import {UNAUTHORIZED} from "http-status-codes";
const Qs = require('qs');
/**
* axios 設定を定義
*/
class BaseRepositoryConfig implements AxiosRequestConfig {
// ドメインを一々書かなくていいようにします。MIX_で始まる.envに書かれた値はビルド時に埋め込まれます
public readonly baseURL?: string = process.env.MIX_BASE_APP_URL;
// タイムアウト設定
public readonly timeout?: number = 30000; // ms
// ヘッダー定義。csrfToken()ではHTML上に埋め込んだCSRFトークンを呼び出し
public headers: { [index: string]: string } = {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': csrfToken(),
};
/**
* GETを投げる時にparamsにオブジェクトを渡す時、妙な解釈をされないためのパーサ設定
* @param {Object|String} params
* @return {String}
*/
public paramsSerializer = (params:any) => {
return Qs.stringify(params, {arrayFormat: 'brackets'});
};
}
// 設定を読み込んだインスタンスを用意.
const axiosInstance: AxiosInstance = axios.create(new BaseRepositoryConfig());
// インスタンスを元にした通信をするたびに必ず動く動作を定義
axiosInstance.interceptors.response.use((response) => { // intercept the global error
return response;
}, function(error) {
// API通信結果が401でログインが必要な状態と通知されたらログインページ(Laravel製)へリダイレクト
if (error.response.status === UNAUTHORIZED) {
window.location.href = process.env.MIX_BASE_APP_URL + '/login';
// API通信結果が404でNotFoundな場合、NotFoundページ(Vue.js製)へリダイレクト
} else if (error.response.status === NOT_FOUND) {
router.push('/404');
}
return Promise.reject(error);
});
export const ApiBaseRepository = axiosInstance;
axiosのinterceptorsはあっさりした記述ですが、詳しく動作をコントロールすると肥大化します。SPA(シングルページアプリケーション)であるとAPIアクセスをwebページの遷移的に扱う必要があり、随分お世話になる機能です。