【CORS対策版】Nuxt.jsでAxiosを扱ってみるGET編

「ラズパイ4でNuxt.jsの入門をしてみる」の続きの記事になります。

私はラズパイでローカルサーバーを建ててWindows側でSSH接続していますが、 今回からはnuxt.jsをインストールできるのであればラズパイじゃなくても大丈夫です。

それでは今回はAPIを叩くために使われるaxiosを使っていきたいと思います。

axiosはnuxt.js以外でももちろん普通に使える、Ajaxのラッパーライブラリとなっています。

axisoをnpmでインストール

まずaxiosを使うためにnpmでインストールします。

sudo npm install --save nuxtjs@axios

恐らく問題なくインストールできてると思います。

nuxtの場合axios単体ではなくてnuxtjs@axiosでインストールするのに気をつけてください。

次にnuxt.config.jsに使用する設定を書き込みます。

export default {

    // 省略 //

  // Modules: https://go.nuxtjs.dev/config-modules
  modules:     [
    "@nuxtjs/axios",
  ],

    // 省略 //
}

modulesの部分に先程インストールしたモジュールを指定してやるだけでOKです。

新しいページを追加してaxiosでGETをしてみる

nuxt.js導入直後だと思うのでとりあえずなんか新しいページを作ってみましょう。

ルートディレクトリにある「pages」に入っている「index.vue」が最初に表示されるページとなっています。

一旦これは置いといて新たにファイルを作っていきます。

とりあえずaxiosのテストをやっていきたいので「axios.vue」とでもファイル名をつけて index.vueのあるところと同じ階層に保存してください。

<template>
    <div class="container">
        {{ coinDatas }}
        <button>GET</button>
    </div>
</template>

<script>
    export default {
        async asyncData({ $axios }) {
            // APIのURL
            const url = "https://api.coindesk.com/v1/bpi/currentprice.json";
            // リクエスト(Get) 非同期で取得したデータが配列で返ってくる
            const res = await $axios.$get(url);
            // 配列をjson形式にして返す
            return {
                coinDatas: res
            };
        }
    };
</script>

アクセスしたら画面に取得したjsonデータをそのままテキストとして描写するだけの仕組みです。

普通にaxiosを使う場合は「axios.get~」みたいな書き方をしますが、 nuxtの場合「$axios.$get」的な書き方になっているのに気をつけてください。

なんでそうなってるのかは各自調べてください。

そうなってるからそうなってるのです。

郷に入っては郷に従えで進めていきましょう。

template側にあるbuttonタグは一旦無視でOKです。

後ほどボタンを押したらGETする仕組みを作っていきます。

このコードを保存して「localhost:3000/axios」でアクセスすると取得したjsonデータが表示されます。

localhost:3000は環境に合わせて変更してください。

ちなみにjsonの内容はビットコインの価格情報です。

vue公式でaxiosを使う際に使ってたAPIなので各自お好きなAPIをお使いください。

ボタンを押したらGETする仕組みに変更してみる

現状アクセスしたらいきなりAPIを叩いてしまうので、ボタンを押したタイミングで axiosでGETする仕組みに切り替えてみましょう。

やることは単純で、GET処理を関数化してボタンを押すと関数を呼び出すだけです。

簡単ですね!

メソッド化の仕方はvueの書き方にそってみます。

<template>
  <div class="container">
    {{ coinDatas }}
    <button v-on:click="asyncData()">GET</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      coinDatas: [],
    }
  },
  methods: {
    async asyncData() {
      // APIのURL
      const url = 'https://api.coindesk.com/v1/bpi/currentprice.json'
      // リクエスト(Get) 非同期で取得したデータが配列で返ってくる
      const res = await this.$axios.$get(url)
      // 配列をjson形式にして返す
      return {
        coinDatas: res,
      }
    },
  },
}
</script>

変更点は$axiosのあたりですね。

this.$axiosになっていることに注意してください。

あとは関数化したものをv-onで呼んでいるだけです。

CORSエラー

恐らくローカルのみで開発しているとNetworkエラーとでて、 ブラウザ付属のデベロッパーツールのコンソールを見るとCORSエラーが出ると思います。

ローカルで作ってるサイトから外部ネットワークにつなごうとすると働くセキュリティですね。

