使用Nuxt.js和SpringBoot开始SPA/API服务器开发和部署
我整理了使用Nuxt.js v2创建SinglePageApplication(简称为SPA)和使用SpringBoot v2创建API服务器的组合进行Web应用程序开发时的环境设置以及部署到Netlify/Heroku的步骤。主要是针对Nuxt.js v2和SpringBoot v2的组合进行说明。
在建立之前
假设以下软件已经安装完毕。
-
- Node.js v10
-
- Java Development Kit(以下、JDK) 16
- Maven v3
另外,我们假设您已经创建了Netlify/Heroku的账户。
目录结构
假设我们采用一种单个目录结构,将Nuxt.js应用程序放置在「assets」目录中,并将Maven格式的Spring Boot应用程序放置在「server」目录中。
.
├── assets
│ ├── node_modules
│ ├── nuxt.config.js
│ ├── package.json
│ ...
│
└── server
├── pom.xml
├── src
...
创建开发环境
我們將使用Nuxt.js和SpringBoot創建一個可以進行熱重載的環境。
+-------------+
+------------+ /api | |
| +------------------->| Spring Boot |
| | localhost:8080 | |
| Nuxt.js | +-------------+
-------------->| Dev Server |
localhost:3000 | |
| |
+------------+
设置只允许从Web应用程序使用者访问localhost:3000,这样就不需要处理跨域相关的事项了。这个配置的要点有两点。
-
- /api へのリクエストは Nuxt.js Dev Server が localhost:8080 で動作している SpringBoot に転送(Proxy)し、SpringBoot が処理する。
- その他の URL へのリクエストは、静的リソースへのアクセスとして Nuxt.js 開発サーバが処理する。
创建 Nuxt.js 应用
请安装Nuxt应用程序生成器create-nuxt-app。
$ npm i -g create-nuxt-app
由于我想将Nuxt.js应用程序的源代码放置在assets文件夹下,所以我将应用程序命名为assets并创建Nuxt应用程序。您将被询问要使用的框架,您可以根据喜好进行选择。在”Choose rendering mode”中选择”Single Page App”,在”Use axios module”中选择”yes”。
$ create-nuxt-app assets
> Generating Nuxt.js project ...
? Project name [assets]
? Project description [My sublime Nuxt.js project]
? Use a custom server framework [none]
? Use a custom UI framework [none]
? Choose rendering mode [Single Page App]
? Use axios module [yes]
? Use eslint [yes]
? Use prettier [yes]
? Author name []
? Choose a package manager [npm]
如果在「选择渲染模式」中选择「Universal」,则可以进行服务器端渲染。由于在服务器端进行渲染,会给服务器增加负担,因此在实现服务器端渲染时需要注意一些事项,不适合快速开发。而「Single Page App」是仅在浏览器端进行渲染的模式,对服务器友好,且在应用开发中的限制较少,因此选择这个模式。
「使用axios模块」是一个可以简化异步的HTTP(S)通信的模块。它是与API服务器通信所必需的。
Nuxt.js 应用的配置
为了将对 localhost:3000/api 的访问转发到 localhost:8080/api(SpringBoot),请在Nuxt.js应用程序中添加代理模块。请进入 “assets” 文件夹并添加 “@nuxtjs/proxy” 模块。
$ npm i --save @nuxtjs/proxy
在 Nuxt.js 中,assets/nuxt.config.js 是配置文件。为了识别 Proxy 模块,请在此文件的 “modules” 部分添加 “@nuxtjs/proxy”。
modules: [
// Doc: https://github.com/nuxt-community/axios-module#usage
- '@nuxtjs/axios'
+ '@nuxtjs/axios',
+ '@nuxtjs/proxy'
],
进行axios模块的配置。”credentials”选项是用于指示在进行HTTP通信时是否传递cookie等敏感信息的选项。本文不涉及此部分,但在创建仅能在已登录情况下访问的API时会用到。”proxy”选项在与proxy模块一起使用时需要进行配置。
axios: {
// See https://github.com/nuxt-community/axios-module#options
+ credentials: true,
+ proxy: true
},
接下来将进行 axios 模块的设置。
将对 localhost:3000/api 的访问转发至 localhost:8080/api (SpringBoot)。
有一个故事,我们在这里进行设置。另外,在代理下运行Spring Boot时,需要通过“X-Forwarded-Host”头部传递原始主机名。下面将解释为什么需要这样做。
+
+ proxy: {
+ '/api/': {
+ target: 'http://localhost:8080',
+ headers: { 'X-Forwarded-Host': 'localhost:3000' }
+ }
},
为什么需要 X-Forwarded-Host 头部
在使用Spring Boot运行在代理服务器下时,需要通过”X-Forwarded-Host”头信息来告知原始主机名的原因。
HTTP 301, 303在Location头部执行重定向,但根据HTTP规范,可以指定在Location头部的URL应是绝对路径。在RFC2616日本语翻译14.30 Location中有详细说明。据认为,Spring Boot(基于Spring Framework)也符合这一规范。因此,使用Spring Boot进行重定向处理时,会将重定向定向到以http://localhost:8080/开头的URL。
因此,可以通过在Spring Boot中使用”X-Forwarded-Host”头来通知原始主机名,而不是自己正在运行的主机名,以便构建基于转发源主机名的重定向URL,并将操作重定向到以”http://localhost:3000/”开头的URL。实际上,在构建URL的org.springframework.web.util.UriComponentsBuilder类中,如果有”X-Forwarded-Host”头的指定,就会有使用指定的主机名来构建URL的处理过程。实际的源代码
创建Spring Boot应用程序
我将以Maven项目的形式编写Spring Boot应用程序。像往常一样,我们将使用”spring-boot-starter-parent”作为父项目。在这里,我们决定创建一个简单的API服务器,它仅返回请求时间的接口:”/api/time”。为了创建一个RESTful的WebAPI,我们将在Maven的dependencies中添加”Spring MVC”和”Developer Tools”,以便实现热重载。在JDK9中,对内部API的访问进行了限制的行为更改。由于在JDK9及更高版本的JDK上运行旧的SpringBoot版本会导致错误发生,请尽量使用更新的SpringBoot版本。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>com.example.server</artifactId>
<version>1.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<parent>
<!-- Spring Core -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
</parent>
<dependencies>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Developer Tools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
由于Spring Boot在创建RESTful WebAPI方面有很多详细说明,因此我在此省略了具体讲解。
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] arguments) {
SpringApplication.run(Application.class, arguments);
}
}
package com.example.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@RestController
public class TimeController {
@RequestMapping("/api/time")
public Map<String, String> index() {
Map<String, String> response = new HashMap<>();
response.put("date", new Date().toString());
return response;
}
}
如何开始开发
启动 Nuxt.js 开发服务器。
$ npm run dev
用另一个终端启动Spring Boot。
$ mvn spring-boot:run
目前两个都以启用热重载的状态启动。为了确认热重载是否可行,我们将尝试在主页上显示从 “/api/time” 获取的日期和时间。保存并按以下方式重写后,Nuxt.js 的热重载功能将立即重新加载并反映这些更改。
<template>
<h1>{{ date }}</h1>
</template>
<script>
module.exports = {
data() {
return {
date: ''
}
},
async asyncData({ app }) {
const response = await app.$axios.get('/api/time')
console.log(response.data.date)
return { date: response.data.date }
}
}
</script>
<style>
</style>
部署
本文介绍了将SPA部署到Netlify以及将Spring Boot应用部署到Heroku的方法。
+-----------------+
+------------+ /api | |
| +------------------->| Spring Boot |
| | | (Heroku Server) |
| Netlify | | |
-------------->| Web Server | +-----------------+
| |
| |
+------------+
将开发环境配置与原始一致。
-
- Netlify の Web サーバの /api へのリクエストは Heroku サーバで動作する SpringBoot の /api に転送して、SpringBoot が処理する。
- その他の URL へのリクエストは、静的リソースへのアクセスとして Netlify の Web サーバが処理する。
将代码部署到Netlify。
Netlify是一个提供静态网站托管服务的平台。它不仅可以简单地进行托管,还可以与git存储库进行集成,实现自动构建等功能。此外,还可以通过netlify.toml配置文件进行自定义。虽然无法进行服务器端渲染(SSR),但作为SPA的部署目标,其具备足够的功能。
以下将解释在 SPA/API 服务器配置情况下,通过 netlify.toml 文件进行设置的方法。需要注意的有两点。
-
- API サーバの設定では、転送対象のパスと転送先だけでなく、「X-Forwarded-Host」ヘッダでオリジナルサーバのホスト名も送るように設定します。
- 「/」以外の URL へ直接アクセスした場合はトップページと同じ内容を返すように設定します。この設定がないと「/」以外の URL に直接アクセスすると 404 NotFound です。
# APIサーバの設定
[[redirects]]
from = "/api/*"
to = "https://<あなたのherokuホスト名>/api/:splat"
status = 200
[redirects.headers]
X-Forwarded-Host = "<あなたのnetlifyホスト名>"
# SPAの設定
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
以下是向 Netlify 部署的步骤。请确保已经安装了 Netlify 命令行工具。
$ npm install -g netlify-cli
此外,我会打开一个新的终端,并确保已登录到Netlify。
$ netlify login
执行构建命令在「assets」文件夹中,会在「assets/dist」文件夹中生成 SPA 应用程序。
$ npm run build
使用Netlify命令将“dist”目录部署。如果是第一次部署,可能会询问您一些问题,请根据您的喜好回答。
$ netlify deploy
将应用程序部署到Heroku
Heroku 是一个能够托管 Java、Ruby、Node.js 服务器应用的服务。
有几种方法可以将应用部署到Heroku,常见的是将Heroku应用的Git存储库推送到部署。但是,本次我们将使用Maven来进行部署。由于该项目将Maven项目配置在顶层目录下的子目录中,因此部署会变得困难。
Maven 通过使用「heroku-maven-plugin」来部署到Heroku平台。
-
- jdkVersion タグの中にはお使いの JDK バージョン
- web タグの中には JavaVM オプション
如果您有使用Heroku的经验,可能曾经编写过Procfile文件。但是,如果您想使用”heroku-maven-plugin”,则无需创建此文件。
</dependencies>
+ <build>
+ <plugins>
+ <!-- Heroku deploy settings -->
+ <plugin>
+ <groupId>com.heroku.sdk</groupId>
+ <artifactId>heroku-maven-plugin</artifactId>
+ <version>2.0.6</version>
+ <configuration>
+ <jdkVersion>1.8</jdkVersion>
+ <processTypes>
+ <web>java -Duser.language=ja -Duser.country=JP -Duser.timezone=Asia/Tokyo -jar ./target/com.example.server-1.0.jar</web>
+ </processTypes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
- 「-jar ./target/com.example.server-1.0.jar」
使用Maven进行构建时,将生成包含Spring Boot本身和您编写的应用程序的JAR文件,该文件位于“target/com.example.server-1.0.jar”。这意味着执行该文件。
- 「-Duser.language=ja -Duser.country=JP -Duser.timezone=Asia/Tokyo」
这是将语言、时区等(即所谓的本地区)设置为日本的选项。
请设置环境变量“HEROKU_API_KEY”,然后进行构建和部署。可在https://dashboard.heroku.com/account页面找到环境变量“HEROKU_API_KEY”的相关信息。
$ HEROKU_API_KEY=<APIキー> mvn clean install heroku:deploy -Dheroku.appName=<herokuアプリ名>
结束时
Nuxt.js和Spring Boot都有很多解說網站和書籍,可以輕鬆開始使用。
通過使用Netlify和Heroku來執行,現在可以輕鬆地將Web服務公開。
在這裡所介紹的內容都可以在免費範圍內完成,所以大家也一定要試試看。