46
37

More than 3 years have passed since last update.

Vue-CLI3 ベースのアプリ開発で JSON API が使える express server を使う

Last updated at Posted at 2019-01-28

はじめに

Webpack を使ったフロントエンド開発では、Webpack dev server を使うと、ファイルの変更をチェックして自動的にビルド・ブラウザのリロードをやってくれます。このとき、サーバ側に REST API の機能を持たせたい…ということがあります。

それを Vue-CLI3 ベースのプロジェクトでやる方法について紹介します。

使う道具

Ubuntu 18.04 でやっています。

hagiwara@dev01:~/tmp$ nodejs --version
v8.10.0
hagiwara@dev01:~/tmp$ npm --version
6.6.0
hagiwara@dev01:~/tmp$ vue --version
3.3.0
hagiwara@dev01:~/tmp$

Vue-CLI3 ベースのプロジェクトを用意する

とりあえずサンプルのプロジェクトをサクッと立てます。

hagiwara@dev01:~/tmp$ vue create foobar

Vue CLI v3.3.0
? Please pick a preset: default (babel, eslint)

Vue CLI v3.3.0
✨  Creating project in /home/hagiwara/tmp/foobar.
🗃  Initializing git repository...
⚙  Installing CLI plugins. This might take a while...

(省略)

🎉  Successfully created project foobar.
👉  Get started with the following commands:

$ cd foobar
$ npm run serve

hagiwara@dev01:~/tmp$

ひとまず dev server 起動してみましょう。

hagiwara@dev01:~/tmp/foobar$ npm run serve

> foobar@0.1.0 serve /home/hagiwara/tmp/foobar
> vue-cli-service serve

DONE  Compiled successfully in 4841ms

  App running at:
  - Local:   http://localhost:8080/
  - Network: http://10.0.2.15:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

localhost:8080 にアクセスするとこんな感じで動きます。
a01.png

vue-cli-plugin-express で API Server を作る

vue-cli-plugin-express - npm を使います。

インストール

hagiwara@dev01:~/tmp$ cd foobar/
hagiwara@dev01:~/tmp/foobar$ vue add express

📦  Installing vue-cli-plugin-express...

(省略)

✔  Successfully installed plugin: vue-cli-plugin-express

? Should serve vue app? Yes
? Where will be located your server? ./srv

🚀  Invoking generator for vue-cli-plugin-express...
✔  Successfully invoked generator for plugin: vue-cli-plugin-express
   The following files have been updated / added:

     srv/index.js
     vue.config.js
     package.json

   You should review these changes with git diff and commit them.

hagiwara@dev01:~/tmp/foobar$

途中の質問についてはデフォルト回答ですが、"Should serve vue app?" は yes にしてください。この後出てくる "Fallback" 動作に関する設定です。インストールすると、表示があるとおり、いくつかファイルが変更・追加されてます。

設定

デフォルト設定で動かしましょう。追加された srv/index.js に express server のコードがコメントアウトされた状態で貼っているので、とりあえず GET api のみ使えるようにします。

srv/index.js
import express from 'express';

export default app => {
  app.use(express.json());

  app.get('/foo', (req, res) => {
    res.json({msg: 'foo'});
  });
}

API Server を動かす

hagiwara@dev01:~/tmp/foobar$ npm run express
DONE  Mon Jan 28 2019 17:37:14 GMT+0900 (JST)  

  ♻️  Server running at:
    - Local:   http://localhost:3000/
    - Network: http://10.0.2.15:3000/


  ⚙  You're in development mode. to start the application, run yarn serve.

  🎉 Fallback to this server enabled: you can use relative routes in your code!

  🔀 api routes found:
    - /foo: GET

localhost:3000/foo をたたいてみましょう。
a02.png
ちゃんと JSON データが返ってきてますね。

アプリ (Frontend) からAPIを使う

ここまでだとだからどうしたって話なんですよね。まだアプリはアプリ、API Server は API Server で個別に動いているだけです。

アプリ側サーバ起動

npm run express して API Server を起動している状態で、npm run serve してアプリ用の dev server も起動しましょう。このとき dev server 側で

INFO  Starting development server...
DONE  Express server  Fallback will be done on your server. You can use relative calls to it in your code.

というメッセージが出ているのを確認しておいてください。このあと "Fallback" ってなんのこっちゃ、という話をします。

アプリから REST API をたたく

API /foo をたたいたとき返っている msg の値をサンプルアプリ側で表示してみます。

まず API Server 側で適当なメッセージを返すように変更。

srv/index.js
import express from 'express';

export default app => {
  app.use(express.json());

  app.get('/foo', (req, res) => {
    res.json({msg: 'Welcome to Your Vue.js App FROM API SERVER'});
  });
}

アプリ側は /foo をたたいて取得した JSON を元にメッセージを設定します。

src/App.vue
hagiwara@dev01:~/tmp/foobar$ git diff src/App.vue
diff --git a/src/App.vue b/src/App.vue
index fcc5662..2d6dac4 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,7 +1,7 @@
<template>
   <div id="app">
     <img alt="Vue logo" src="./assets/logo.png">
