内容
Vue.js + Spring Boot + HerokuでSPAを作成しました。
Vue.jsとSpring Bootは同じリポジトリ上で管理し、ビルドも同時に実施します。
それにより、最低限のソースコード管理とHerokuへのデプロイ時にまとめてビルドする状態を実現しました。
本記事は第一弾として、プロジェクト作成〜ビルドまでを紹介します。
Vue.js + Spring Boot + Heroku(はじめに 兼 まとめ)
Vue.js + Spring Boot + Heroku(プロジェクト作成~ビルド)
Vue.js + Spring Boot + Heroku(Herokuへデプロイ〜環境毎プロパティファイル作成)
Vue.js + Spring Boot + Heroku(認証作成 Spring Boot編)
Vue.js + Spring Boot + Heroku(認証作成 Vue編)
Vue.js + Spring Boot + Heroku(サンプルAPI作成)
前提
・Herokuに登録済であること。
・Heroku CLIがインストール済であること。
・SprintToolSuiteがインストール済であること。(プロジェクト作るだけ)
・IntelliJがインストール済であること。(IDEとして使うだけ)
・npmが使用可能であること。
・Vue-CLIがインストール済であること。
・ポート8080と8081が使用されていないこと。
ディレクトリ構成
src配下は下記の通りです。
vue配下にソースコード管理して、ビルド時にresorce/vue配下に生成しSpringが使用される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
├── main │ ├── java │ │ └── com │ └── resources │ ├── application.properties │ ├── static │ │ └── vue // Springに利用される。ビルド時に生成。(git管理対象外) │ │ ├── css │ │ ├── favicon.ico │ │ ├── img │ │ ├── index.html │ │ └── js │ └── templates ├── test │ └── java │ └── com └── vue //vueのソースコード(git管理対象) ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ ├── components │ └── main.js └── vue.config.js |
Spring Bootプロジェクト作成
Spring Bootのプロジェクトを作成します。
IntelliJで作成したかったのですが、(コミュニティだから?)作成するものが見当たらず、STS(Spring Tool Suite)で作成しました。
新規のワークスペースを作成し、「新しいSpringスターター・プロジェクトを作成する」から作成開始。
とりあえずデフォルト設定+(java11は用意してないので)java 8を指定。
Spring webを追加して完了をクリック。
STS(というかEclipse)は使いづらいので一旦終了。IntelliJ(コミュニティ版)で開発します。
IntelliJを開き、
Open or Importからdemo(作成したプロジェクトのディレクトリ)を指定
聞かれたらMaen projectを選択
DemoApplicationを右クリックし、RunすることでSpring bootを起動できます。
以降は右上の▶︎で起動できます。
Spring Bootの作成は一旦完了です。
Vueプロジェクトを作成
Vueの作成をします。事前にVue CLIをインストールしてください。
まずはコマンドラインからVue CLI UIを起動。
1 |
vue ui |
Vueプロジェクトマネージャで作成をクリック
「demo(プロジェクト名)/src」を開き、「ここに新しいプロジェクトを作成する」をクリック
プロジェクトフォルダに「vue」と入力して次へをクリック
デフォルトプリセットを選択して「プロジェクトを作成する」をクリック
プロジェクト作成後はVue用のディレクトリに配置したいので、設置→Vue CLI→公開パスに「/vue」を指定して変更を保存をクリック。
設定を完了するとvue.config.jsが作成されます。
package.jsonのscriptsを修正して、ビルド時の出力先を指定。
加えて、Vue CLIのローカルサーバのポートがSpring Bootと被るため8081へ変更。
1 2 3 4 5 |
"scripts": { "serve": "vue-cli-service serve --port 8081", "build": "vue-cli-service build --dest ../../src/main/resources/static/vue", "lint": "vue-cli-service lint" }, |
Spring BootのビルドでVueもビルドする
heroku gitによるソースコード管理は「.vue」ファイルのみにして、ビルドして生成される「.js」は管理せずにHerokuによるSpringのビルド時に一緒にビルドされ配置されることが理想的です。
pom.xmlへmavenでvueのビルドを追記。
参考:A Lovely Spring View: Spring Boot & Vue.js
ついでにlombokも追加
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>com.github.eirslett</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.10.0</version> <executions> <execution> <id>install node and npm</id> <goals> <goal>install-node-and-npm</goal> </goals> <configuration> <nodeVersion>v12.16.2</nodeVersion> <npmVersion>6.14.4</npmVersion> </configuration> </execution> <execution> <id>npm install --prefix ./src/vue/</id> <goals> <goal>npm</goal> </goals> <phase>generate-resources</phase> <configuration> <arguments>install --prefix ./src/vue/</arguments> </configuration> </execution> <execution> <id>npm run build --prefix ./src/vue/</id> <goals> <goal>npm</goal> </goals> <configuration> <arguments>run build --prefix ./src/vue/</arguments> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
右側のMavenタブを開き、グルグルマーク(Reload All Maven Projects)をクリック
src > main > java > com.example.demo配下にBaseController.javaを作成して設定。
BaseController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; /** * VueのSPAを返す。存在しないURLへのアクセス時はHtml5HistoryModeResourceConfigで返す。 */ @Controller public class BaseController { @GetMapping(path = "/") public String getSpa() { return "forward:vue/index.html"; } } |
historyモードを実現する場合、API以外のURLに対するアクセスはSPAを返却する必要があるため、存在しないULRへのアクセスは固定でファイルを返すよう指定。
参考:SPA(Nuxt.js)をSpring Bootからホストする方法
src > main > java > com.example.demo配下にHtml5HistoryModeResourceConfig.javaを作成。
Html5HistoryModeResourceConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.web.ResourceProperties; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.resource.PathResourceResolver; import java.io.IOException; /** * 対応しないURLの場合、固定ページを返す。 * https://qiita.com/yushi_koga/items/65e94a97af1d0b0dc8b1 */ @RequiredArgsConstructor @Configuration public class Html5HistoryModeResourceConfig implements WebMvcConfigurer { private final ResourceProperties resourceProperties; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**") // 全パスをこのリソースハンドラーの処理対象にする .addResourceLocations(resourceProperties.getStaticLocations()) // 静的リソース配置先のパスを指定する .resourceChain(resourceProperties.getChain().isCache()) // 開発時はfalse、本番はtrueが望ましい。trueにしておくとメモリ上にキャッシュされるためI/Oが軽減される .addResolver(new SpaPageResourceResolver()); // 拡張したPathResourceResolverを読み込ませる } public static class SpaPageResourceResolver extends PathResourceResolver { @Override protected Resource getResource(String resourcePath, Resource location) throws IOException { Resource resource = super.getResource(resourcePath, location); // まずはPathResourceResolverで静的リソースを取得する return resource != null ? resource : super.getResource("/vue/index.html", location); // 取得できなかった場合は、index.htmlを返す } } } |
右側のmavenタブを開き、cleanとinstallを実行してVueをビルド。
【追記】windows環境の場合、npmコマンドの–prefixオプションが意図した動作をしません。手動でのビルドが必要です。
1 2 3 |
cd src/vue npm install npm build |
Spring Boot起動中の場合は一旦終了(■マーク)し、Spring Bootを起動(▶︎マーク)してサーバを起動。http://localhost:8080/へアクセスし、トップページを確認。
demo配下の.gitignoreへ追記
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
HELP.md target/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/** !**/src/test/** .DS_Store # vue dist directory src/main/resources/static/vue # frontend-maven-plugin node/ node_modules/ ### STS ### .apt_generated .classpath .factorypath .project .settings .springBeans .sts4-cache ### IntelliJ IDEA ### .idea *.iws *.iml *.ipr ### NetBeans ### /nbproject/private/ /nbbuild/ /dist/ /nbdist/ /.nb-gradle/ build/ ### VS Code ### .vscode/ |