プロキシを利用してエラーを回避する方法があります。

Nuxt.js Axios moduleでCORSエラーの優しい対処法 https://qiita.com/mouse_484/items/71f77aef3dfe5216a71b

この解決法が一番てっとり早かったです。

CORSに関しては数記事書けるぐらいの内容になるので解説は省きます。

各自しらべてみてください。

ちゃんとしたhttpsのオンラインサーバーであればCORS対策とかは別にしなくても大丈夫ですが、 ローカルで外部のAPIを叩くときはnuxtに限らず発生してしまうので気をつけましょう。

ボタンを押したときの処理改良版ソースコード

色々調べているとわかったこともあったので最終的になったコードを載せておきます。

v-on:clickは@clickと省略できるようなのでボタンを押した時に表示したい場合、 以下のようなコードになります。

v-showは表示非表示を切り替える時に便利なので覚えておきましょう。

v-if v-elseでもいいですが非表示とかではなくDOMそのものを操作するので 場合によって使い分けるようにします。

今回はv-showを使いました。

<template>
  <div class="container">
    <div v-show="coinDatas !== null && coinDatas !== undefined">
      <p>{{ coinDatas.length !== 0 ? coinDatas : '無し' }}</p>
    </div>
    <div v-show="coinDatas === null || coinDatas === undefined">
      <p>GETボタンを押してください</p>
    </div>
    <button @click="asyncData()">GET</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      coinDatas: [],
    }
  },
  methods: {
    async asyncData() {
      // APIのURL
      const url = '/api/v1/bpi/currentprice.json'
      // リクエスト(Get) 非同期で取得したデータが配列で返ってくる
      const res = await this.$axios.$get(url)
      // 配列をjson形式にして返す
      this.coinDatas = res
      // return this.coinDatas
    },
  },
}
</script>

私はCORS対策をした後なので、asyncDataの部分のurlがちょっと変わってますね。

一見自分ところのアドレスを叩いてるようにみえますが、 CORS対策をしたことで/api/の形で叩くと外部のAPIを叩くような仕様になっています。

一見自分のサイトでやってるようにみせかけることでCORSエラーを回避しているイメージです。

先程も言ったように、本番の場合はCORSエラーを気にする必要は基本ないとおもうので、 本番のときと開発のときでアドレスを切り替えられるようにしておくと便利でしょう。

これでボタンを押したら画面にjsonテキストが表示されると思います。

Windows環境でのフォーマットエラー

windowsでローカル開発してるとフォーマットエラー的なのがでたので

https://qiita.com/ryosukes/items/1d2d2f2be9fa46c50f85 create-nuxt-appで作ったプロジェクトが最初からフォーマットエラーを抱えているときの対応

コチラを参考にさせていただきました。

package.jsonのscriptsにあるlint:jsのところの --extの後ろに--fixを付けるだけでコンパイル通りました。

VS-Codeのpretterが動かなかったりしたのでそれを修正して いい感じに形成してくれたのですが、今度はWindowsの改行コードエラーがでてしまいました。

Windows改行コード問題はこれをすれば多分解決

.pretterrcファイルに「"endOfLine": "auto"」を加えたら解決してくれました。

MacやLinux関連でやっていれば特に起こらない問題だと思いますが メイン機がWindowsの場合はこれをやっておけばいいかなとおもいます。

APIサーバーをローカルで建てたらいいじゃない

少し余談ですが、今回は外部のAPIを利用したのでCORS対策に悩まされていました。

ローカルにAPIサーバーがあれば気にせずやれるわけなんですが、 いちいちAPIサーバーを建てるのも面倒くさいですよね。

Laravelなんかだとフロントもバックも一緒に作ることができるので あんまり気にならないんですがPHPの環境やらDB環境やら色々準備が必要なので 出来れば簡単にできてしまいたいところです。

そこで!Strapiの出番です。

「HeadlessCMSのStrapiに入門してみる」で簡単にAPIを作ることができたので ローカルでAPIを建ててしまえばGETもPOSTのテストも簡単にできてしまいますね。

ってことで次回はStrapiの復讐も兼ねてnuxtのためにAPIサーバーをローカルで立ててしまいましょう。