{"id":308219,"date":"2020-08-10T03:00:09","date_gmt":"2020-08-10T03:00:09","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=308219"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=308219","title":{"rendered":"\u041f\u0438\u0448\u0435\u043c full stack \u043c\u043e\u043d\u043e\u043b\u0438\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Angular Universal + NestJS + PostgreSQL"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/514380\/\">\n<h5 id=\"privet-habr\">\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!<\/h5>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d-\u043c\u043e\u043d\u043e\u043b\u0438\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0431\u0440\u0430\u0442\u044c \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443 \u043d\u043e\u0432\u043e\u0433\u043e fullstack \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u043a \u0441\u043a\u0435\u043b\u0435\u0442 \u0434\u043b\u044f \u043d\u0430\u0432\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430.<\/p>\n<p>  <\/p>\n<h4 id=\"eta-statya-budet-polezna-esli-vy\">\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430, \u0435\u0441\u043b\u0438 \u0432\u044b:<\/h4>\n<p>  <\/p>\n<ul>\n<li>\u041d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0439\u00a0 fullstack-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a;<\/li>\n<li>\u0421\u0442\u0430\u0440\u0442\u0430\u043f\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0438\u0448\u0435\u0442 MVP \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0433\u0438\u043f\u043e\u0442\u0435\u0437\u0443.<a name=\"habracut\"><\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<h4 id=\"pochemu-vybral-takoy-stek\">\u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u044b\u0431\u0440\u0430\u043b \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0435\u043a:<\/h4>\n<p>  <\/p>\n<ul>\n<li>Angular: \u0438\u043c\u0435\u044e \u043c\u043d\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430 \u0432 \u043d\u0435\u043c, \u043b\u044e\u0431\u043b\u044e \u0441\u0442\u0440\u043e\u0433\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0438 Typescript \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u0432\u044b\u0445\u043e\u0434\u0435\u0446 \u0438\u0437 .NET<\/li>\n<li>NestJS: \u0442\u043e\u0442-\u0436\u0435 \u044f\u0437\u044b\u043a, \u0442\u0430-\u0436\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u0431\u044b\u0441\u0442\u0440\u043e\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 REST API, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043f\u0435\u0440\u0435\u0441\u0435\u0441\u0442\u044c \u043d\u0430 Serverless (\u0434\u0435\u0448\u0435\u0432\u043b\u0435 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u043a\u0438)<\/li>\n<li>PostgreSQL: \u0421\u043e\u0431\u0438\u0440\u0430\u044e\u0441\u044c \u0445\u043e\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0432 \u042f\u043d\u0434\u0435\u043a\u0441.\u041e\u0431\u043b\u0430\u043a\u0435, \u043d\u0430 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u043a\u0430\u0445 <a href=\"https:\/\/cloud.yandex.ru\/prices\" rel=\"nofollow\">\u0434\u0435\u0448\u0435\u0432\u043b\u0435 \u043d\u0430 30% \u0447\u0435\u043c MongoDB<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/q1\/ww\/dp\/q1wwdppczgqz9faox6jy5uynx44.png\" alt=\"\u041f\u0440\u0430\u0439\u0441 \u044f\u043d\u0434\u0435\u043a\u0441\u0430\"><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e, \u043f\u043e\u0438\u0441\u043a\u0430\u043b \u043d\u0430 \u0445\u0430\u0431\u0440\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043a\u0435\u0439\u0441, \u043d\u0430\u0448\u0435\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/423739\/\">Angular \u0438 SEO: \u043a\u0430\u043a \u0438\u0445 \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c?<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/341044\/\">Firebase + Angular Universal = \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/324926\/\">\u0414\u0440\u0443\u0436\u0438\u043c Angular \u0441 Google (Angular Universal)<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/348818\/\">\u0423\u0434\u0438\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 Angular<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0418\u0437 \u044d\u0442\u043e\u0433\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 &quot;\u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b \u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u043b&quot; \u0438\u043b\u0438 \u0434\u0430\u0435\u0442 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0442\u043e \u0447\u0442\u043e \u0435\u0449\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<h4 id=\"oglavlenie\">\u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435:<\/h4>\n<p>  <\/p>\n<p><a href=\"#step_one\">1. \u0421\u043e\u0437\u0434\u0430\u0435\u043c Angular \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 ng-zorro<\/a><br \/>  <a href=\"#step_two\">2. \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c NestJS \u0438 \u0440\u0435\u0448\u0430\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 SSR<\/a><br \/>  <a href=\"#step_three\">3. \u0414\u0435\u043b\u0430\u0435\u043c API \u043d\u0430 NestJS \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043a \u0444\u0440\u043e\u043d\u0442\u0443<\/a><br \/>  <a href=\"#step_fouth\">4. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 PostgreSQL<\/a><\/p>\n<p>  <a name=\"step_one\"><\/a>  <\/p>\n<h4 id=\"1-sozdaem-angular-prilozhenie\">1. \u0421\u043e\u0437\u0434\u0430\u0435\u043c Angular \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h4>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c Angular-CLI \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c SPA-\u0441\u0430\u0439\u0442\u044b \u043d\u0430 \u0410\u043d\u0433\u0443\u043b\u044f\u0440\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">npm install -g @angular\/cli<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Angular \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">ng new angular-habr-nestjs<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043f\u0430\u043f\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">cd angular-habr-nestjs ng serve --open<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/--\/vh\/kz\/--vhkzkyfw_i1xoh8itqcnvlw_i.png\" alt=\"\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 SPA-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 Angular\"><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0437\u0434\u0430\u043b\u043e\u0441\u044c. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 NG-Zorro:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">ng add ng-zorro-antd<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">? Enable icon dynamic loading [ Detail: https:\/\/ng.ant.design\/components\/icon\/en ] Yes ? Set up custom theme file [ Detail: https:\/\/ng.ant.design\/docs\/customize-theme\/en ] No ? Choose your locale code: ru_RU ? Choose template to create project: sidemenu<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u0438\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 app.component \u043d\u0430 \u0434\u0438\u0437\u0430\u0439\u043d \u0441 \u043c\u0435\u043d\u044e\u0448\u043a\u043e\u0439 \u0441\u043b\u0435\u0432\u0430, \u0444\u0443\u0442\u0435\u0440\u043e\u043c \u0438 \u0445\u0435\u0434\u0435\u0440\u043e\u043c \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ok\/6r\/6j\/ok6r6j2qygd08jwkjwvftzjvzmc.png\" alt=\"\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 NG-Zorro\"><\/p>\n<p>  <\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443 \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 <em>src\/app\/pages\/welcome<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u043b NG-Zorro:<br \/>  \u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u0437\u044f\u0442 \u043e\u0442\u0441\u044e\u0434\u0430:<br \/>  <a href=\"https:\/\/ng.ant.design\/components\/table\/en\" rel=\"nofollow\">https:\/\/ng.ant.design\/components\/table\/en<\/a><\/p>\n<p>  <\/p>\n<pre><code class=\"html\">\/\/ welcome.component.html &lt;nz-table #basicTable [nzData]=&quot;items$ | async&quot;&gt; \u00a0 &lt;thead&gt; \u00a0 &lt;tr&gt; \u00a0 \u00a0 &lt;th&gt;Name&lt;\/th&gt; \u00a0 \u00a0 &lt;th&gt;Age&lt;\/th&gt; \u00a0 \u00a0 &lt;th&gt;Address&lt;\/th&gt; \u00a0 &lt;\/tr&gt; \u00a0 &lt;\/thead&gt; \u00a0 &lt;tbody&gt; \u00a0 &lt;tr *ngFor=&quot;let data of basicTable.data&quot;&gt; \u00a0 \u00a0 &lt;td&gt;{{ data.name }}&lt;\/td&gt; \u00a0 \u00a0 &lt;td&gt;{{ data.age }}&lt;\/td&gt; \u00a0 \u00a0 &lt;td&gt;{{ data.address }}&lt;\/td&gt; \u00a0 &lt;\/tr&gt; \u00a0 &lt;\/tbody&gt; &lt;\/nz-table&gt;<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ welcome.module.ts import { NgModule } from '@angular\/core';  import { WelcomeRoutingModule } from '.\/welcome-routing.module';  import { WelcomeComponent } from '.\/welcome.component'; import { NzTableModule } from 'ng-zorro-antd'; import { CommonModule } from '@angular\/common';  @NgModule({ \u00a0 imports: [ \u00a0 \u00a0 WelcomeRoutingModule, \u00a0 \u00a0 NzTableModule, \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u00a0 \u00a0 CommonModule \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u043b\u044f \u043f\u0430\u0439\u043f\u0430 async \u00a0 ], \u00a0 declarations: [WelcomeComponent], \u00a0 exports: [WelcomeComponent] }) export class WelcomeModule { }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ welcome.component.ts import { Component, OnInit } from '@angular\/core'; import { Observable, of } from 'rxjs'; import { HttpClient } from '@angular\/common\/http'; import { share } from 'rxjs\/operators';  @Component({ \u00a0 selector: 'app-welcome', \u00a0 templateUrl: '.\/welcome.component.html', \u00a0 styleUrls: ['.\/welcome.component.scss'] }) export class WelcomeComponent implements OnInit { \u00a0 items$: Observable&lt;Item[]&gt; = of([ \u00a0 \u00a0 {name: '\u0412\u0430\u0441\u044f', age: 24, address: '\u041c\u043e\u0441\u043a\u0432\u0430'}, \u00a0 \u00a0 {name: '\u041f\u0435\u0442\u044f', age: 23, address: '\u041b\u043e\u043d\u0434\u043e\u043d'}, \u00a0 \u00a0 {name: '\u041c\u0438\u0448\u0430', age: 21, address: '\u041f\u0430\u0440\u0438\u0436'}, \u00a0 \u00a0 {name: '\u0412\u043e\u0432\u0430', age: 23, address: '\u0421\u0438\u0434\u043d\u0435\u0439'} \u00a0 ]);  \u00a0 constructor(private http: HttpClient) { \u00a0 }  \u00a0 ngOnInit() { \u00a0 }  \u00a0 \/\/ \u0421\u0440\u0430\u0437\u0443 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u043a \u0431\u044d\u043a\u0443, \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u043e\u0437\u0436\u0435 \u00a0 getItems(): Observable&lt;Item[]&gt; { \u00a0 \u00a0 return this.http.get&lt;Item[]&gt;('\/api\/items').pipe(share()); \u00a0 } }  interface Item { \u00a0 name: string; \u00a0 age: number; \u00a0 address: string; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/hq\/dn\/bp\/hqdnbpxvyfai0mmxz7mbag0psfs.png\" alt=\"\u0422\u0430\u0431\u043b\u0438\u0447\u043a\u0430 NG-Zorro\"><\/p>\n<p>  <a name=\"step_two\"><\/a>  <\/p>\n<h4 id=\"2-ustanavlivaem-nestjs\">2. \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c NestJS<\/h4>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c NestJS \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u043b Angular Universal (Server Side Rendering) \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0430\u0440\u0443 \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">ng add @nestjs\/ng-universal<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043d\u0430\u0448 SSR \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">npm run serve<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u0432\u043e\u0442 \u0443\u0436\u0435 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u0441\u044f\u043a \ud83d\ude42 \u0423 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">TypeError: Cannot read property 'indexOf' of undefined \u00a0 \u00a0 at D:\\Projects\\angular-habr-nestjs\\node_modules\\@nestjs\\ng-universal\\dist\\utils\\setup-universal.utils.js:35:43 \u00a0 \u00a0 at D:\\Projects\\angular-habr-nestjs\\dist\\server\\main.js:107572:13 \u00a0 \u00a0 at View.engine (D:\\Projects\\angular-habr-nestjs\\node_modules\\@nestjs\\ng-universal\\dist\\utils\\setup-universal.utils.js:30:11) \u00a0 \u00a0 at View.render (D:\\Projects\\angular-habr-nestjs\\node_modules\\express\\lib\\view.js:135:8) \u00a0 \u00a0 at tryRender (D:\\Projects\\angular-habr-nestjs\\node_modules\\express\\lib\\application.js:640:10) \u00a0 \u00a0 at Function.render (D:\\Projects\\angular-habr-nestjs\\node_modules\\express\\lib\\application.js:592:3) \u00a0 \u00a0 at ServerResponse.render (D:\\Projects\\angular-habr-nestjs\\node_modules\\express\\lib\\response.js:1012:7) \u00a0 \u00a0 at D:\\Projects\\angular-habr-nestjs\\node_modules\\@nestjs\\ng-universal\\dist\\angular-universal.module.js:60:66 \u00a0 \u00a0 at Layer.handle [as handle_request] (D:\\Projects\\angular-habr-nestjs\\node_modules\\express\\lib\\router\\layer.js:95:5) \u00a0 \u00a0 at next (D:\\Projects\\angular-habr-nestjs\\node_modules\\express\\lib\\router\\route.js:137:13)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043a\u043e\u0441\u044f\u043a, \u0437\u0430\u0439\u0434\u0435\u043c \u0432 \u0444\u0430\u0439\u043b <em>server\/app.module.ts<\/em> \u0438 \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <em>liveReload<\/em> \u043d\u0430 false:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { Module } from '@nestjs\/common'; import { AngularUniversalModule } from '@nestjs\/ng-universal'; import { join } from 'path';  @Module({ \u00a0 imports: [ \u00a0 \u00a0 AngularUniversalModule.forRoot({ \u00a0 \u00a0 \u00a0 viewsPath: join(process.cwd(), 'dist\/browser'), \u00a0 \u00a0 \u00a0 bundle: require('..\/server\/main'), \u00a0 \u00a0 \u00a0 liveReload: false \u00a0 \u00a0 }) \u00a0 ] }) export class ApplicationModule {}<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0442\u044e\u043d\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u0442\u0430\u0439\u043f\u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0442\u0430\u043a-\u043a\u0430\u043a \u044d\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u0432\u0437\u043b\u0435\u0442\u0430\u0435\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Ivy \u0440\u0435\u043d\u0434\u0435\u0440\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"json\">\/\/ tsconfig.server.json { \u00a0 &quot;extends&quot;: &quot;.\/tsconfig.app.json&quot;, \u00a0 &quot;compilerOptions&quot;: { \u00a0 \u00a0 &quot;outDir&quot;: &quot;.\/out-tsc\/server&quot;, \u00a0 \u00a0 &quot;target&quot;: &quot;es2016&quot;, \u00a0 \u00a0 &quot;types&quot;: [ \u00a0 \u00a0 \u00a0 &quot;node&quot; \u00a0 \u00a0 ] \u00a0 }, \u00a0 &quot;files&quot;: [ \u00a0 \u00a0 &quot;src\/main.server.ts&quot; \u00a0 ], \u00a0 &quot;angularCompilerOptions&quot;: { \u00a0 \u00a0 &quot;enableIvy&quot;: false, \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0444\u043b\u0430\u0436\u043e\u043a \u00a0 \u00a0 &quot;entryModule&quot;: &quot;.\/src\/app\/app.server.module#AppServerModule&quot; \u00a0 } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0435\u0440\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 ng run serve \u0447\u0442\u043e\u0431\u044b SSR \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/tq\/df\/9q\/tqdf9qbnodfiiftwqz-jhkkezkm.png\" alt=\"Angular SSR + NestJS\"><\/p>\n<p>  <\/p>\n<p>\u0423\u0440\u0430! SSR \u043f\u043e\u0434\u0440\u0443\u0431\u0438\u043b\u0441\u044f, \u043d\u043e \u043a\u0430\u043a \u0432\u0438\u0434\u0438\u043c\u043e \u0432 devtools \u043e\u043d \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0441 \u043a\u0440\u0438\u0432\u044b\u043c\u0438 \u0441\u0442\u0438\u043b\u044f\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c <em>extractCss: true<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u0442\u0438\u043b\u0438 \u043d\u0435 \u0432 <em>styles.js<\/em>, \u0430 \u0432 <em>styles.css<\/em>:<\/p>\n<p>  <\/p>\n<pre><code class=\"json\">\/\/ angular.json ... &quot;architect&quot;: { \u00a0 \u00a0 \u00a0 \u00a0 &quot;build&quot;: { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;builder&quot;: &quot;@angular-devkit\/build-angular:browser&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;options&quot;: { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;outputPath&quot;: &quot;dist\/browser&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;index&quot;: &quot;src\/index.html&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;main&quot;: &quot;src\/main.ts&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;polyfills&quot;: &quot;src\/polyfills.ts&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;tsConfig&quot;: &quot;tsconfig.app.json&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;aot&quot;: true, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;assets&quot;: [ \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;src\/favicon.ico&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;src\/assets&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;glob&quot;: &quot;**\/*&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;input&quot;: &quot;.\/node_modules\/@ant-design\/icons-angular\/src\/inline-svg\/&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;output&quot;: &quot;\/assets\/&quot; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ], \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;extractCss&quot;: true, \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0444\u043b\u0430\u0436\u043e\u043a \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;styles&quot;: [ \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;.\/node_modules\/ng-zorro-antd\/ng-zorro-antd.min.css&quot;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;src\/styles.scss&quot; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ], \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &quot;scripts&quot;: [] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }, ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0441\u0442\u0438\u043b\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432 <em>app.component.scss<\/em>:<\/p>\n<p>  <\/p>\n<pre><code class=\"css\">\/\/ app.component.scss @import &quot;~ng-zorro-antd\/ng-zorro-antd.min.css&quot;; \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0441\u0442\u0438\u043b\u0438  :host { \u00a0 display: flex; \u00a0 text-rendering: optimizeLegibility; \u00a0 -webkit-font-smoothing: antialiased; \u00a0 -moz-osx-font-smoothing: grayscale; }  .app-layout { \u00a0 height: 100vh; } ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0438\u043b\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b, SSR \u043e\u0442\u0434\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0443 \u0441\u043e \u0441\u0442\u0438\u043b\u044f\u043c\u0438, \u043d\u043e \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0447\u0442\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0443 \u043d\u0430\u0441 \u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f SSR, \u043f\u043e\u0442\u043e\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043c\u043e\u0440\u0433\u0430\u0435\u0442 \u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f CSR (Client Side Rendering). \u042d\u0442\u043e \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { NgModule } from '@angular\/core'; import { Routes, RouterModule } from '@angular\/router';  const routes: Routes = [ \u00a0 { path: '', pathMatch: 'full', redirectTo: '\/welcome' }, \u00a0 { path: 'welcome', loadChildren: () =&gt; import('.\/pages\/welcome\/welcome.module').then(m =&gt; m.WelcomeModule) } ];  @NgModule({ \u00a0 imports: [RouterModule.forRoot(routes, {initialNavigation: 'enabled', scrollPositionRestoration: 'enabled'})], \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 initialNavigation, scrollPositionRestoration \u00a0 exports: [RouterModule] }) export class AppRoutingModule { }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><em>initialNavigation: &#8216;enabled&#8217;<\/em> \u0434\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0443 \u043d\u0435 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0435\u0441\u043b\u0438 \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 SSR<\/li>\n<li><em>scrollPositionRestoration: &#8216;enabled&#8217;<\/em> \u0441\u043a\u0440\u043e\u043b\u0438\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043d\u0430\u0432\u0435\u0440\u0445 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0435.<\/li>\n<\/ul>\n<p>  <a name=\"step_three\"><\/a>  <\/p>\n<h4 id=\"3-sdelaem-paru-endpointov-na-nestjs\">3. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0430\u0440\u0443 \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u043d\u0430 NestJS<\/h4>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432 \u043f\u0430\u043f\u043a\u0443 server \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 items:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">cd server nest g module items nest g controller items --no-spec<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ items.module.ts import { Module } from '@nestjs\/common'; import { ItemsController } from '.\/items.controller';  @Module({ \u00a0 controllers: [ItemsController] }) export class ItemsModule { }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ items.controller.ts import { Controller } from '@nestjs\/common';  @Controller('items') export class ItemsController {}<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0438 \u043c\u043e\u0434\u0443\u043b\u044c \u0441\u043e\u0437\u0434\u0430\u043b\u0438\u0441\u044c. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u0435\u0442\u043e\u0434 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 items \u0438 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ server\/src\/items\/items.controller.ts import { Body, Controller, Get, Post } from '@nestjs\/common';  class Item { \u00a0 name: string; \u00a0 age: number; \u00a0 address: string; }  @Controller('items') export class ItemsController {  \u00a0 \/\/ \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u0437\u044f\u043b \u0438\u0437 Angular\u00a0 \u00a0 private items: Item[] = [ \u00a0 \u00a0 {name: '\u0412\u0430\u0441\u044f', age: 24, address: '\u041c\u043e\u0441\u043a\u0432\u0430'}, \u00a0 \u00a0 {name: '\u041f\u0435\u0442\u044f', age: 23, address: '\u041b\u043e\u043d\u0434\u043e\u043d'}, \u00a0 \u00a0 {name: '\u041c\u0438\u0448\u0430', age: 21, address: '\u041f\u0430\u0440\u0438\u0436'}, \u00a0 \u00a0 {name: '\u0412\u043e\u0432\u0430', age: 23, address: '\u0421\u0438\u0434\u043d\u0435\u0439'} \u00a0 ];  \u00a0 @Get() \u00a0 getAll(): Item[] { \u00a0 \u00a0 return this.items; \u00a0 }  \u00a0 @Post() \u00a0 create(@Body() newItem: Item): void { \u00a0 \u00a0 this.items.push(newItem); \u00a0 } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c GET \u0432 Postman:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/gh\/qs\/oj\/ghqsojm4jcpyqavcv2wfgx8czjs.png\" alt=\"GET \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0430\u043f\u0438\u0448\u043a\u0438 NestJS\"><\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442! \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 GET items \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c api, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 <em>server\/main.ts<\/em> \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 NestJS:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ server\/main.ts import { NestFactory } from '@nestjs\/core'; import { ApplicationModule } from '.\/app.module';  async function bootstrap() { \u00a0 const app = await NestFactory.create(ApplicationModule); \u00a0 app.setGlobalPrefix('api'); \/\/ \u042d\u0442\u043e \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u00a0 await app.listen(4200); } bootstrap();<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043c \u0431\u044d\u043a \u043a \u0444\u0440\u043e\u043d\u0442\u0443. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a \u0444\u0430\u0439\u043b\u0443 <em>welcome.component.ts<\/em> \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043f\u0438\u0441\u043a\u0430 \u043a \u0431\u044d\u043a\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ welcome.component.ts import { Component, OnInit } from '@angular\/core'; import { Observable, of } from 'rxjs'; import { HttpClient } from '@angular\/common\/http'; import { share } from 'rxjs\/operators';  @Component({ \u00a0 selector: 'app-welcome', \u00a0 templateUrl: '.\/welcome.component.html', \u00a0 styleUrls: ['.\/welcome.component.scss'] }) export class WelcomeComponent implements OnInit { \u00a0 items$: Observable&lt;Item[]&gt; = this.getItems(); \/\/ \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043b\u0438 \u0432\u044b\u0437\u043e\u0432 \u0431\u044d\u043a\u0430  \u00a0 constructor(private http: HttpClient) { \u00a0 }  \u00a0 ngOnInit() { \u00a0 }  \u00a0 getItems(): Observable&lt;Item[]&gt; { \u00a0 \u00a0 return this.http.get&lt;Item[]&gt;('\/api\/items').pipe(share()); \u00a0 } }  interface Item { \u00a0 name: string; \u00a0 age: number; \u00a0 address: string; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0447\u0442\u043e \u0430\u043f\u0438\u0445\u0430 \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435 \u0434\u0435\u0440\u0433\u0430\u0435\u0442\u0441\u044f, \u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u0434\u0435\u0440\u0433\u0430\u0435\u0442\u0441\u044f \u0438 \u0432 SSR, \u043f\u0440\u0438\u0447\u0435\u043c \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ku\/3b\/8d\/ku3b8dawllmtdwbxztufco3fdbm.png\" alt=\"\u0414\u0435\u0440\u0433\u0430\u043d\u0438\u0435 \u0430\u043f\u0438\u0445\u0438 \u0432 SSR\"><\/p>\n<p>  <\/p>\n<p>\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0432 SSR \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ welcome.component.ts import { Component, OnInit } from '@angular\/core'; import { Observable, of } from 'rxjs'; import { HttpClient } from '@angular\/common\/http'; import { share } from 'rxjs\/operators';  @Component({ \u00a0 selector: 'app-welcome', \u00a0 templateUrl: '.\/welcome.component.html', \u00a0 styleUrls: ['.\/welcome.component.scss'] }) export class WelcomeComponent implements OnInit { \u00a0 items$: Observable&lt;Item[]&gt; = this.getItems(); \/\/ \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043b\u0438 \u0432\u044b\u0437\u043e\u0432 \u0431\u044d\u043a\u0430  \u00a0 constructor(private http: HttpClient) { \u00a0 }  \u00a0 ngOnInit() { \u00a0 }  \u00a0 getItems(): Observable&lt;Item[]&gt; { \u00a0 \u00a0 return this.http.get&lt;Item[]&gt;('http:\/\/localhost:4200\/api\/items').pipe(share()); \/\/ \u041f\u0440\u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043a \u0430\u043f\u0438\u0445\u0435 \u0447\u0442\u043e\u0431\u044b SSR \u043d\u0435 \u0440\u0443\u0433\u0430\u043b\u0441\u044f \u00a0 } }  interface Item { \u00a0 name: string; \u00a0 age: number; \u00a0 address: string; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u0430\u043f\u0438\u0445\u0435 (\u043e\u0434\u0438\u043d \u043d\u0430 SSR, \u0434\u0440\u0443\u0433\u043e\u0439 \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435), \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 @nguniversal\/common:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"plaintext\">npm i @nguniversal\/common<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li>\u0412 \u0444\u0430\u0439\u043b\u0435 <em>app\/app.module.ts<\/em> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 SSR:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ app.module.ts import { BrowserModule } from '@angular\/platform-browser'; import { NgModule } from '@angular\/core';  import { AppRoutingModule } from '.\/app-routing.module'; import { AppComponent } from '.\/app.component'; import { IconsProviderModule } from '.\/icons-provider.module'; import { NzLayoutModule } from 'ng-zorro-antd\/layout'; import { NzMenuModule } from 'ng-zorro-antd\/menu'; import { FormsModule } from '@angular\/forms'; import { HttpClientModule } from '@angular\/common\/http'; import { BrowserAnimationsModule } from '@angular\/platform-browser\/animations'; import { NZ_I18N } from 'ng-zorro-antd\/i18n'; import { ru_RU } from 'ng-zorro-antd\/i18n'; import { registerLocaleData } from '@angular\/common'; import ru from '@angular\/common\/locales\/ru'; import {TransferHttpCacheModule} from '@nguniversal\/common';  registerLocaleData(ru);  @NgModule({ \u00a0 declarations: [ \u00a0 \u00a0 AppComponent \u00a0 ], \u00a0 imports: [ \u00a0 \u00a0 BrowserModule.withServerTransition({ appId: 'serverApp' }), \u00a0 \u00a0 TransferHttpCacheModule, \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u00a0 \u00a0 AppRoutingModule, \u00a0 \u00a0 IconsProviderModule, \u00a0 \u00a0 NzLayoutModule, \u00a0 \u00a0 NzMenuModule, \u00a0 \u00a0 FormsModule, \u00a0 \u00a0 HttpClientModule, \u00a0 \u00a0 BrowserAnimationsModule \u00a0 ], \u00a0 providers: [{ provide: NZ_I18N, useValue: ru_RU }], \u00a0 bootstrap: [AppComponent] }) export class AppModule { }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0445\u043e\u0436\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u0435\u043c \u0441 <em>app.server.module.ts<\/em>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ app.server.module.ts import { NgModule } from '@angular\/core'; import { ServerModule, ServerTransferStateModule } from '@angular\/platform-server';  import { AppModule } from '.\/app.module'; import { AppComponent } from '.\/app.component';  @NgModule({ \u00a0 imports: [ \u00a0 \u00a0 AppModule, \u00a0 \u00a0 ServerModule, \u00a0 \u00a0 ServerTransferStateModule, \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u00a0 ], \u00a0 bootstrap: [AppComponent], }) export class AppServerModule {}<\/code><\/pre>\n<p>  <\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0430\u043f\u0438 \u0432 SSR, \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0444\u043e\u0440\u043c\u0435, \u043e\u0442\u0434\u0430\u0435\u043c \u043d\u0430 \u0444\u0440\u043e\u043d\u0442 \u0438 \u0442\u043e\u0442 \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/zz\/yo\/so\/zzyosolpdynevxo-kg2nrulq8am.png\" alt=\"\u0417\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0435\u0442, \u0434\u0430\u043d\u043d\u044b\u0435 \u0435\u0441\u0442\u044c!\"><\/p>\n<p>  <a name=\"step_fouth\"><\/a>  <\/p>\n<h4 id=\"4-podklyuchim-bazu-postgresql\">4. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0431\u0430\u0437\u0443 PostgreSQL<\/h4>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 PostgreSQL, \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c TypeORM \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0437\u043e\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">npm i pg typeorm @nestjs\/typeorm<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 PostgreSQL \u0441 \u0431\u0430\u0437\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0438.<\/p>\n<p>  <\/p>\n<p>\u041e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0431\u0430\u0437\u0435 \u0432 <em>server\/app.module.ts<\/em>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ server\/app.module.ts import { Module } from '@nestjs\/common'; import { AngularUniversalModule } from '@nestjs\/ng-universal'; import { join } from 'path'; import { ItemsController } from '.\/src\/items\/items.controller'; import { TypeOrmModule } from '@nestjs\/typeorm';  @Module({ \u00a0 imports: [ \u00a0 \u00a0 AngularUniversalModule.forRoot({ \u00a0 \u00a0 \u00a0 viewsPath: join(process.cwd(), 'dist\/browser'), \u00a0 \u00a0 \u00a0 bundle: require('..\/server\/main'), \u00a0 \u00a0 \u00a0 liveReload: false \u00a0 \u00a0 }), \u00a0 \u00a0 TypeOrmModule.forRoot({ \/\/ \u041a\u043e\u043d\u0444\u0438\u0433 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0431\u0430\u0437\u0435 \u00a0 \u00a0 \u00a0 type: 'postgres', \u00a0 \u00a0 \u00a0 host: 'localhost', \u00a0 \u00a0 \u00a0 port: 5432, \u00a0 \u00a0 \u00a0 username: 'postgres', \u00a0 \u00a0 \u00a0 password: 'admin', \u00a0 \u00a0 \u00a0 database: 'postgres', \u00a0 \u00a0 \u00a0 entities: ['dist\/**\/*.entity{.ts,.js}'], \u00a0 \u00a0 \u00a0 synchronize: true \u00a0 \u00a0 }) \u00a0 ], \u00a0 controllers: [ItemsController] }) export class ApplicationModule {}<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e \u043f\u043e\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li>type: \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f<\/li>\n<li>host \u0438 port: \u043c\u0435\u0441\u0442\u043e \u0433\u0434\u0435 \u0431\u0430\u0437\u0430 \u0445\u043e\u0441\u0442\u0438\u0442\u0441\u044f<\/li>\n<li>username \u0438 password: \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0431\u0430\u0437\u044b<\/li>\n<li>database: \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u044b<\/li>\n<li>entities: \u043f\u0443\u0442\u044c, \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0441\u0445\u0435\u043c\u044b \u043d\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u044b<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041f\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c\u0443 \u043f\u0443\u043d\u043a\u0442\u0443, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c Item \u0434\u043b\u044f \u043c\u0430\u043f\u0438\u043d\u0433\u0430 \u043f\u043e\u043b\u0435\u0439 \u0432 \u0431\u0430\u0437\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ server\/src\/items\/item.entity.ts import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeorm\/index';  @Entity() export class ItemEntity { \u00a0 @PrimaryGeneratedColumn() \u00a0 id: number;  \u00a0 @CreateDateColumn() \u00a0 createDate: string;  \u00a0 @Column() \u00a0 name: string;  \u00a0 @Column() \u00a0 age: number;  \u00a0 @Column() \u00a0 address: string; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u0432\u044f\u0436\u0435\u043c \u044d\u0442\u0443 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u0441 \u043d\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u043e\u0439.\u00a0<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ items.module.ts import { Module } from '@nestjs\/common'; import { TypeOrmModule } from '@nestjs\/typeorm'; import { ItemEntity } from '.\/item.entity'; import { ItemsController } from '.\/items.controller';  @Module({ \u00a0 imports: [ \u00a0 \u00a0 TypeOrmModule.forFeature([ItemEntity]) \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0438\u0447\u0430-\u043c\u043e\u0434\u0443\u043b\u044c \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0431\u0430\u0437\u044b \u00a0 ], \u00a0 controllers: [ItemsController] }) export class ItemsModule { }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443\u043a\u0430\u0436\u0435\u043c \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0431\u0430\u0437\u043e\u0439, \u0430 \u043d\u0435 \u043a\u0435\u0448\u0435\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ items.controller.ts import { Body, Controller, Get, Post } from '@nestjs\/common'; import { ItemEntity } from '.\/item.entity'; import { InjectRepository } from '@nestjs\/typeorm'; import { Repository } from 'typeorm\/index';  interface Item { \u00a0 name: string; \u00a0 age: number; \u00a0 address: string; }  @Controller('items') export class ItemsController {  \u00a0 constructor(@InjectRepository(ItemEntity) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private readonly itemsRepository: Repository&lt;ItemEntity&gt;) { \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u00a0 }  \u00a0 @Get() \u00a0 getAll(): Promise&lt;Item[]&gt; { \u00a0 \u00a0 return this.itemsRepository.find(); \u00a0 }  \u00a0 @Post() \u00a0 create(@Body() newItem: Item): Promise&lt;Item&gt; { \u00a0 \u00a0 const item = this.itemsRepository.create(newItem); \u00a0 \u00a0 return this.itemsRepository.save(item); \u00a0 } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0430\u043f\u0438\u0445\u0438 \u0432 Postman:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ul\/ij\/lc\/ulijlcyyp0y4nzgcfu7u2hhybw0.png\" alt=\"POST \u043a \u0430\u043f\u0438\u0445\u0435 \u0441 \u0431\u0430\u0437\u043e\u0439\"><\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041f\u043e\u0442\u044b\u043a\u0430\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u043e\u0441\u0442\u043c\u0430\u043d, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u043b\u043e\u0441\u044c \u0432 \u0431\u0430\u0437\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e DBeaver:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/2g\/ou\/dk\/2goudkcrqww4ct3v4t_dbdj_vj0.png\" alt=\"\u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u0431\u0430\u0437\u0435\"><\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e! \u0412 \u0431\u0430\u0437\u0435 \u0435\u0441\u0442\u044c, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/qs\/cd\/vg\/qscdvgw3qtudywugxklusckrtsq.png\" alt=\"\u0420\u0430\u0431\u043e\u0447\u0435\u0435 fullstack \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\"><\/p>\n<p>  <\/p>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e! \u041c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 fullstack \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>  <\/p>\n<p>P.S. \u0421\u0440\u0430\u0437\u0443 \u043f\u043e\u044f\u0441\u043d\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0412\u043c\u0435\u0441\u0442\u043e Ng-Zorro \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u0434\u0440\u0443\u0433\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 Angular Material. \u041c\u043d\u0435 \u043e\u043d\u0430 \u043b\u0438\u0447\u043d\u043e \u043d\u0435 \u0437\u0430\u0448\u043b\u0430 \u0438\u0437-\u0437\u0430 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438;<\/li>\n<li>\u042f \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430 \u0431\u044d\u043a\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0430 \u043d\u0435 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0434\u0435\u0440\u0433\u0430\u0442\u044c \u0431\u0430\u0437\u0443 \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0435\u0448\u0438\u0432 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b &quot;\u0432\u043b\u043e\u0431&quot; \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c MVP \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u0430 \u043d\u0435 \u043f\u0440\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b;<\/li>\n<li>\u0412\u043c\u0435\u0441\u0442\u043e \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435 <a href=\"http:\/\/localhost:4200\/api\" rel=\"nofollow\">http:\/\/localhost:4200\/api<\/a> \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043b\u0443\u0447\u0448\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0441\u0435\u043f\u0442\u043e\u0440 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043e\u0442\u043a\u0443\u0434\u0430 \u043c\u044b \u0441\u0442\u0443\u0447\u0438\u043c\u0441\u044f<\/li>\n<\/ul>\n<p>  <\/p>\n<h4 id=\"poleznye-ssylki\">\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438:<\/h4>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/ng.ant.design\/docs\/introduce\/en\" rel=\"nofollow\">\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 NG-Zorro<\/a><\/li>\n<li><a href=\"https:\/\/angular.io\/\" rel=\"nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f Angular<\/a><\/li>\n<li><a href=\"https:\/\/docs.nestjs.com\/\" rel=\"nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f NestJS<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Murz1k\/angular-nestjs-starter\" rel=\"nofollow\">\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/li>\n<\/ul>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/514380\/\"> https:\/\/habr.com\/ru\/post\/514380\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/514380\/\">\n<h5 id=\"privet-habr\">\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!<\/h5>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d-\u043c\u043e\u043d\u043e\u043b\u0438\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0431\u0440\u0430\u0442\u044c \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443 \u043d\u043e\u0432\u043e\u0433\u043e fullstack \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u043a \u0441\u043a\u0435\u043b\u0435\u0442 \u0434\u043b\u044f \u043d\u0430\u0432\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430.<\/p>\n<p>  <\/p>\n<h4 id=\"eta-statya-budet-polezna-esli-vy\">\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430, \u0435\u0441\u043b\u0438 \u0432\u044b:<\/h4>\n<p>  <\/p>\n<ul>\n<li>\u041d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0439\u00a0 fullstack-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a;<\/li>\n<li>\u0421\u0442\u0430\u0440\u0442\u0430\u043f\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0438\u0448\u0435\u0442 MVP \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0433\u0438\u043f\u043e\u0442\u0435\u0437\u0443.<br \/>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-308219","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/308219","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=308219"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/308219\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=308219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=308219"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=308219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}