Closed3
NestJS+Angular+Scullyを試してみる
セットアップ
nxを使ってNestJS+Angularまではやる。
$ npx create-nx-workspace
npx: installed 190 in 24.11s
? Workspace name (e.g., org name) nx-scully-sample
? What to create in the new workspace angular-nest [a workspace with a full stack application (Angular + Nest)]
? Application name nx-scully-sample
? Default stylesheet format SASS(.scss) [ http://sass-lang.com ]
? Default linter ESLint [ Modern linting tool ]
? Use Nx Cloud? (It's free and doesn't require registration.) No
Scully追加
$ npm run ng add @scullyio/init -- --nx-scully-sample
RouterModule追加
ScullyがAngularRouterが要求するので追加する。
これがないとScullyでビルドした結果にアクセスするときにNullInjectorで落ちる。
(ハマって数時間溶かした)
RouterModuleを追加するために雑にコンポーネントを作って対応する。
top.component
nxが生成したapp.componentに記載されてる内容を切り出していく。
※cssについては割愛
top.component.html
<div style="text-align: center">
<h1>Welcome to nx-scully-sample!</h1>
<img
width="450"
src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png"
/>
</div>
<div>Message: {{ hello$ | async | json }}</div>
top.component.ts
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Message } from '@nx-scully-sample/api-interfaces';
@Component({
selector: 'nx-scully-sample-root',
templateUrl: './top.component.html',
styleUrls: ['./top.component.scss'],
})
export class TopComponent {
hello$ = this.http.get<Message>('/api/hello');
constructor(private http: HttpClient) {}
}
app-router.module.tsを追加
app-router.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TopComponent } from './components/top/top.component';
const routes: Routes = [
{ path: '', component: TopComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.module.ts修正
RouterModuleと作ったComponentを読み込む様に修正。
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { ScullyLibModule } from '@scullyio/ng-lib';
import { AppRoutingModule } from './app-router.module';
import { TopComponent } from './components/top/top.component';
@NgModule({
declarations: [AppComponent, TopComponent],
imports: [BrowserModule, HttpClientModule, ScullyLibModule, AppRoutingModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
app.component.html
routingに対応する様に修正する。
app.component.html
<router-outlet></router-outlet>
ビルド
# Angularのビルド
$ npm run build -- --prod
# scullyのビルド
$ npm run scully -- --scanRoutes
起動
これで起動できればOK。
$ npm run scully:serve
firebaseにあげてみる
準備
$ npx firebase init
> functionsとhostingを選択
> 適当にproject選択(今回はあるもの選んだ)
> 言語選択はお好みで(今回はビルドしたもの上げるのでjs)
> eslintの質問はNo
> npm installもNo
> spaじゃなくなっているので全URLを/index.htmlに飛ばすのはNo
> 404の上書きもNo
> index.htmlの上書きもNo
firebase.jsonの修正
{
"hosting": {
"public": "dist/static",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "/v1/**/*",
"function": "api"
},
{
"source": "/*[!v1]*/**",
"destination": "/"
}
]
},
"functions": {
"source": "dist/apps/api"
}
}
apps/api/main.tsの修正
デフォのままじゃfirebase functionsで動かないので修正。
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import { AppModule } from './app/app.module';
import * as express from 'express';
import * as functions from 'firebase-functions';
const server = express();
async function bootstrap(instance) {
const app = await NestFactory.create(AppModule, new ExpressAdapter(instance));
app.setGlobalPrefix('v1');
return app.init();
}
bootstrap(server)
.then(v => Logger.log(`Ready`))
.catch(e => Logger.warn(e));
export const api = functions.https.onRequest(server);
top.component.ts修正
APIのパス変えたので修正する。
prefixを変えるのみ。
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Message } from '@nx-scully-sample/api-interfaces';
@Component({
selector: 'nx-scully-sample-root',
templateUrl: './top.component.html',
styleUrls: ['./top.component.scss'],
})
export class TopComponent {
hello$ = this.http.get<Message>('/v1/hello');
constructor(private http: HttpClient) {}
}
デプロイ先にpackage.jsonを追加
firebase functions用にAPIのデプロイ先にpackage.jsonを追加するscriptを用意する。
/tools/generator
配下にpackage-json-generator.jsを作成
const path = require('path');
const fs = require('fs');
const original = require('../../package.json');
const ROOT_PATH = path.resolve(__dirname, '../../');
const OUTPUT_PATH = path.resolve(ROOT_PATH, 'dist/apps/api');
const functionsJson = {
main: "main.js",
engines: {
node: "12"
}
};
(function writeJson() {
const dependencies = original.dependencies;
const writeJson = {
...functionsJson,
dependencies
}
fs.writeFileSync(`${OUTPUT_PATH}/package.json`, JSON.stringify(writeJson));
})();
ビルド & デプロイ
script準備
package.jsonに↓を追加 or 修正
{
"scriptis": {
"scully": "scully",
"scully:prod": "scully --scanRoutes --prod --RSD",
"firebase": "firebase",
"firebase:deploy": "firebase deploy",
"generate:package": "node tools/generators/package-json-generator.js"
},
}
上2つがscully用であとはfirebase周り用。
# nx周りをきれいに設定すればaffected:buildで完結する気がする
# APIのビルド
$ npm run affected:build
# Scully用にAngularのビルド
$ npm run build -- --prod
# Scullyのビルド
$ npm run scully:prod
# デプロイ
$ npm run firebase:deploy
デプロイ後、hostingのURLでアプリが表示されていればOK。
このスクラップは2021/01/21にクローズされました