メモ代わりの記事です
2021/11/09時点
要約
現状個人開発中で感じたもの
- コードしか書かなくていいからCloud Functionsを選択は間違い
- Firebase Hostingは公開「は」楽、Cloud Functionsを絡めるとregionが問題になる
環境
mac (imac 2019)
angular 10
Angular CLI: 10.2.3
Node: 14.17.3
OS: darwin x64
Angular: 10.2.5
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router
Ivy Workspace: Yes
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1002.3
@angular-devkit/build-angular 0.1002.3
@angular-devkit/core 10.2.3
@angular-devkit/schematics 10.2.3
@angular/cdk 10.2.7
@angular/cli 10.2.3
@angular/material 10.2.7
@nguniversal/builders 11.2.1
@nguniversal/express-engine 11.1.2
@schematics/angular 10.2.3
@schematics/update 0.1002.3
rxjs 6.6.7
typescript 4.0.8
nestjs
"@nestjs/common": "^7.0.0",
"@nestjs/core": "^7.0.0",
"@nestjs/ng-universal": "^4.3.0",
"@nestjs/platform-express": "^7.0.0",
コードしか書かなくていいからCloud Functionsを選択は間違い
-
App Engineでも同じことができる 使用歴はかなり浅いが簡単な差は以下
- Functions:
コードベース&firebase.json
で、Cloud環境指定 - App Engine:
app.yaml
で、Cloud環境指定、package.jsonのstartがアプリ起動フック
- Functions:
-
選択基準
- ファイルのアップロードや、他のアプリへのログインなど他の
イベントベースで動く
ならCloud Functions -
普通のWebサービス
ならApp Engineのほうが無難
- ファイルのアップロードや、他のアプリへのログインなど他の
-
deploy時にエラーが出たとき何が原因か見つけるのが大変
- エラーログなどから推測しづらいためコードに集中しづらい上に時間がかなりかかる
-
Window や Document などのグローバルオブジェクトのMockとしてdominoが`server.ts`でimportされていて
windowのMock作成時に何故か `distのindex.htmlが絶対パスでreadFileSync().toString()`していたためローカル環境では問題なし。
`firebase deploy` 時に`cleaning up`で毎回失敗、ライブラリの更新等しても治らない、`--debug`オプションでも有用な情報がなし
不要そうなものを消したりを繰り返して原因突き止めやっと解決といった流れ
sqlファイルとかをdistにコピーするScriptで削除ディレクトリ間違えてコピーできなかったときにも出て結構困った
初めて出たときには2日くらい無駄にした
windowのMock作成時に何故か `distのindex.htmlが絶対パスでreadFileSync().toString()`していたためローカル環境では問題なし。
`firebase deploy` 時に`cleaning up`で毎回失敗、ライブラリの更新等しても治らない、`--debug`オプションでも有用な情報がなし
不要そうなものを消したりを繰り返して原因突き止めやっと解決といった流れ
sqlファイルとかをdistにコピーするScriptで削除ディレクトリ間違えてコピーできなかったときにも出て結構困った
初めて出たときには2日くらい無駄にした
- この環境での問題だがAngular Universal & Nestjsの構成だとネットにあまり情報がない&自分の知識が浅すぎて公開が大変だった
- SSR構成でもexportしているmoduleを理解していればすぐできる、素のExpressを利用しているならsampleので十分
- 記載環境で以下のディレクトリ構成のときのcloud functionsへの公開方法 (やり方が正しいかはわかりません)
project-root
├── functions
│ ├── dist
│ └── src
│ └── index.ts
├── node_modules
├── public
├── server
└── src
├──app
├──index.html
├──main.server.ts
└──main.ts
// main.server.ts
import { enableProdMode } from '@angular/core';
import * as express from 'express';
import { ExpressAdapter } from '@nestjs/platform-express';
import { environment } from './environments/environment';
import { NestFactory } from '@nestjs/core';
import { AppModule } from '../server/app.module';
import { Logger } from '@nestjs/common';
if (environment.production) {
enableProdMode();
}
const server = express();
export const initNestServer = ( async (): Promise<any> => {
const apiPrefix = 'api';
Logger.log(`[Nest]initNestServer ${apiPrefix}`);
const nest = await NestFactory.create(
AppModule,
new ExpressAdapter(server),
);
nest.setGlobalPrefix(apiPrefix);
return nest.init();
});
export const expressServer = server;
export { AppServerModule } from './app/app.server.module';
export { renderModule, renderModuleFactory } from '@angular/platform-server';
// functions/src/index.ts
// App Engine乗り換え検討し始めた時期なので少し適当
import * as functions from 'firebase-functions';
import * as path from 'path';
// @ts-ignore
import { initNestServer } from '../dist/project/server/main.js';
const mainDir = path.resolve(__dirname, '../dist/project/server/main.js');
initNestServer();
const server = require(mainDir).expressServer;
export const app =
functions
.region('us-central1')
.runWith({ memory: '256MB' })
.https
.onRequest(server);
Firebase Hostingは公開「は」楽、Cloud Functionsを絡めるとregionが問題になる
- Firebase Hostingを利用してhosting側でrewritesを設定後、Functionsを利用しようとするとregionがus-central1に固定される
- 重要: Firebase Hosting は、us-central1 でのみ Cloud Functions をサポートします。
- HostingもFunctionsもus-central1でレスポンスに問題無いのであれば、Cloud Sql側もus-central1にしておいたほうがいい
- TTFBのことを考えるならApp Engineでasia-northeastにしたほうが圧倒的にいい