-    <HelloWorld msg="Welcome to Your Vue.js App"/>
+    <HelloWorld v-bind:msg="message"/>
   </div>
</template>
@@ -12,6 +12,18 @@ export default {
   name: 'app',
   components: {
     HelloWorld
+  },
+  computed: {
+    message () {
+      const req = new XMLHttpRequest
+      let message = ''
+      req.open('GET', '/foo', false)
+      req.onload = function () {
+        message = JSON.parse(req.responseText).msg
+      }
+      req.send(null)
+      return message
+    }
   }
}
</script>
hagiwara@dev01:~/tmp/foobar$

HelloWorld というコンポーネントに msg で渡した文字列が表示されるので、そこを computed (算出プロパティ) の message で置き換えます。で、message の中身は単純に /foo をたたく→ JSON をパース → msg の値を取り出し、というだけ。(エラーチェックも何もない雑な処理ですがまあサンプルなので。)

アプリはこうなります。ちゃんと /foo を GET して取得してきた値で更新できています。
a03.png

これをやってみると、以下の点気づくかと思います。

  • App.vue を編集するとアプリが自動的にリビルドされてブラウザ上でリロードされる。
    • これはもともと使ってる dev server の動作
  • index.js を編集すると API サーバ側がリロードされる。
    • express plugin もサーバ側ソースコードの更新を watch してリロードしてくれます。
  • アプリ側 dev server は tcp/8080, API server は tcp/3000 で起動しているのに、アプリ側コードではそれらの違いを気にしなくても動いている。
    • ここが "Fallback" といってる動作ですね。

express-plugin の中身の動作まで細かく追いかけてるわけではないのですが、簡単な動作確認ができます。API server, Dev server の両方が動いている状態で、API サーバだけ落としてみましょう。その上でアプリ側を更新 (ブラウザ F5) すると、こういうエラーが出ます。

Proxy error: Could not proxy request /foo from localhost:8080 to http://0.0.0.0:3000/.

……ということで、内部的に Proxy してくれてるみたいですね。

Mode (develop/production) の設定

上記の話は development mode での利用方法でした。Production では下記のようにします。

まず npm run build してパッケージングする (dist ディレクトリができます)。

hagiwara@dev01:~/tmp/foobar$ npm run build
(省略)
hagiwara@dev01:~/tmp/foobar$ ls dist
css  favicon.ico  img  index.html  js
hagiwara@dev01:~/tmp/foobar$

この状態で npm run express:run を実行する。

hagiwara@dev01:~/tmp/foobar$ npm run express:run

> foobar@0.1.0 express:run /home/hagiwara/tmp/foobar
> vue-cli-service express:run


DONE  Mon Jan 28 2019 18:42:00 GMT+0900 (JST)

  ♻️  Server running at:
    - Local:   http://localhost:3000/
    - Network: http://10.0.2.15:3000/


  📦 You're in production mode. To build the application, run yarn build.

  🎉 Fallback to the app enabled: your application is served!

  🔀 api routes found:
    - /foo: GET

これで localhost:3000 にアクセスするとアプリが動きます。(express plugin でアプリケーションを含めて起動している)

まとめ

vue-cli-plugin-express を使うと API サーバを含むフロントエンド開発がお手軽にやれるようになります。

  • アプリ側は API Server の URL をいちいち気にしなくてよい
  • サーバ側は API の定義だけ書けばよい
  • development の場合
    • API, App (dev server) をそれぞれ起動する
    • npm run express : API server (default, tcp/3000)
    • npm run serve : App dev server (default, tcp/8080)
  • production の場合
    • npm run build でビルド (packing)
    • npm run serve で App/API server を起動 (default, tcp/3000)

おまけ

for Heroku

ここまでできていればあとは Node/Express なアプリをデプロイするのと同じなのでそれほど困らないはず。

  • デフォルトでは vue-cli が生成した .gitignore に dist ディレクトリが入っているので注意
  • サーバのポート番号設定を Heroku にあわせる
const port = process.env.PORT || 3000
app.set('port', port)
  • heroku config:set NPM_CONFIG_PRODUCTION=false しておく。
    • Node.js now installs devDependencies by default ということなので特にいじってなければ問題ないです。package.json 見ればわかるんですが、npm run express は中で vue-cli-server を呼んでいます。で、このパッケージ類が devDependencies になってるんですよね。この辺いじると後々面倒だろうから素直に devDependencies 含めて全部パッケージ入れましょう。

vue-cli-plugin-express 以外の方法

vue-cli-plugin-express を使わない場合どうするか、というと…… Dev server 自体が express middleware になっているので、ソレを組み込んだサーバスクリプトを書き始めることになると思います。下記参照…。見ればわかるんですが、まあそれなりに面倒なので。express 周りに詳しい人はいろいろやれて良いのかもしれないけど。

46
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
37