Gradle で Multi-project を作成する ( その15 )( vuejs+springboot編、frontend-app プロジェクトを作成する )
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
- frontend を Vue.js で、backend を Spring Boot でアプリケーションを実装し、各アプリケーションをサブプロジェクトとする Gradle Multi-project のサンプルを作成します。
- 今回は Vue.js のアプリケーション(frontend)を作成し、gradle build で実行可能 jar にまとめます。
参照したサイト・書籍
Vuetify
https://vuetifyjs.com/en/How to build a web app with Vue, Vuetify and Axios
https://medium.com/javascript-in-plain-english/implement-movie-app-with-vue-vuetify-axios-open-movie-database-api-d12290318cf9axios、async/awaitを使ったHTTPリクエスト(Web APIを実行)
https://qiita.com/shisama/items/61cdcc09dc69fd8d3127async関数においてtry/catchではなくawait/catchパターンを活用する
https://qiita.com/akameco/items/cc73afcdb5ac5d0774bcVue.jsでビューの変更がされないときに疑うこと+主な解決策方法
https://cloudpack.media/41984Vue Test Utils
https://vue-test-utils.vuejs.org/Vue.jsのテストでコンポーネントをいい感じにwrapする方法
https://qiita.com/ykhirao/items/8e8a9547a693c677813cVue CLI - Configuration Reference - devServer.proxy
https://cli.vuejs.org/config/#devserver-proxyGradle Docs - The Base Plugin
https://docs.gradle.org/current/userguide/base_plugin.htmlnode-gradle/gradle-node-plugin
https://github.com/node-gradle/gradle-node-pluginnode-gradle/gradle-node-plugin - Node Plugin
https://github.com/node-gradle/gradle-node-plugin/blob/master/docs/node.md
目次
- Vue.js のアプリケーション(frontend)(frontend-app)を作成する
- Gradle の build タスク実行時に
npm run test:unit
、npm run build
が実行されるようにする - Gradle の build タスク実行時に frontend-app の dist ディレクトリの下にあるファイルを backend-app の src/main/resources/static にコピーする
- settings.gradle に sample-cmdapp プロジェクトの include 文を追加する
- clean タスク実行 → Rebuild Project 実行 → build タスク実行を行う
- 実行可能 jar から Tomcat を起動して動作確認する
- 次回は。。。
手順
Vue.js のアプリケーション(frontend)(frontend-app)を作成する
Vue CLI をインストールする
以下のコマンドを実行して Vue CLI をインストールします。
npm install -g @vue/cli
npm install -g @vue/cli-service-global
以下の警告メッセージが出ていますが、TypeScript、GraphQL は使用しないので今回は何もしません。
ts-node@8.1.0 requires a peer of typescript@>=2.0 but none is installed.
apollo-tracing@0.5.2 requires a peer of graphql@0.10.x - 14.1.x but none is installed.
インストールされた Vue CLI のバージョンを vue --version
コマンドで確認すると 3.7.0 でした。
Vue CLI で frontend-app プロジェクトを作成する
コマンドラインから vue create frontend-app
を実行して frontend-app プロジェクトを作成します。
※「Please pick a preset:」では「Manually select features」を選択します。
※「Check the features needed for your project:」はデフォルトで「Babel」「Linter / Formatter」が選択済みで、「Unit Testing」を追加で選択します。
※「Pick a linter / formatter config:」では「ESLint + Prettier」を選択します。
※「Pick additional lint features:」はデフォルトで「Lint on save」が選択済みで、そのままにします。
※「Pick a unit testing solution:」では「Jest」を選択します。
※「Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? (Use arrow keys)」では「In dedicated config files」を選択します。
※「Save this as a preset for future projects? (y/N)」は何も入力せずに Enter キーを押します。
インストールが実行されます。
インストール後 frontend-app ディレクトリに移動してから npm run serve
コマンドを実行して、
http://localhost:8080/ にアクセスすると画面が表示されました。
npm run build
コマンドを実行すると、警告・エラーは出ずに終了します。
IntelliJ IDEA の Project Tool Window で frontend-app のディレクトリ構成を見てみると以下のようになっていました。尚、IntelliJ IDEA で最初に表示させる時には「Indexing…」のメッセージが表示されてしばらく時間がかかります(おそらく node_modules の下の大量のファイルを index するのに時間がかかっているためでしょう)。
Vuetify をインストールする
Quick start の記述に従い vue add vuetify
コマンドを実行します。
※「Choose a preset: (Use arrow keys)」はデフォルトの「Default (recommended)」のままにします。
インストール直後の状態で npm run build
コマンドを実行すると prettier のフォーマットと異なるために eslint が警告を大量に出すので、npm run build
コマンド実行時に prettier で自動フォーマットして警告が出ないようにします。
npm run build
、npm run lint
、npm run test:unit
実行時に prettier で自動フォーマットするよう設定する
npm install --save-dev npm-run-all
コマンドを実行して npm-run-all をインストールします。
frontend-app/package.json の "scripts": { ... }
を以下のように変更します。
"scripts": { "serve": "vue-cli-service serve", "build": "run-s prettier:format vue-cli-service:build", "lint": "run-s prettier:format vue-cli-service:lint", "test:unit": "run-s prettier:format vue-cli-service:test:unit", "vue-cli-service:build": "vue-cli-service build", "vue-cli-service:lint": "vue-cli-service lint", "vue-cli-service:test:unit": "vue-cli-service test:unit", "prettier:format": "prettier --write {src,tests}/**/*.{js,vue}" },
- 以下の4行を追加します。今回初めて知りましたが、Paste した時に Paste した行や1つ上の行の末尾に "," がないと IntelliJ IDEA が自動で付けてくれますね。
"vue-cli-service:build": "vue-cli-service build"
"vue-cli-service:lint": "vue-cli-service lint"
"vue-cli-service:test:unit": "vue-cli-service test:unit"
"prettier:format": "prettier --write {src,tests}/**/*.{js,vue}"
"build": "vue-cli-service build"
→"build": "run-s prettier:format vue-cli-service:build"
に変更します。"lint": "vue-cli-service lint"
→"lint": "run-s prettier:format vue-cli-service:lint"
に変更します。"test:unit": "vue-cli-service test:unit"
→"test:unit": "run-s prettier:format vue-cli-service:test:unit"
に変更します。
以上で設定は完了です。再度 npm run build
コマンドを実行してみると2件 warning が出ていますが Build complete. が表示されました。
2件の warning はファイルサイズや lazy load に関するものでしたので、今回は解消せずに先に進みます。
また IntelliJ IDEA 上でも prettier でフォーマットできるように設定します。メインメニューから「File」-「Settings...」を選択して「Settings」ダイアログを表示させた後、画面右上に prettier
と入力して Prettier Plugin の設定画面を開いてから、画面右側の「Prettier package」に frontend-app/node_modules/prettier の絶対パスを設定します。
WebAPI を呼び出して取得したデータを画面に表示する処理を実装する
WebAPI を呼び出すのに axios を使用するので npm install --save axios
コマンドを実行してインストールします。
frontend-app/src/components/HelloWorld.vue のファイル名を CallSampleWebapi.Vue に変更します。
frontend-app/src/App.vue を以下のように変更します。
<template> <v-app> <v-content> <CallSampleWebapi /> </v-content> </v-app> </template> <script> import CallSampleWebapi from "./components/CallSampleWebapi"; export default { name: "App", components: { CallSampleWebapi: CallSampleWebapi }, data() { return { // }; } }; </script>
<v-toolbar app>...</v-toolbar>
を削除します。HelloWorld
→CallSampleWebapi
に一括置換します。
frontend-app/src/components/CallSampleWebapi.Vue を以下のように変更します。
<template> <v-container> <v-layout text-xs-center wrap> <v-flex xs12> <div>code: {{ code }}</div> <div>value: {{ value }}</div> <v-btn color="info" v-on:click="callSampleWebapi">クリック!</v-btn> </v-flex> </v-layout> </v-container> </template> <script> import axios from "axios"; export default { data: function() { return { code: "(空)", value: "(空)" }; }, methods: { callSampleWebapi: async function() { try { const response = await axios.post("/webapi/sample"); this.$set(this, "code", response.data.code); this.$set(this, "value", response.data.value); } catch (err) { alert(err); } } } }; </script> <style></style>
frontend-app/tests/unit/example.spec.js もファイル名を CallSampleWebapi.spec.js に変更した後、以下の内容に変更します。
import { mount } from "@vue/test-utils"; import Vue from "vue"; import Vuetify from "vuetify"; import CallSampleWebapi from "@/components/CallSampleWebapi.vue"; describe("CallSampleWebapi.vue test", () => { it("init render test", () => { Vue.use(Vuetify); const wrapper = mount(CallSampleWebapi, {}); expect(wrapper.html()).toContain("<div>code: (空)</div>"); }); });
vue.config.js を作成して webpack-dev-server に proxy の設定を追加する
npm run serve
コマンドで起動した webpack-dev-server に http://localhost:8080/webapi/sample でアクセスしたら backend-app の http://localhost:8081/webapi/sample へリクエストを転送させるための設定を行います。
frontend-app の下に vue.config.js を新規作成した後、以下の内容を記述します。changeOrigin: true
を記述すると backend-app 側で @RestController
アノテーションを付与したクラスに @CrossOrigin
アノテーションを付与して設定しなくてもアクセスできるようになります。
module.exports = { devServer: { proxy: { "^/webapi/sample": { target: "http://localhost:8081", changeOrigin: true } } } };
動作確認
backend-app の Tomcat を develop profile で起動してから、
npm run serve
コマンドを実行して frontend-app の webpack-dev-server を起動した後、
http://localhost:8080/ にアクセスすると以下の画面が表示されます。
「クリック!」ボタンをクリックすると backend-app の WebAPI を呼び出して取得した code, value の値が画面に表示されました。
Tomcat、webpack-dev-server を停止します。
npm run test:unit
コマンドを実行するとテストも成功します。
npm run build
コマンドも2件の warning は出たままですが、他の警告・エラーは出ずに Build complete. が表示されました。
Gradle の build タスク実行時に npm run test:unit
、npm run build
が実行されるようにする
frontend-app ディレクトリの下に build.gradle を新規作成し、以下の内容を記述します。
plugins { id "base" id "com.github.node-gradle.node" version "1.3.0" } clean.delete "dist" task npmTestUnit(type: NpmTask) { args = ["run", "test:unit", "2>&1"] execOverrides { it.standardOutput = new ByteArrayOutputStream() } } task npmBuild(type: NpmTask) { args = ["run", "build", "2>&1"] execOverrides { it.standardOutput = new ByteArrayOutputStream() } } npmBuild.dependsOn npmTestUnit build.dependsOn npmBuild
id "base"
を記述することで clean や build タスクが使えるようになります。npm run ...
コマンドの実行には gradle-node-plugin を使用します。- args に
"2>&1"
を指定して標準エラー出力を標準出力にリダイレクトし、execOverrides { it.standardOutput = new ByteArrayOutputStream() }
を記述することで標準出力、標準エラー出力に何も出力されないようにします。
ちなみに標準出力、標準エラー出力の内容をファイルに出力したい場合には、以下のように記述すれば frontend-app/build/tests/stdout.txt に出力されます。
task npmTestUnit(type: NpmTask) { args = ["run", "test:unit", "2>&1"] def testsDir = "${projectDir}/build/tests" execOverrides { // it.standardOutput = new ByteArrayOutputStream() it.standardOutput = new FileOutputStream("${testsDir}/stdout.txt") } doFirst { mkdir testsDir } }
Gradle の build タスク実行時に frontend-app の dist ディレクトリの下にあるファイルを backend-app の src/main/resources/static にコピーする
backend-app/build.gradle を以下のように変更します。
.......... dependencies { .......... } clean.delete fileTree("src/main/resources/static").include("**/*") task copyDistToStatic(type: Copy) { from project(":frontend-app").file("dist") into "src/main/resources/static" } copyDistToStatic.dependsOn ":frontend-app:build" processResources.dependsOn copyDistToStatic
clean.delete fileTree("src/main/resources/static").include("**/*")
~processResources.dependsOn copyDistToStatic
の記述を追加します。
settings.gradle に frontend-app プロジェクトの include 文を追加する
gradle-multiprj-vuejs-springboot の settings.gradle に include 'frontend-app'
を追加します。
rootProject.name = 'gradle-multiprj-vuejs-springboot' include 'backend-app' include 'frontend-app'
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。Gradle Tool Window に frontend-app が表示されます。
clean タスク実行 → Rebuild Project 実行 → build タスク実行を行う
clean タスクを実行すると backend-app は src/main/resources/static の下がクリアされて、frontend-app は dist ディレクトリが削除されます。
build タスクを実行すると警告・エラーは出ずに BUILD SUCCESSFUL が表示されて、
frontend-app の dist ディレクトリの下のディレクトリ・ファイル一式が backend-app の src/main/resources/static の下にコピーされます。
実行可能 jar から Tomcat を起動して動作確認する
backend-app/build/libs の下に backend-app-1.0.0-RELEASE.jar が生成されていますので、
コマンドラインから java -Dspring.profiles.active=product -jar backend-app-1.0.0-RELEASE.jar
を実行します。
http://localhost:8080/ にアクセスすると以下の画面が表示されて、
「クリック!」ボタンをクリックすると WebAPI を呼び出して取得したデータが画面に表示されました。
次回は。。。
frontend-app の下に作成した build.gradle のタスクを build タスク実行時に動かすための The Base Plugin を見つけるまでが意外に時間がかかりました。書いてある記事が少ないのか、なかなか見つけられなかったんですよね。。。
これでとりあえずやりたいことは全てやったので、最後に感想を書いて終わりにします。
履歴
2019/05/08
初版発行。