使用GAE和Angular创建普通的SPA的方法〜入门指南
首先
-
- Google App Engine をバックエンドサーバーとして動く普通の Angular アプリケーションの作り方を紹介していく。
- 今回は導入編としてアプリケーションのひな形を作って通信ができるだけのところまでやってみる。
准备
-
- Go, Node.js のインストール
Google Cloud SDK のインストール
GAE のローカル開発サーバーなどが入っているので公式ドキュメントの通りにインストールする
Angular CLI のインストール
Angular CLI を使って Angular プロジェクトの初期化や管理ができるのでREADME.mdに従ってインストールする
创建项目根目录
-
- $GOPATH の通っているディレクトリにプロジェクトルートを作成する
- 以下は github.com で公開し、ユーザー名が you で、プロジェクト名が gae-angular-sample の場合のプロジェクトルートディレクトリの作成
mkdir -p $GOPATH/src/github.com/you/gae-angular-sample/{server,client}
创建GAE应用程序的模板
-
- GAE アプリのひな形としては、HTTP リクエストを処理するメインの go ファイルと、設定用の yaml が必要になる
- メインの Go ファイルとして “/” へのリクエストで “hello world” と出力するだけの HTTP ハンドラの定義された server/gae/app.go を作成する
package main
import (
"net/http"
"fmt"
)
func init() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "hello world")
})
}
- 設定用の Yaml として全リクエストを前記の Go ファイルで処理するように定義した server/gae/app.yaml を作成する
runtime: go
api_version: go1.8
handlers:
- url: /.*
script: _go_app
启动开发服务器
- Cloud SDK に入っている dev_appserver.py コマンドで開発サーバーを立ち上げる
cd server/gae
dev_appserver.py app.yaml
-
- 起動ログに表示される通り http://localhost:8080 で立ち上げたアプリケーションへアクセスできる
- これも起動ログにあるが http://localhost:8000 で管理用のサーバーにアクセスすることができ、開発用にエミュレートされた Google Datastore などを操作することができる
创建Angular应用程序的模板
- Angular CLI を使ってひな形を作成する
# プロジェクトルートヘ
cd $PROJECT_ROOT
# client という名前でひな形の作成
ng new client
# 依存パッケージのインストール
cd client && npm install
启动Angular应用程序的开发服务器。
npm start
http://localhost:4200 でクライアントの開発サーバーへアクセス
在同一个主机上提供 GAE 应用程序和 Angular 应用程序。
-
- GAE と Angular でそれぞれ開発サーバーを立ち上げると、それぞれ別ドメインとして動作してしまい Cookie などを共有することができずに面倒な場合がある
- ここでは Angular アプリのソースをビルドして GAE アプリで提供することで同一ドメインで動作させる
Angular 应用程序的构建
- 下記の通り client/package.json に GAE アプリ用のビルドスクリプトを追加する
{
...
"scripts": {
...
"build:gae": "ng build --prod --output-path=../server/gae/client/ --base-href=/client/"
- ビルドスクリプトを実行して server/gae/client にビルド後のソースがコピーされていることを確認する
npm run build:gae
在GAE应用程序中提供Angular应用程序的文件
-
- GAE アプリの設定ファイルを変更してビルドした Angular アプリのファイルを静的ファイルとして提供する
- 以下のように “handlers” 要素に “/client/” 以下の静的ファイルを提供する設定と、それ以外の “/client/.*” で “/client/index.html” を提供する設定を追加する
runtime: go
api_version: go1.8
handlers:
- url: /client/(.*\.(gif|png|jpeg|jpg|css|js|ico))$
static_files: client/\1
upload: client/(.*)
- url: /client/(.*)
static_files: client/index.html
upload: client/index.html
- url: /.*
script: _go_app
- GAE 開発サーバーを起動し http://localhost:8080/client/ で Angular アプリが立ち上がるのを確認する
自动重新构建
- ビルドコマンドにオプションを足すとファイル変更を検知してリビルドしてくれる
npm run build:gae -- --watch
从 Angular 应用程序与 GAE 应用程序进行通信
给GAE应用添加通信接口
-
- パラメータを受けて動的な結果を返す HTTP ハンドラを定義する。
- パラメータの bind と JSON のレスポンスなどウェブサーバーではおなじみの処理を手軽に実装したいのでウェブアプリケーションフレームワーク echo を利用する
package main
import (
"github.com/labstack/echo"
"net/http"
)
func init() {
// 軽量なウェブアプリケーションフレームワーク echo を使う
// 素の net/http に比べてパラメータの bind や Json の出力を便利になる
e := echo.New()
// ルート定義
e.GET("/hello", helloHandler)
// 全リクエストを echo で処理する
http.Handle("/", e)
}
// helloHandler のリクエスト
type helloRequest struct {
// クエリストリングの name 要素を受け取る
Name string `query:"name"`
}
// helloHandler のレスポンス
type helloResponse struct {
Message string
}
// echo のハンドラ型を定義
func helloHandler(c echo.Context) error {
// 入力を受け取って構造体に入れる
req := new(helloRequest)
c.Bind(req)
// ステータスコード 200 で JSON を返す
return c.JSON(http.StatusOK, helloResponse{
Message: "hello " + req.Name,
})
}
- 追加したライブラリをインストールして開発サーバーを起動する
go get github.com/labstack/echo
cd server/gae
dev_appserver.py app.yaml
使用Angular应用程序与GAE应用程序进行通信
-
- Angular で HTTP 通信をする場合は @angular/common/http の HttpClient を利用する
- HttpClient を DI できるように AppModule に HttpClientModule を追加する
import { AppComponent } from './app.component';
+import {HttpClientModule} from "@angular/common/http";
@NgModule({
declarations: [
AppComponent
],
imports: [
+ HttpClientModule,
BrowserModule
],
-
- AppComponent 初期化時に通信を行う
コンストラクタで HttpClient を DI で初期化し GET リクエストを送信、console.log で結果を表示する
レスポンスの型 helloResponse は事前に定義する
interface helloResonse {
Message: string
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(private http: HttpClient) {
this.http.get<helloResonse>("/hello?name=bob").subscribe(
res => console.log(res)
);
}
}
最后
- 実コードはリポジトリを参照のこと