S3
DynamoDB
CloudFront
lambda
Angular2

サーバレスでAngular2のサービスを作った話

More than 1 year has passed since last update.

前置き

静的ファイルをS3に置いて、APIをLambdaに書いたらサーバレスでサービス出来るやん!と思いやってみた。
まだまだよく分かってない事が多いけど、とにかく調べ物したときに英語ばっかで泣きそうになったので、このノウハウが少しでも役に立てればと。
AWS関連の構成に関してはこっちにも書いてます。
AWS完結でサーバレス構成のWebアプリ(SPA)を作ったときに使ったAWSサービスたち

結果

html、js、css、imageといった静的ファイルをS3に配置、CloudFrontを活用。
LambdaとDynamoDBでAPIを作成。
という構成で一応サービスは出来た。

以下、回想

※起きた問題が山ほどあるけどとりあえず列挙

ビルド環境の構築よく分からない問題(Angular2導入で躓く)

Angular1系は触った事あったものの、世は2系の時代っぽいので2を導入する事に。(後から知ったけどもはや4出ててそろそろ5が出そうな事に衝撃。というかもう出てる?)
いろいろなサイトに、もはや別物との記載が多数あったが、実際に触ってみるとなかなか違った。
TypeScriptも触った事がなく、Componentとか諸々Angular2の概念を把握するのに苦戦。
そしてビルド関係にもっと苦戦。
そしてそしてちょこっとしたものの調べ物をするとほとんど英語で超苦戦。

Angular2のチュートリアル
いろいろ調べてたら、ビルドしなくてもロード時にトランスパイルする形式で動作確認出来る事が分かったので、ビルド環境出来るまではこれ方式で開発をスタート。
ちなみに上のサイトの各チュートリアルコードはPlunkerで開けるが、プロジェクトのところでダウンロードしたコードはnode.jsで動かす前提のコードになってるので、そのまま動かしてみようとしても動かない。
何言ってるか分からないと思うけど、とりあえずエディタ部分に書いてるソースをコピペしないとダメ。

起動までのスピード的な問題でいくと

S3だけを使っているきは、ロード時トランスパイル形式で10秒ほど、ビルド形式だと30秒ほど。
CloudFront経由にしたときは、ビルド形式が5秒ほど。

なので、ビルドしてデプロイしてCloudFrontをリフレッシュ、するよりは、デプロイしてロード時トランスパイル形式で開発した方が、動作確認時のストレスは少ないのではと思った。

肝心のビルド環境の方は

Angular2の開発環境を構築する
こことかnpmインストール関連のサイトを参考にしてなんとか構築…
EC2に(爆

最終的にローカルに持ってこようと思ってたんだけど、めんどくさくなって環境構築練習してたEC2の環境をそのまま活用中。
真のサーバレスとは言えない現状に涙。

ちなみに上の記事のビルドコマンドだと、environments/environment.tsの中身のパラメータがfalseだと、エラーになる。
--prodを削除すべし。
※trueにして--prodつけてビルドすると出来上がったソースコードがスッキリしてた(何がどうなったのかは分からない)

ページ追加ってどうすればいいの問題

app.module.tsに対象のcomponentをimport。
@NgModuleのdeclarationsに、componentを追記。

app.module.ts
import { HogeComponent }        from './hoge.component'; // ←これと

@NgModule({
    imports: [
       
    ],
    declarations: [
        
        HogeComponent // ←これ
    ],
    providers: [
    ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

あとルーティングの設定。
app.module.tsに対象のcomponentをimport。
RoutesにpathとComponentのセットを追記。

app-routing.module.ts
import { HogeComponent }        from './hoge.component'; // ←これと

const routes: Routes = [
    
    { path: 'hoge',       component: HogeComponent }, // ←これ
];

これでtsに

this.router.navigate(["/hoge"]);

とかhtmlに

<a routerLink="/hoge" routerLinkActive="active"></a>

とかすれば、HogeComponentが呼ばれる。
慣れればなんの事はない事なんだけど、慣れないと何をどうしたら動くか分からずに本当に途方にくれる。

ルーティングのURLがNot Foundになる問題

回避策があるのか分からないが、とりあえず普通にチュートリアルに載っているルーティングをすると、URLが/◯◯◯的になるので、リロードすると当然そんなファイルをS3に配置しておらずNot Foundになる。
S3はファイルに対してリダイレクト設定とか出来るので、空のファイル作って設定してみたりしたものの、CloudFrontにすると適用されないのと、他にパラメータつくと対応出来ないので却下。
CloudFrontで、Not Foundの際の挙動設定出来るので、redirect.html(JavaScriptでリダイレクトを記述してるだけのファイル)を用意して、404のときはそこを読ませるようにして解決。
設定方法は、CloudFrontのDistributions一覧から、Distribution ID(14桁くらいの英数)をクリックして出てくるメニューの、『Error Pages』で設定。

ただのリダイレクトなので、リロードしたときに滞在していたページに戻ってこれないという問題が発生したが、ローカルストレージに最終閲覧ページの情報を持つようにして、アクセス時に最初に遷移するComponentに最終閲覧ページへ遷移するようなロジックにして解決。

最後に

EC2に作ってしまったビルド環境に始まり、まだまだ改善点だらけなものの、スケールの心配とかめんどくさいネットワーク周りの設定とかしなくて良いので、今後も継続的にこのサーバレス構成をブラッシュアップしていきたい。
ちなみに諸々の事業でLambdaとDynamoDB周りは今回ほとんど触ってないので、serverlessフレームワークとか近々触ってみようかと思ってます。